When developing projects on the basis of a new, but already very popular Symfony2 framework, you involuntarily encounter pieces of code that, with minimal changes, or even without them, migrate from one project to another. Having collected several such “pieces” together, I created a ShtumiUsefulBundle, the use of which I want to talk about.
You can find the bundle itself on GitHub:
ShtumiUsefulBundle .
Installing and configuring the bundle is trivial and described in
Reedme . I will not dwell on this question.
Auto-Substitution Form Fields
Symfony2 has a remarkable type of entity field — a field containing a Select drop-down list filled with the records of a specific table. Moreover, after submitting the form, you will receive not the id of the selected record, but the object itself. Very comfortably! Conveniently, while the amount of data in the table does not exceed reasonable limits. But when you have, for example, a user table contains tens of thousands of records and you need to make a user choice in the form, this approach becomes inapplicable. The smart solution in this case would be to use a text field with auto-lookup. ShtumiUsefulBundle allows you to create and flexibly customize such fields.
')

First you need to define in the settings each field with auto substitution (in the example there are two).
//app/config/config.yml
shtumi_useful: autocomplete_entities: users: class: AcmeDemoBundle:User role: ROLE_ADMIN property: email products: class: AcmeDemoBundle:Product role: ROLE_ADMIN search: contains
- class - Doctrine model.
- role - The user role that is required to use the field. By default: IS_AUTHENTICATED_ANONYMOUSLY (available to everyone)
- property - The property of the model that will be used for autosubstitution. By default: title.
- search - Type of search for autosubstitution:
- begins_with - begins with the characters entered (by default)
- ends_with - ends with the entered characters
- contains - contains the entered characters inside
The definition of the field in the settings is necessary so that the hacker does not auto-prompt, say, credit card numbers into the request to the controller. The controller prompts only the values ​​of those fields that are defined in the settings. And only to those users whose roles correspond to those specified in the settings.
Using the field is very simple:
$formBuilder ->add('product', 'shtumi_ajax_autocomplete', array('entity_alias'=>'products'));
This field can also be used as a filter in
SonataAdminBundle (for those who do not know, this is the admin generator in Symfony2 - to be honest, I don’t know how I would live without this bundle ...). For this, the Sale model must contain a user property with a ManyToOne connection to the User model.
If in the model for which filters are added there is no filtered field with a ManyToOne bundle, you should use Callback. Typically there are two such situations. First, you may have a structure for Hotel-> Campaign-> Offer. In this case, of course, it makes no sense to keep the hotel in the offer, since This duplication of information. But filtering the list of campaign offers may be necessary. Secondly, you may want to filter the user table by e-mail using autosubstitution. But the problem is that the e-mail field itself is in the User model, and there can be no talk of ManyToOne communication here.
Using callback in the shtumi_ajax_autocomplete field is not difficult:
Dependent field
Another useful and often necessary field is a drop-down list, the contents of which depend on the value of another field. A typical example is countries and regions. It is necessary to display in the regions field only those regions that correspond to the selected country. ShtumiUsefulBundle provides a one-stop solution for creating similar fields — the dependent_filtered_entity type.

First, as with the previous type, we need to configure the fields used:
//app/config/config.yml
shtumi_useful: dependent_filtered_entities: region_by_country: class: AcmeDemoBundle:Region parent_property: country property: title role: ROLE_USER no_result_msg: 'No regions found for that country' order_property: title order_direction: ASC
- class - Model dependent field.
- role - the role of the user to whom the field will be available. The default is IS_AUTHENTICATED_ANONYMOUSLY to all.
- parent_property is a property of the model containing a link to the main model with a ManyToOne combination.
- property - the property of the model used as text in the dependent drop-down list. Default: title
- no_result_msg - text that will be used in the dependent drop-down list in case the dependent elements are missing in the database. By default: No results were found. This text can be translated in the files messages.lokal.php
- order_property is a property of the model by which data will be sorted in the drop-down list. Default: id
- order_direction - sorting direction:
- ASC - (default)
- DESC
Using the field itself does not pose any difficulty.
$formBuilder ->add('country', 'entity', array('class' => 'AcmeDemoBundle:Country' , 'required' => true , 'empty_value'=> '== Choose country ==')) ->add('region', 'shtumi_dependent_filtered_entity' , array('entity_alias' => 'region_by_country' , 'empty_value'=> '== Choose region ==' , 'parent_field'=>'country'))
parent_field - the name of the main field in this form.
The values ​​of the dependent field are loaded using AJAX. Therefore, it can be used on sufficiently large amounts of data.
As a result, after the user fills out the form, we get the Country object and the Region object.
Work with dates
Symfony2 has a built-in type date. It has several widgets and can look like several drop-down lists for choosing the day, month and year, as well as a simple text field where the date is displayed in a specific format. As a result, you get a DateTime object. Connecting to this field pop-up calendar is not difficult. To do this, you just need to pass the class attribute to the form element, and then set the datepicker for it in the template, having previously connected the jQuery UI, or any other calendar.
Daterange
Less often, but still, it is necessary to choose a date interval in the form. There is no standard simple solution here, so I developed a universal solution for this. In the ShtumiUsefulBundle there is a type shtumi_daterange. This type of field works with objects of the DateRange class, which is defined inside the bundle. DateRange contains the date of the beginning and end of the period, the format of the dates as well as methods for converting an object into a string and back.

Using this type again, you need to start with the settings, where you need to specify the format of dates and the default time interval:
//app/config/config.yml
shtumi_useful: date_range: date_format: d/m/Y default_interval: P30D
For the convenience of creating DateRange objects, a separate service is registered with the ShtumiUsefulBundle.
There are three ways to create a DateRange object:
1. Using the shtumi_daterange service
2. Creating an object directly from the class
use Shtumi\UsefulBundle\Model\DateRange; ... $date_format = 'Ym-d'; $dateRange3 = new DateRange($date_format); $dateRange3->createToDate(new \DateTime(), 'P3D');
3. By parsing a string containing a date range.
use Shtumi\UsefulBundle\Model\DateRange; ... $dateRange4 = new DateRange('m/d/Y'); $dateRange4->parseData('03/27/2012 - 04/05/2012');
The DateRange object itself, as already mentioned, contains two main properties - the date of the start of the dateStart and the end of the dateEnd interval. These properties are objects of the DateTime system class.
echo $dateRange->dateEnd->format('dmY');
Using the same type of the field of the form shtumi_daterange is again simple and intuitive:
$formBuilder ->add('point1', "shtumi_daterange", array('required'=>false , 'default'=>$dateRange1))
Additional DQL functions
Everyone knows that Symfony2 uses ORM Doctrine, which has its own DQL query language. DQL syntax is very similar to SQL, but does not have all the functions that MySQL has. I often have to use the IFNULL, ROUND and DATE_DIFF functions, which are not included in the standard Doctrine package.
ShtumiUsefulBundle adds the ability to use these functions with the same syntax as in MySQL to DQL.
To use additional DQL functions, you just need to add them to the Doctrine configuration:
doctrine: ... orm: entity_managers: default: dql: datetime_functions: datediff: Shtumi\UsefulBundle\DQL\DateDiff numeric_functions: ifnull: Shtumi\UsefulBundle\DQL\IfNull round: Shtumi\UsefulBundle\DQL\Round
Conclusion
Of course, the global task presented by the bundle does not solve. But still a few minor problems that arise before the developers on the symphony were solved and made my life easier to work on several projects. I hope my work will seem interesting to someone else and at least a little easier for him. Naturally, as we continue working with the framework, ShtumiUsefulBundle will be updated with new types of forms, DQL functions, TWIG extensions will be added, etc. While developing this bundle I tried to make solutions universal and easily configurable, I tried to describe everything in detail in the documentation. I would be very happy to hear feedback on its use, criticism, comments and suggestions.