Working with Doctrine 2 Dates. Navigating in Symfony 2. And, hopefully, other goodies
Welcome all! And let's make a topic crib on Symfony and Doctrine.
I am an ordinary Siberian developer, the main task in life is to capture the world and make people happier. At Symfony, he made several projects. During development, sometimes there are tasks for which there is absolutely no information on the Internet, or very little and not entirely clear. Therefore, I wanted to create this discussion, where I will show how I solved some of my problems, and you, I hope, will direct me on the right path or join and also share your hacks. This topic is intended for those people who use the above mentioned framework well or its components. And also for those who want to talk about solving certain problems, share their experience with other developers.
Imagine a small personal blog. You need to display navigation for posts grouped by year and month. A very simple task. You create a method in the BlogRepository class, and name it for example getArchiveByMonths (). On the machine, write a code similar to:
And you get an error:
The fact is that Doctrine does not know all the functions for working with a date. So you need to add them. In the official documentation there are a couple of lines on how to add these functions ( Tyts )
Solution: there is a wonderful repository: github.com/simukti/DoctrineExtensions , there we are interested in 2 classes:
Why not use them? We copy them to our bundle, for example, to the Dql folder, change the namespace to
In config.yml add:
After that, our functions will work.
It was unexpected for me that Doctrine is not aware of these features. But you can forgive her for other reasons.
To create navigation I use KnpMenuBundle . Read how to use it on github. So, we read, made our first menu, for example this:
Brought this menu somewhere on the left / right side of the site. And now we need to bring out bread crumbs. And here I do not have a beautiful and wonderful solution, I hope someone will tell me how to do this. In the meantime, I will give my decision.
First we need to find the active menu item. There is no standard method anymore in the Knp bundle. Extend our MenuBuilder:
We have added a method to find the current menu item. Now we need to get it out. To do this, in our view, write:
Here we use a method
That’s probably all. I hope it was useful. Errors, please in PM, because the Chukchi is not a writer, a Chukchi developer. Add your decisions to make the topic even more useful. Thanks for attention.
Introduction
I am an ordinary Siberian developer, the main task in life is to capture the world and make people happier. At Symfony, he made several projects. During development, sometimes there are tasks for which there is absolutely no information on the Internet, or very little and not entirely clear. Therefore, I wanted to create this discussion, where I will show how I solved some of my problems, and you, I hope, will direct me on the right path or join and also share your hacks. This topic is intended for those people who use the above mentioned framework well or its components. And also for those who want to talk about solving certain problems, share their experience with other developers.
Get to the point
Date Functions and Doctrine
Imagine a small personal blog. You need to display navigation for posts grouped by year and month. A very simple task. You create a method in the BlogRepository class, and name it for example getArchiveByMonths (). On the machine, write a code similar to:
$qb = $this->createQueryBuilder('p');
return $qb
->addSelect('MONTHNAME(p.created) as month')
->addSelect('YEAR(p.created) as year')
->addSelect('COUNT(p) as cnt')
->groupBy('month, year')
->orderBy('p.created', 'DESC')
->getQuery()
->getArrayResult();
And you get an error:
Expected known function, got 'MONTHNAME'
The fact is that Doctrine does not know all the functions for working with a date. So you need to add them. In the official documentation there are a couple of lines on how to add these functions ( Tyts )
Solution: there is a wonderful repository: github.com/simukti/DoctrineExtensions , there we are interested in 2 classes:
DoctrineExtensions\Query\Mysql\Month;
DoctrineExtensions\Query\Mysql\Year;
Why not use them? We copy them to our bundle, for example, to the Dql folder, change the namespace to
Acme\BlogBundle\Dql
and rejoice that there is such a wonderful repository. We Monthname
make the function as an example Month
. And according to the link , we have to say doctrine about these functions. In config.yml add:
# Doctrine Configuration
doctrine:
orm:
dql:
datetime_functions:
month: Acme\BlogBundle\Dql\Month
monthname: Acme\BlogBundle\Dql\Monthname
year: Acme\BlogBundle\Dql\Year
After that, our functions will work.
It was unexpected for me that Doctrine is not aware of these features. But you can forgive her for other reasons.
Navigation and breadcrumbs
To create navigation I use KnpMenuBundle . Read how to use it on github. So, we read, made our first menu, for example this:
namespace Acme\BlogBundle\Menu;
use Knp\Menu\FactoryInterface;
use Knp\Menu\MenuItem;
use Symfony\Component\DependencyInjection\ContainerAware;
class Builder extends ContainerAware {
public function mainMenu (FactoryInterface $factory, array $options) {
$menu = $factory->createItem('root');
$request = $this->container->get('request');
$menu
->addChild('Homepage', array(
'route' => 'homepage',
));
$blog = $menu->addChild('Blog', array(
'route' => 'blog'
));
$blog->addChild('BlogView',array(
'route' => 'blog_post_view',
'routeParameters' => array('id' => $request->get('id', 1)),
'display' => false
));
return $menu;
}
Brought this menu somewhere on the left / right side of the site. And now we need to bring out bread crumbs. And here I do not have a beautiful and wonderful solution, I hope someone will tell me how to do this. In the meantime, I will give my decision.
First we need to find the active menu item. There is no standard method anymore in the Knp bundle. Extend our MenuBuilder:
namespace Acme\BlogBundle\Menu;
use Knp\Menu\FactoryInterface;
use Knp\Menu\Iterator\CurrentItemFilterIterator;
use Knp\Menu\Iterator\RecursiveItemIterator;
use Knp\Menu\MenuItem;
use Symfony\Component\DependencyInjection\ContainerAware;
class Builder extends ContainerAware {
public function mainMenu (FactoryInterface $factory, array $options) {
$menu = $factory->createItem('root');
$request = $this->container->get('request');
$menu
->addChild('Homepage', array(
'route' => 'homepage',
));
$blog = $menu->addChild('Blog', array(
'route' => 'blog'
));
$blog->addChild('BlogView',array(
'route' => 'blog_view',
'routeParameters' => array('id' => $request->get('id', 1)),
'display' => false
));
return $menu;
}
public function getCurrentItem (FactoryInterface $factory, array $options) {
$menu = $this->mainMenu($factory, $options);
$matcher = $this->container->get('knp_menu.matcher');
$voter = $this->container->get('knp_menu.voter.router');
$matcher->addVoter($voter);
$treeIterator = new \RecursiveIteratorIterator(
new RecursiveItemIterator(
new \ArrayIterator(array($menu))
),
\RecursiveIteratorIterator::SELF_FIRST
);
$iterator = new CurrentItemFilterIterator($treeIterator, $matcher);
// Set Current as an empty Item in order to avoid exceptions on knp_menu_get
$current = new MenuItem('', $factory);
foreach ($iterator as $item) {
$current = $item;
break;
}
return $current;
}
We have added a method to find the current menu item. Now we need to get it out. To do this, in our view, write:
{% set breadcrumbs = knp_menu_get('AcmeBlogBundle:Builder:getCurrentItem').getBreadcrumbsArray() %}
Here we use a method
getBreadCrumbsArray()
that returns what we need. That’s probably all. I hope it was useful. Errors, please in PM, because the Chukchi is not a writer, a Chukchi developer. Add your decisions to make the topic even more useful. Thanks for attention.