I have a table "config" with three fields
------------------
id | name | value
------------------
1 | na1 | va1
2 | na2 | va2
3 | na3 | va3
. | ... | ...
I need to fetch the above data to an array "$confData" as given below
$confData ===>
array(
'na1' => 'va1',
'na2' => 'va2',
'na1' => 'va3',
' . ' => '...'
);
I want to know wether there is any predefined function/method in symfony-doctrine to get this array? If it is not available, how can use doctrine way?
There is no such default way. You should build this array manually for fetched object.
//after fetching $objectCollection
$config = array();
foreach ($objectCollection as $object) {
$config[$object->getName()] = $object->getValue();
}
Related
I have DynamoDB records using this structure, category being the partition key:
{ 'category':'1',
'name' : 'wind instruments',
'instruments' : [
{ 'name' : 'oboe',
'count' : 3 },
{ 'name' : 'recorder',
'count' : 2 },
{ 'name' : 'trumpet',
'count' : 2} ]
}
{ 'category':'1',
'name' : 'string instruments',
'instruments' : [
{ 'name' : 'violin',
'count' : 6 },
{ 'name' : 'cello',
'count' : 3 } ]
}
I would like to run the following queries on this DynamoDB table :
how many kinds of instrument do I have ? (answer is 5)
how many instruments do I have in total ? (answer is 16)
By either using :
AWS CLI
PartiQL
Python code
Thanks for your help !
side note: please do not suggest any change in the data model, it's designed like this on purpose (The app reading the instruments inventory per instrument category is the principal access pattern).
DynamoDB does not do these types of queries for you, there is no count or distinct for example. My suggestion is to either have an aggregate table or store aggregate data back to the table. To do this you would use DynamoDB Streams.
----------------------------------------------------------------------------
| pk | sk | instruments | inst_kind | inst_type |
----------------------------------------------------------------------------
| category1 | wind | map of instrumnets | | |
----------------------------------------------------------------------------
| category1 | string | map of instruments | | |
----------------------------------------------------------------------------
| category1 | aggregate | | 5 | 16 |
----------------------------------------------------------------------------
To update the aggregates you use Streams and Lambda and adjust the values each time you modify the item.
To retrieve the aggregates, you simply do a GetItem where PK = "{categoryId}" and SK = "aggreagate"
I already have GSI set to author as partition key and status as a sort key and use them to query the data I need. However, I can't figure out to sort my return data by chronological order.
DynamoDb table
-----------------------------------------------
| id | post | author | status | createdAt |
-----------------------------------------------
| 1 | post1 | author1 | publish | 2019-12-10 |
-----------------------------------------------
| 2 | post2 | author2 | draft | 2019-12-11 |
-----------------------------------------------
| 3 | post3 | author1 | publish | 2019-12-12 |
-----------------------------------------------
and the query
var params = {
TableName : "TABLENAME",
IndexName: "gsi-authorStatus",
KeyConditionExpression: "author = :author AND status = :status",
ExpressionAttributeValues: {
":author": JSON.stringify(event.bodyJSON.author),
":status": JSON.stringify(event.bodyJSON.status)
}
};
dynamo.query(params, function (err, data) {
if (err) {
console.error('Error with ', err);
context.fail(err);
} else {
context.succeed(data);
}
});
My query give me the data where author and status are matching but it give me a data in a random order. It is possible to use createdAt to make the return data order by latest?
Ho to do recursion in cakephp 3.x
I have 4 tables
users
----------
|id|name |
|1 | mick|
----------
responses
-------------------------
id|question_id| response|
1 | 1 | slim |
-------------------------
questions
------------------
id | question |
1 | body type |
-------------------
user_respopnses
----------------------------------------------
id | user_id | question_id | response_id |
1 | 1 | 1 | 1 |
----------------------------------------------
following query is auto generated by Cakephp to fetch data
$users = $this->Users->get($id, [
'contain' => ['Responses' ]
]);
Response by running above query
Id Question Id Response Actions
1 1 slim View Edit Delete
I needs to display question attribute(text) instead of question Id but stuck.
Relation defined in User Table
$this->table('users');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('Responses', [
'foreignKey' => 'user_id',
'targetForeignKey' => 'response_id',
'joinTable' => 'users_responses'
]);
}
after debugging I got this data
'responses' => [
(int) 0 => object(App\Model\Entity\Response) {
'id' => (int) 1,
'question_id' => (int) 1,
'response' => 'slim',
'_joinData' => object(Cake\ORM\Entity) {
'response_id' => (int) 1,
'id' => (int) 1,
'user_id' => (int) 1,
'question_id' => (int) 1,
'[new]' => false,
'[accessible]' => [
'*' => true
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'UsersResponses'
},
Actually, User has relation with Responses table and no association with Questions table, but we can get them from 3rd table "users_responses" as this table has question_id, user_id, reponse_id. but cakephp 3.x does not allow recursion. Right now query hitting Response table and users_response table only. Any suggestion or hint to solve this issue much be appreciated.
Following SQL query to achieve result what I want (I used user_id = 4 static value as It was run on mysqlyog )
SELECT users.id , questions.question, responses.response
FROM questions, responses, users_responses , users
WHERE
users.id = 4 AND
users_responses.user_id = 4 AND users_responses.response_id = responses.id
AND
users_responses.question_id = responses.question_id
AND
responses.question_id = questions.id;
"Recursion" isn't quite the right word here, but what you want is
$users = $this->Users->get($id, [
'contain' => ['Responses' => ['Questions']]
]);
This is pretty clearly described in the Eager Loading Associations portion of the manual.
I'm parsing a big XML file, with many items. Each item has many categories, which can repeat. Here's a sample XML.
<item>
<category>Category1</category>
<category>Category2</category>
<category>Category3</category>
<category>Category4</category>
<category>Category5</category>
</item>
<item>
<category>Category1</category>
<category>Category2</category>
<category>Category3</category>
<category>Category7</category>
<category>Category9</category>
</item>
Using doctrine to handle the many-to-many relationship described above, I have a sample code like this:
$em = $this->getDoctrine()->getEntityManager();
foreach ($items as $item) {
[...]
$categories = ... //Array with category names, parsed from the XML.
foreach ($categories as $category) {
//This will check if the 'item' entity
//already has a category with that name.
$exists = $entity->getCategories()->exists(function($key, $element) use ($category) {
return $category == $element->getName();
});
if (!$exists) {
//If there's already one on the database, we'll load it.
//Otherwise, we'll save a new Category..
$query = $this->_entityManager->createQueryBuilder();
$query->select('c')
->from("MyBundle:Category, 'c');
->where("c.name = :name")
->setParameter("name", $category);
}
$result = $query->getQuery()->getOneOrNullResult();
if ($result != null) {
$item->addCategory($result);
} else {
$categoryEntity = new Category($category);
$em->persist($categoryEntity);
$item->addCategory($categoryEntity);
}
}
}
}
The thing is: I only flush() the entitymanager when I complete looping through all items. Therefore, $query->getQuery()->getOneOrNullResult() always returns null, leading me to create duplicated categories.
In the XML example above, I have the following:
| item |
| 1 |
| 2 |
| category.id, category.name |
| 1, Category1 |
| 2, Category2 |
| 3, Category3 |
| 4, Category4 |
| 5, Category5 |
| 6, Category1 |
| 7, Category2 |
| 8, Category3 |
| 9, Category7 |
| 10, Category9 |
| item | category |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |
| 2 | 6 |
| 2 | 7 |
| 2 | 8 |
| 2 | 9 |
| 2 | 10 |
I wanted the following:
| item |
| 1 |
| 2 |
| category.id, category.name |
| 1, Category1 |
| 2, Category2 |
| 3, Category3 |
| 4, Category4 |
| 5, Category5 |
| 6, Category7 |
| 7, Category9 |
| item | category |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 9 |
| 2 | 10 |
Simply adding $em->flush() after $em->persist($categoryEntity) solves it, but I don't want to flush things just yet (or for that matter, flush only a category). There are a lot of unfinished stuff to do and I don't want to interrupt my transaction. I want to still be able to rollback to the very beginning and exclude all unused categories, if I need to (and, obviously, without running additional queries).
My question is: is there a way to access both the database and doctrine's internal entity mapping to retrieve an entity that might or might not have an ID? Or will I have to create this mapping myself, run a DQL and check on my mapping?
Doctrine2 can't do this for you,
but it's pretty easy to store the newly created categories in your loop and check them when you get a MISS from the database.
$_created_categories = array();
if (!$exists) {
// If there's already one on the database, we'll load it.
// Otherwise, we'll save a new Category..
$query = $this->_entityManager->createQueryBuilder();
$query->select('c')
->from("MyBundle:Category, 'c');
->where("c.name = :name")
->setParameter("name", $category);
$result = $query->getQuery()->getOneOrNullResult();
if ($result) {
$item->addCategory($result);
elseif ( isset($_created_categories[$category]) ) {
$item->addCategory($_created_categories[$category]);
} else {
$categoryEntity = new Category($category);
$em->persist($categoryEntity);
$item->addCategory($categoryEntity);
$_created_categories[$category] = $categoryEntity;
}
}
There is no memory overhead to store the new categories entities in the $_created_categories array as all objects are manipuled by reference in PHP.
I am trying to make a form for adding race results to an event, but cant figure out how to display information from joined tables concatenated together in the options of one select box.
Here is my database structure:
Person Table:
id | name
----------
1 | fred
2 | dave
3 | james
Entrant Table (the code is the entrants race number - the kind of thing you pin to your shirt):
id | code | person_id | category_id
---------------------------------
1 | 210 | 1 | 1
2 | 211 | 2 | 1
3 | 212 | 3 | 1
4 | 156 | 1 | 2
6 | 157 | 3 | 2
Results Table:
id | time | entrant_id
---------------------
1 | 1:20 | 1
2 | 1:35 | 2
3 | 2:02 | 3
Desired Output when adding results to Category=1:
<select>
<option>210 - Fred</option>
<option>211 - Dave</option>
<option>212 - James</option>
</select>
The code I have currently got in my ResultType gets me just the person.name which is a good start (at the expense of 1 extra query per name) but not the entrant.code:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('time')
->add('entrant', 'entity', array(
'class'=>'KP\EventsBundle\Entity\Entrant',
'property' => 'person.name',
));
}
How can I get both the entrant.code and the person.name in the same list of options?
I have only been using Symfony for a couple of weeks, so please be gentle with me.
The simplest way I came up with off the top of my head is to implement the __toString() method in the Entrant class:
public function __toString()
{
return sprintf("%d %s", $this->code, $this->person->getName());
}
Remove the property option from entrant field of the form type to make it use the method.
To solve the extra queries problem, you could do a fetch join in the query_builder option of the entity type.