Twig - Merge associative array deep - multidimensional-array

I'm trying to use merge function in Twig to add a new key : value element deep in an associative array. The key/value item I want to push is this deep
element['something']['another_thing']
In ['another_thing'] there are other keys with other values.
I want to add this new key/value it gives
element['something']['another_thing']['new_key'] = 'new_value'
I'm doing this in twig :
{% set array = array|merge({'new_key': 'new_value'}) %}
I don't get the syntax to add this key/value to 'another_thing' key.
My code is doing that right now :
element['new_key'] = 'new_value';

Related

Getting values of a POST multi-dimensional array with doctrine

I have a Symfony3 CRM that implements a form to create an invoice. In this form there is a list of different costs, such as labour, service and materials. I have coded this so it's in a multidimensional array since the user can create any number of fields with whatever they want.
An example of the post array:
[costings] => Array
(
[labour] => 80.30
[materials] => 75.00
[service] => 43.50
....
)
I want to use Doctrine to get the data. To retrieve the costings array, I use this:
$request->request->get('costings');
But I do not know how to get the values within that array. I tried:
$costings->get('labour');
But I get a warning saying I'm trying to call get() on an array. Is there a way to do this or do I need to revert back to just using $_POST?
Simply use this, since you POST costings as normal array.
$costings = $request->request->get('costings');
$labourCostings = $costings['labour'];
Did you try:
$labour = $request->request->get('costings')['labour'];
?
If it doesn't work, try to dump the result of $request->request->get('costings')

Symfony, OneTwoMany, first child element in twig

Product and Image are two entities linked by a oneToMany association (one product has many images). I try to enumerate with TWIG each product with the first image (filename fied) like this :
class ProductRepository extends EntityRepository
{
public function getProductsWithImages() {
$query = $this->createQueryBuilder('e')
->leftJoin('e.images', 'i', 'with', 'i.order = :order')
->setParameter('order' , 0)
->select('e')
->addSelect('i');
return $query->getQuery()->getResult();
}
}
But I got this error :
Method "filename" for object "\entity\product" does not exist.
I understand why (product entity has no image field). What is the best pratice to get only one child element without add a reference on the parent (like a mainImage field) ?
As the doctrine documentation explains :
A one-to-many association has to be bidirectional, unless you are
using an additional join-table. This is necessary, because of the
foreign key in a one-to-many association being defined on the “many”
side. Doctrine needs a many-to-one association that defines the
mapping of this foreign key.
I have this kind of relation in my current project and I simply defined bidirectional one-to-many association. So in your twig view you should be able to do for example :
{# first Image linked to the Product #}
{{ product.images.first }}
The attribute images is an ArrayCollection.
Hope it helps

How to transform a collection of entities to form elements indexed by their IDs?

I'm having trouble rendering a collection of entity IDs as form elements using a simple transformer.
In the main form's buildForm method I have this for the things collection:
$collection = $builder->create( 'things', 'collection' );
$collection->addModelTransformer( new EntityTransformer );
$builder->add( $collection );
In the EntityTransformer I ensure the form receives scalars indexed by the entities' primary keys:
public function transform( $entities ){
$scalars = array();
foreach( $entities as $entity ){
$scalars[ $entity->getId() ] = (string) $entity;
}
return $scalars;
}
I am now expecting to see form elements with names corresponding to the entity IDs, like "form[things][998]", "form[things][999]" etc.. But instead the entity ID keys are ignored and the elements become zero-indexed "form[things][0]", "form[things][1]" etc..
It doesn't matter what type of form elements I use, or what I assign as the scalar values of the array, it is the associative mapping which gets lost in all cases.
I know there are other ways to achieve entity mapping, but I want to understand why this approach doesn't work.
My question is simply, why is the collection field ignoring the keys defined by the transformer and reindexing the collection?

How can I select count(field) and still get an object with createQueryBuilder

I want to access a query result in twig as a whole object. In the query however, I want to select just several fields from the tables + count. In my example I have a company, which is owned by an owner and has several employees. I want to create a query, which gives me a list of companies ordered by count of their employees.
$qb = $this->createQueryBuilder('c');
$qb->select('count(e.id), partial c.{id, name}, partial o.{id, name}');
$qb->leftJoin('c.employees', 'e');
$qb->innerJoin('c.owner', 'o');
$qb->groupBy('c.id');
The query works fine, however I get an error, when I want to access other objects liked with normaly in the company entity (there is an collection of image entities, and each image entity contains the path to the image). The query does not load the whole company entity with its dependencies... I cannot acces the "firstImage" method, which returns the first image from the collection. I get this error
Key "firstImage" for array with keys "0, 1" does not exist in
MyBundle:List:results.html.twig at line 6
Note that leaving out the "employees count" makes it whole work.
$qb = $this->createQueryBuilder('c');
$qb->select('partial c.{id, name}, partial o.{id, name}');
$qb->leftJoin('c.employees', 'e');
$qb->innerJoin('c.owner', 'o');
$qb->groupBy('c.id');
Your object will be the first element of result array and the count() value will be the second. You can access to object properties and methods in twig by the following way:
{{ object[0].firstImage }}
{{ object[0].name }}
And the count of employees can be accessed as:
{{ object[1] }}
Also you may define the name for your count() value in the query
$qb->select('count(e.id) AS empQty, partial c.{id, name}, partial o.{id, name}');
and then you can access this value in twig as:
{{ object['empQty'] }}

Best way to filter a relationship from a twig template

in my Symfony2 project, I've two entities: Spot and Weather, with a one-to-many relationship "weatherReports" between the two entities.
Some weather reports are outdated, so I would like do create an "activeWeatherRecords" method to filter the Weather entities in a Spot entity.
Unfortunately, I can't see how to do this. The idea is not to fetch objects from the controller since the Spot objects are favorited, linked to an User object and accessed directly from a twig template.
So here is the question: What's the best way to filter a relationship directly from a twig template?
UPDATE 09/11/2013
I managed to filter my relationship with a filtering method on my relationship.
In my spot entity, I declared a getActiveWeatherRecords() method:
public function getActiveWeatherReports()
{
// Date
$date = new \DateTime(date('Y-m-d 12:00:00', time()));
// Criteria
$criteria = Criteria::create()
->where(Criteria::expr()->gte("date", $date))
->orderBy(array("date" => Criteria::ASC))
;
return $this->weatherReports->matching($criteria);
}
And I can call this method from a twig template as simply as follow:
[...]
{% for weatherReport in spot.activeWeatherReports %}
[...]
{% endfor %}
[...]
One way is to create a finder method that fetches only active records. You could put that method in a Doctrine repository, call it from your controller (or the Service Layer) and pass it to your template.
Another way is to add a filtering method right to your entity. This way you don't have to call a separate method and pass the result to a template — the entity you pass to the entity will be enough.

Resources