Symfony QueryBuilder count request returns "array" - symfony

I'm trying to make a count request on an id field.
I have the following code in my controller:
$qb = $em->createQueryBuilder();
$qb->select('count(c.id)')
->from('MyBundle:Category', 'c')
->where('c.author = :aut')
->setParameter('aut', $author);
$result = $qb->getQuery()->getResult();
return $this->render('MyCategoryBundle:Category:categories.html.twig', array(
'categories' => $categories,
'result' => $result
));
And in my view.html.twig :
{% for category in categories %}
<li>
{{ category.title }}
{% for total in result %}
{{ total }}
{% endfor %}
</li>
{% endfor %}
It returns the category title and the string "Array" just besides. What am I doing wrong ?

The getResult() returns an array (collection) of objects. You have to use the getSingleScalarResult() function in order to get the result as a simple number.
Anyway, what is the goal of your code? If you want to display the number of categories for each author, your code may not work since you display a list of categories but you only count the categories from one author.

Try this:
$qb = $em->createQueryBuilder();
$qb->select('count(c.id) AS cnt')
->from('MyBundle:Category', 'c')
->where('c.author = :aut')
->setParameter('aut', $author);
$result = $qb->getQuery()->getResult();
and then in twig {{result.cnt}}

Related

Get subfield in flexible content layout

Seems that I can't get the value out off the field “overview_title” on line 29. which is a subfield of the “overview_layout”.
JSON: https://pastebin.com/BLBb6cjx.
I can get the “overview_layout” field. but its subfields won't return anything. anyone?
What I'm trying to do is to get the values of those 3 custom fields. But I get nothing.
This is what i'm trying in Timber:
$post = new Timber\Post();
$context['post'] = $post;
$context['layout'] = get_field('cancer_type_layout');
$context['overview'] = array (
'title' => get_field('overview_title'),
'text' => get_field('overview_text'),
'image' => get_field('overview_picture')
);
Timber::render('templates/pages/template-cancer.twig', $context);```
When you work with Flexible Content fields in Timber, you mustn’t access subfields by more calls to get_field(). All data of the subfields is already there when you get the data with the name of the Flexible Content field.
$post = new Timber\Post();
$context['post'] = $post;
// Everything you need will be in block.
$context['block'] = $post->meta( 'cancer_type_layout' );
Timber::render( 'templates/pages/template-cancer.twig', $context );
In Twig, you can then access your data directly from the block variable:
{% if 'overview_layout' === block.acf_fc_layout %}
{{ block.overview_title }}
{{ block.overview_text }}
{{ block.overview_picture }}
{% endif %}

Displaying Wordpress custom post type by first letter with Timber (twig)

I use Timber for Wordpress and I would like to create a dictionary system like that :
https://wordpress.stackexchange.com/questions/119163/displaying-custom-post-type-by-first-letter-through-custom-taxonomy
I wrote this :
lexique.php
$query = get_posts(array('post_type' => 'lexique','posts_per_page' => -1));
But I don't know how to transform this with Timber :
$by_letter = array();
while( $query->have_posts() ) { $query->the_post();
global $post;
$letter = substr($post->post_name, 0, 1);
if ( ! isset($by_letter[$letter]) ) $by_letter[$letter] = array();
$by_letter[$letter][] = $post;
}
wp_reset_postdata();
It’s a good idea to get all posts at once. By adding the orderby parameter, you can already put them into the correct order for the letter-sorting. I’d use title and not name for the sorting and to define the first letter, because name/post_name is a URL-safe string (used in permalinks) might be different from the actual title of the post.
You get the posts through Timber::get_posts(), so that you don’t have to rely on The Loop. You get an array with posts that you can work with, before you render it through a Twig file. This is much more direct than the method you linked to, because you don’t have to rely on additional functions and query resets.
lexique.php
$posts = Timber::get_posts( array(
'post_type' => 'lexique',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
) );
$posts_by_letter = array();
// Sort posts by letter
foreach ( $posts as $post ) {
$first_letter = substr( $post->post_title, 0, 1);
// Create array for letter if it doesn’t exist
if ( ! isset( $posts_by_letter[ $first_letter ] ) ) {
$posts_by_letter[ $first_letter ] = array();
}
$posts_by_letter[ $first_letter ][] = $post;
}
$context['posts_by_letter'] = $posts_by_letter;
Timber::render( [ 'lexique.twig' ], $context );
Display only letters for existing posts
lexique.twig
<dl>
{% for letter, posts in posts_by_letter %}
<dt>{{ letter }}</dt>
{% for post in posts %}
<dd>{{ post.title }}</dd>
{% endfor %}
{% endfor %}
</dl>
Because you have a nested array, you have to do two for-loops. The first loop goes through the letters (which are the keys of the outer array). The value assigned to a letter key is another array, containing all the posts starting with that letter. To display the post titles as links, you use the second for-loop.
Display all letters from A to Z
If you want to generate a list of all letters from A to Z and display existing posts, you can use range and check if posts exists for that letter in posts_by_letter.
Additionally you can use range to create a list of anchor links that lets a visitor jump to a specific letter.
lexique.twig
{# Anchor links to jump to letter #}
{% for letter in range('A', 'Z') %}
{{ letter }}
{% endfor %}
<dl>
{% for letter in range('A', 'Z') %}
<dt><a id="{{ letter }}">{{ letter }}</a></dt>
{% if posts_by_letter[letter] is defined %}
{% for post in posts_by_letter[letter] %}
<dd>{{ post.title }}</dd>
{% endfor %}
{% endif %}
{% endfor %}
</dl>

How to pass another entity info into form in Symfony2?

What is best practice to include another info in form from another entity?
I have Student Entity, Group Entity, StudentsGroup and Attendance Entity.
Student have id, code, and name.
Group have id and name.
StudentsGroup have id, group_id, and student_id.
Attendance have id, students_group_id, date and status.
Group can have many Student which saved in StudentsGroup. Why I make StudentsGroup? Because actually 1 Group can have some sub groups like SubjectsGroup etc. And Attendance save student information by StudentsGroup Id which same student can have different students_group_id.
Now, the problem is : How to show Student information in collection form of attendance?
All Entity relationship is declared as object, so actually we can access em freely from any entity. But I don't know how to do that in form. Here my form :
<?php
/* Collection Form */
$tanggal = new \DateTime($request->request->get('sifo_adminbundle_studentsgrouping')['tanggal']);
$attendances = new StudentsGrouping();
foreach ($entities as $temp) {
$entity = new Attendance();
$entity = $em->getRepository('SifoAdminBundle:Attendance')->findOneBy(array('studentsGrouping' => $temp, 'date' => $tanggal));
if ($entity){
$attendances->getAttendances()->add($entity);
}
}
$form = $this->createCollectionForm($attendances, $id, $tanggal);
return $this->render('SifoAdminBundle:DftAbsensi:manage.html.twig', array(
'form' => $form->createView(),
));
This is how I render it in twig :
{{ form_start(form_collection) }}
{{ form_row(form_collection.tanggal) }}
{% for attendance in form_collection.attendances %}
{{ form_row(attendance.status) }}
{% endfor %}
{{ form_end(form_collection) }}
## Concept ##
I'm thinking about creating entity and pass it into form like this :
foreach ($entities as $temp) {
$entity = new Student();
$entity = $em->getRepository('SifoAdminBundle:Student')->find($temp->getId());
if ($entity){
$entities[i] = $entity;
}
$i++
}
and then in twig show it like this :
{{ form_start(form_collection) }}
{{ form_row(form_collection.tanggal) }}
{% for key, attendance in form_collection.attendances %}
{{ entities[key].code }}
{{ entities[key].name }}
{{ form_row(attendance.status) }}
{% endfor %}
{{ form_end(form_collection) }}
But I feel not comfort with this. Am I really need to make new entity just for showing name and code from Student Entity? Is there a best practice to do this?
You can use entity field.
$builder->add('users', 'entity', array(
'class' => 'AcmeHelloBundle:User',
'multiple' => true, /* you can choose more than one */
'mapped' => false, /* if you are using the form with an entity */
'query_builder' => function(EntityRepository $er) {
/* use query builder to get correct results */
return $er->createQueryBuilder('u')->orderBy('u.username', 'ASC');
},
));
There are two important keys in above.
'multiple' => true ----- you can able to choose more than one
'mapped' => false ----- if you are using form with an entity, your form will automatically looks for a connection between these entities and if can not found, throws exception. to avoid of that problem you should set this option to false
http://symfony.com/doc/current/reference/forms/types/entity.html

How to display with datetime condition in controller symfony2

i need to display the list of users where they registred after fixed date for example i need to replay the list of users after 2014-03-01 17:34:04 and the the custom 's type in my table User is datetime.
$user = $em->getRepository('UserUserBundle:user')->findBy();
Here is an example of query to get the users after a chosen datetime (assuming that the field containing the datetime is named datetime):
public function yourControllerAction()
{
$dt = new \Datetime('2014-03-01 17:34:04');
$qb = $this->getDoctrine()
->getRepository('UserUserBundle:user')
->createQueryBuilder('u');
$users = $qb
->where(
$qb->expr()->gte('u.datetime',
$qb->expr()->literal($dt->format('Y-m-d H:i:s'))
)
)
->getQuery()
->getResult()
;
return $this->render(
'UserUserBundle:Default:index.html.twig',
array(
'users' => $users
)
);
}
I don't know if it's the best way by calling literal() but it works for me.
Then you'll have to display the users in your Twig template:
{% for user in users %}
{% user.id %}
...
{% endfor %}

Symfony2 & Twig : display all fields and keys

I have a problem with Symfony2 and Twig: I don't know how to display all fields of my entity which is loaded dynamically. Here is my code (displays nothing!!)
Controller :
public function detailAction($id)
{
$em = $this->container->get('doctrine')->getEntityManager();
$node = 'testEntity'
$Attributes = $em->getRepository('TestBetaBundle:'.$node)->findOneById($id);
return $this->container->get('templating')->renderResponse('TestBetaBundle:test:detail.html.twig',
array(
'attributes' => $Attributes
));
}
detail.html.twig :
{% for key in attributes %}
<p>{{ value }} : {{ key }}</p>
{% endfor %}
Don't settle for just the public properties! Get the private/protected as well!
public function detailAction($id){
$em = $this->container->get('doctrine')->getEntityManager();
$node = 'testEntity'
$Attributes = $em->getRepository('TestBetaBundle:'.$node)->findOneById($id);
// Must be a (FQCN) Fully Qualified ClassName !!!
$MetaData = $em->getClassMetadata('Test\Beta\Bundle\Entity\'. $node);
$fields = array();
foreach ($MetaData->fieldNames as $value) {
$fields[$value] = $Attributes->{'get'.ucfirst($value)}();
}
return $this->container
->get('templating')
->renderResponse('TestBetaBundle:test:detail.html.twig',
array(
'attributes' => $fields
));
}
OK. What you are trying to do cannot be done with a Twig for loop over your attributes object. Let me try to explain:
The Twig for loop iterates over an ARRAY of objects, running the inside of the loop for each of the objects in the array. In your case, $attributes is NOT an array, it is an OBJECT which you retrived with your findOneById call. So the for loop finds that this is not an array and does not run the inside of the loop, not even once, that is why you get no output.
The solution proposed by #thecatontheflat does not work either, as it is just the same iteration over an array, only that you have access to both the keys and values of the array, but since $attributes is not an array, nothing is accomplished.
What you need to do is pass the template an array with the properties of the $Attributes object. You can use the php get_object_vars() function for this. Do something like:
$properties = get_object_vars ($Attributes);
return $this->container->get('templating')->renderResponse('TestBetaBundle:test:detail.html.twig',
array(
'attributes' => $Attributes
'properties' => $properties
));
And in the Twig template:
{% for key, value in properties %}
<p>{{ value }} : {{ key }}</p>
{% endfor %}
Take into account that this will only show the public properties of your object.
For Symfony3
$em = $this->getDoctrine()->getEntityManager();
$MetaData = $em->getClassMetadata('TestBetaBundle:Node');
$fields = $MetaData->getFieldNames();
return $this->render('test/detail.html.twig', array('fields'=>fields));
You should change it to
{% for key, value in attributes %}
<p>{{ value }} : {{ key }}</p>
{% endfor %}

Resources