In my Symfony2 app there are users end hotels, for each user it's esay to define his hotels.
In order to list user's hotels I use
class HotelVoter implements VoterInterface
which works fine.
In application there are forms of Order to a Hotel (so order.hotel_id = hotel.id). For this reason there is a field Hotel in Order's form:
$builder->add('hotel', 'entity', array(
'class' => 'AcmeHelloBundle:Hotel',
'property' => 'name',
'query_builder' => ...,
...
));
The problem is that form shows me all existing hotels regardless security voter.
What is the best way to leverage my existing voter. I don't feel like using query_builder for this aim.
Thanks
Related
I am building a backend panel for a website with Laravel Backpack. It is really nice, but I have noticed that relationship queries are very expensive.
I have two models: Product and Center with a many to many relationship between them. In my CenterCrudController I have defined a field this way:
$this->crud->addColumns([
// More fields...
[
'label' => 'Products',
'type' => 'select2_multiple',
'name' => 'products', // the method that defines the relationship in your Model
'entity' => 'products', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => 'App\Models\Product', // foreign key model
'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
],
// More fields...
]);
It works fine, showing a select multiple field with related models. But the query used is SELECT * FROM products, which is highly expensive (table products have thousands of records with about 25 columns).
In this example I only need id and name fields. I am looking for something like Query Builder select() method.
Is there a way for optimizing this type of query?
Thanks in advance!
Not sure if this is actually an answer, but I'll post it anyway.
The best solution (as pointed by #tabacitu) was using select2_from_ajax field. It doesn't slow page load and make an ajax request for retrieving data only when user clicks on the select field.
I'm new to sonata and symfony and I was wondering if there is a way to create a custom query for one of the entities in configureFormFileds()?
I need it to build a rather complex admin view over several entities that are many-to-many related via a single intermediate table in a star-like fashion (many joins). My idea was to build a complex query that fetches all the data and then pass it to my form.
I've also tried to map all these relations in doctrine and fetch them one by one in a series of custom forms, but unfortunately, entities must be checked against each other, so that didn't work.
Yes, you can create custom query for Entity. (example for Doctrine)
->add(
'manager',
EntityType::class,
[
'label' => 'Manager',
'class' => 'MainBundle\Entity\Manager',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('m')
->where('m.username LIKE :username')
->setParameter('username', $this->getConfigurationPool()
->getContainer()
->get('security.token_storage')->getToken()->getUser()->getName()
)
->orderBy('m.id', 'ASC');
},
]
)
How create query - lock at the official documentation .
you need to provide some more information to get a precise answer, but regarding your main question:
I'm new to sonata and symfony and I was wondering if there is a way to
create a custom query for one of the entities in
configureFormFileds()?
I can answer. In general this is possible, yes. Check out the query config parameter of the sonata_type_model or the callback option of the sonata_type_model_autocomplete field type.
I have a problem with hydrating the objects in ZF2.
I have a form for saving either the organization-related info or person-related info into the database. The user makes the choice: save either organization or person. Just 1 form for all html inputs.
In ZF2, I created 2 fieldsets. In each fieldset class, I use setHydrator(new ClassMethods(false)) and setObject(new <objectForHydration>). The 2 fieldsets are included into the form with the following code:
$this->add([
'type' => 'Parties\Form\Fieldsets\RegisterOrganizationFieldset',
'options' => [
'use_as_base_fieldset' => true,
],
]);
$this->add([
'type' => 'Parties\Form\Fieldsets\RegisterPersonFieldset',
'options' => [
'use_as_base_fieldset' => true,
],
]);
I want RegisterOrganizationFieldset to hydrate OrganizationObject, and RegisterPersonFieldset to hydrate PersonObject.
I thought of hydrating both objects at the same time because this won't introduce conditionals into the form class. The problem is the hydration takes place just 1 object depending on which fieldset has use_as_base_fieldset = true. If both fieldsets have use_as_base_fieldset = true, the fieldset later in the code (RegisterPersonFieldset) hydrates only its respective object.
Could you tell how to hydrate both objects? Maybe how to hydrate objects in a better way?
EDIT:
As #jcropp pointed, I use Person and Organization as Parties that are independent entities sharing only Id property.
One way to hydrate two objects at the same time is to make them both the same object.
It is not clear from your question whether 1) a person who is registering is a member of a registering organization, or 2) "parties" are registering, and a party can be either an organization or a person. Here are some answers for both cases:
If persons are members of organizations in your data structure, a method for hydrating both at the same time is to treat the persons data as "collections" of the organization data elements. This method utilizes relationships between the fieldsets to create a single dataset in which both the organization data and the person data can be edited together. See the ZF2 Manual.
If your intent is to register individual parties, and a party can be either an organization or a person, a method for hydrating one or the other in the same form is to use table inheritance. In single table inheritance you would have a single table (and a single fieldset) for both types of parties, and a selection between the person or organization type would indicate whether data should be entered into the organization fields or the person fields of the table. In multiple table inheritance, you would create a party table that related to an organization table and to a person table; and organization and person fieldsets would extend the party fieldset.
I have a database with a simple one-to-many relationship that looks like this:
Tables Company Category
Rows ID ID
Name Name
Category_ID
I have a forms where I can add, edit and delete the company's or category's name, which works fine. Entering the category by ID also works, but is obviously terrible to use. What I want is a simple select element in the form to pick from an existing category.
The code I have to generate the <select> is:
$this->add(array(
'name' => 'Categorie',
'type' => 'Zend\Form\Element\Select',
'attributes' => array(
'options' => $categories,
),
'options' => array(
'label' => 'Categorie',
),
));
From what I could find in the (extremely sparse) ZF2 documentation, I should be using a Hydrator to fetch data into the $categories variable, but I'm not sure where to go from there.
Any sort of example or tips would be well appreciated!
Here's a very good article about forms.
My solution is based on this tutorial and it is (almost) working well. I don't know if you use Doctrine for your project or not, but I think it would be a very good idea!
I also heavily use select elements. In the given fieldset, I generate value options for a select with this piece of code:
$opt= Registry::get('entityManager')->getRepository('My\Entity\Categories')
->getCategoriesForCombobox();
$this->get('category')->setValueOptions($opt);
If you (plan to) use Doctrine, you should read about repositories very carefully in the Doctrine documentation. If you use collections in the form, the topic about associations is also a must read.
In symfony 2.0, how to create a drop down list using one-to-one association in form? Can you guys put good example please?
I will try to answer your question the way I understand it. Let's say I have a Faculty object bound to a single University object. So in the form used to create or edit a faculty, I display a combo box of all the university in the database and the user choose one among them. There is one special Symfony field type that does exactly this: the entity type. Below is the code of the buildForm method that I use in my FacultyType object used to create the faculty form:
// Application\AcmeBundle\Form\Type\FacultyType
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('name');
$builder->add('university', 'entity', array(
// The class of the entity used as a combo box item
'class' => 'AcmeBundle:University',
// The property of the entity displaying the entity as text
'property' => 'name',
// The query builder used to populate the combo box, accepts
// a QueryBuilder object or a \Closure like below
'query_builder' => function(EntityRepository $repository) {
// This will return a query builder selecting all universities
return $repository->createQueryBuilder('u');
}
));
}
Note: There are other properties that can be set for the entity field type, I invite you to take a look at this page for more information on it.
Rendered, this will show a combo box with all the universities I have set in the database. When the user save the form, the university chose is assigned to the faculty object bound to the form via a setter. You could probably render a drop-down list instead of a combo box. If you need to select multiple entities, the 'multiple' option of the field type entity could be useful.
This being said, the example I showed is not a One-to-One relation but rather a Many-to-One for the Faculty object and a One-to-Many for the University object. A One-to-One relation would be something more like a relation where a University has a unique Address. In this case, a combo box wouldn't be useful since the university can only have one adress so a sub-form would be more appropriate. If it has many adresses, then it becomes a One-to-Many relation like the relation between the university and its faculties.
Not sure if this will answer your question correctly but I hope it will lead you to a final solution.
Regards,
Matt
You need to use the entity field type in Symfony2. A good example is found at http://symfony.com/doc/current/reference/forms/types/entity.html