Symfony Entity Type, No lazy load - php

I created a symfony entity form-type and used a QueryBuilder to get the entities.
My Querybuilder looks like this:
$qb = $this
->em
->getRepository('Namespace\Entity\Domain\Nic')
->createQueryBuilder('domainNic')
->join('domainNic.article', 'article')
->andWhere('article.category = :domainCategory')
->setParameter('domainCategory', Article::CATEGORY_DOMAINS)
->orderBy('article.title');
My form type definition below looks like this:
$builder->add(
'withTld',
'bootstrap_collection',
array(
'allow_add' => true,
'allow_delete' => true,
'add_button_text' => 'addtext',
'delete_button_text' => 'deletetext',
'type' => 'entity',
'sub_widget_col' => 5,
'label' => '***',
'options' => array(
'class' => 'Namespace\Entity\Domain\NIC',
'query_builder' => $qb,
'property' => 'title'
)
)
);
The result looks exactly as expected, but for every found record, Symfony doesn't use the data from the QueryBuilder. Instead, Symfony fetches the title for each record again.
Anybody knows a solution? I want Symfony to use the data from the QueryBuilder.

You will need an extra select line in you query builder:
$qb = $this
->em
->getRepository('Namespace\Entity\Domain\Nic')
->createQueryBuilder('domainNic')
->addSelect('article') // <---------------- THIS
->join('domainNic.article', 'article')
->andWhere('article.category = :domainCategory')
->setParameter('domainCategory', Article::CATEGORY_DOMAINS)
->orderBy('article.title');

Related

How to add a new option to select entity

I'm working on a view with lots of invoices.
Users can filter them by 'Customer', 'Date' and also by 'Referent'.
An invoice is linked to a customer, and a customer can have a 'referent' or not.
So in my 'referent' select list, the default value is 'All' to not filter by 'referent', and the rest is the list of all referents got by QueryBuilder.
Now, I need help to know how can I insert an option 'No Referent' in the select list to get all invoices for which the customer has no referent.
Here is my referent field in my 'InvoiceSearchType':
->add('referent', 'genemu_jqueryselect2_entity', array(
'label' => 'Referent',
'class' => 'GeocalUserBundle:User',
'query_builder' => function (UserRepository $ur) {
return $ur->getEmployesQueryBuilder();
},
'empty_value' => '',
'configs' => array(
'placeholder' => 'All',
'width' => '100%',
'allowClear' => true,
),
'required' => false,
))
Here, my QueryBuilder:
public function getEmployesQueryBuilder()
{
$queryBuilder = $this->createQueryBuilder('u')
->leftJoin('u.groups', 'g')
->where('u.enabled = 1')
->andWhere('g.id NOT IN(1)')
->orderBy('u.nom', 'ASC')
;
return $queryBuilder;
}
And I just display the field like that:
<td class="label">Chargé d'affaire</td>
<td colspan="2">{{ form_widget(form.referent) }}</td>
Thanks in advance ! :)
[SOLVED]
First I added a method which get the result (array) of the query, add another referent and return it:
public function getReferentWithNull()
{
// Get the list of referents
$referents = $this->doctrine->getRepository('GeocalUserBundle:User')->getEmployesQueryBuilder()->getQuery()->getResult();
// Create a new instance
$nobody = new User();
$nobody->setName("No Referent");
// Put it in the array result with the key -1
$referents[-1] = $nobody;
return $referents;
}
Then, I modified my form field type to 'choice' type and call my previous function:
->add('referent', 'genemu_jqueryselect2_choice', array(
'label' => 'Referent',
'choices' => $this->getReferentWithNull(),
'empty_value' => '',
'configs' => array(
'placeholder' => 'All',
'width' => '100%',
'allowClear' => true,
),
'required' => false,
))
Finally, I have my last option 'No Referent' with a key of -1.
Hope that it helps someone :)

default data in sonata_type_model

I work with symfony 2.7 , and I use SonataAdminBundle.
I have 2 entities called (Produit) and (Correspondant) with OneToMany relation, One Produit can have Many Correspondant. in the create form for the (Produit) I have correspondants to add Many (Correspondant), and I like by default add all the Correspondants, for that I tried to do this :
ProduitAdmin
$query = $this->modelManager->getEntityManager(new User())->createQuery("SELECT s FROM UserBundle\Entity\User s WHERE s.type LIKE 'Correspondant'" );
$formMapper
->add('correspondants','sonata_type_model', array(
'class'=>'Devagnos\UserBundle\Entity\User',
'multiple'=> true,
'by_reference' => false,
'label'=>'Correspondants associés',
'data' => function() {
$data = new ArrayCollection();
$r= $query->getResult();
foreach($r as $result) {
$data->add($result->getId());
}
return $data;
},
'query' => $query ),
)
But this does not work,
Someone can help me please ? thanks
You need to set data attribute and put the entities you want to be selected as default.
$selected = ... //fetch entities, e.g. from repository
$formMapper
->add('field', 'sonata_type_model', array(
'your_settings' => '...',
'query' => '...',
'data' => $selected
)
);

Yii CGridView and default values in CDbCriteria

I have simple CGridView, which is not showing me any data at all.
I've logged query built by CDbCriteria and there was some LIKE conditions which uses mysql default field values, so MySQL searches for entries with default values in required fields.
Since I have none entries matching this condidion it returns 0 rows. But the thing is, I don't need these LIKEs. Is there a way to disable it?
Here's the view:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model->search(),
'filter' => $model,
'columns' => array(
array(
'name' => 'name',
'type' => 'raw',
'value' => 'CHtml::encode($data->name)'
),
array(
'name' => 'email',
'type' => 'raw',
'value' => 'CHtml::link(CHtml::encode($data->email), "mailto:".CHtml::encode($data->email))',
),
),
));
Controller:
public function actionUsers() {
$model = new Users();
$this->renderPartial('users',array(
'model' => $model,
));
}
Function Search of model Users:
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'user ASC',
),
'pagination'=>array(
'pageSize'=>5
),
));
And Logged Query:
SELECT * FROM `users` `t` WHERE (((((email LIKE :ycp0) AND (`group` LIKE :ycp1)) AND (gender LIKE :ycp2)) AND (city LIKE :ycp3)) AND (name LIKE :ycp4)) AND (av_url LIKE :ycp5) ORDER BY `t`.`name` LIMIT 5. Bound with :ycp0='%NotSet%', :ycp1='%3%', :ycp2='%Secret%', :ycp3='%NotSet%', :ycp4='%NotSet%', :ycp5='%noav.jpg%'
I am new to Stackoverflow and don't have sufficient reputation to post a comment, otherwise I would have asked that you share more information on how you configure your CDbCriteria object in your $model->search() function.
But, I suspect that you are using partial matches in the compare method, which can be disabled by passing false in the $partialMatch parameter as follows:
$criteria = new CDbCriteria;
$criteria->compare('email', $someValue, false);
Or, since false is the default value, you can simple write:
$criteria->compare('email', $someValue);

Zf2 Form dependent on userId

I want to create a dropdown unique to the users, and found a way to do that, but its not ok with the client.
here is what i`ve done:
public function __construct($name = null, EntityManager $em = null, $userId = null)
{
parent::__construct($name);
$this->setAttribute('method', 'post');
[...]
$this->add(array(
'name' => 'religionId',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => array(
'object_manager' => $this->getEntityManager(),
'target_class' => 'Religions\Entity\Religions',
'property' => 'name',
'disable_inarray_validator' => true,
'by_reference' => false,
'is_method' => true,
'find_method' => array(
'name' => 'findBy',
'params' => array(
'criteria' => array('reUserId' => $userId),
'orderBy' => array('name' => 'ASC'),
),
),
),
'attributes' => array(
'multiple' => false,
'required' => false,
)
));
}
This worked, as i was sending the variable reuserId when initializing the form, using $this->identity()
The client wants to inject the user entity and select from there....
Searched stackoverflow and google, but was not able to find anything...any help please? thanks!
To 'inject' anything in ZF2 you will need to use the ServiceManager and create service factories.
It is therefore important to ensure that you are always creating the form via the ServiceManager.
In a controller for instance:
$form = $this->getServiceLocator()->get('MyModule\Form\FooForm');
Then you would need to 'inject' the user buy creating a factory class or closure.
Module.php
public function getFormElementConfig() {
return array(
'factories' => array(
'MyModule\Form\FooForm' => function($fem) {
$serviceManager = $fem->getServiceLocator();
$entityManager = $serviceManager->get('objectmanager'); // Doctrine object manager
// Load the user
// Example is the zfcUser authentication service, however replace
// this with whatever you use to maintain the users id
$user = $serviceManager->get('zfcuser_auth_service')->getIdentity();
// Inject the user entity into the form constructor
$form = new FooForm($user);
return $form;
},
),
);
}
With that said I think you might need to think about the form dependencies. It seems to me that you do not depend on the user entity - but rather the user's id should be used in a database query that reduces the list of 'Religions'.
You could execute this query and then pass the result (The religion collection) to the form in the same way my example shows how to for the user entity - This would then mean you could use a 'normal' Zend\Form\Element\Select rather than the ObjectSelect - meaning no need to inject the ObjectManager etc.

Customizing layout to sfWidgetFormDoctrineChoice disable checkbox

Good morning,
In Symfony 1.4,
I tried to do what is explained here : Customizing layout to sfWidgetFormDoctrineChoice
But it doesn't work. Instead of adding a thumbnail, I just want to hide the <li> before the input, and in some condition disable/hide the checkbox input but show the label anyway.
When I add the renderer without argument, I get this error :
sfWidgetFormMySelectCheckbox requires the following options: 'choices'.
Here is my formatter code :
class sfWidgetFormMySelectCheckbox extends sfWidgetFormSelectCheckbox
{
public function configure($options = array(), $arguments = array())
{
parent::configure($options, $arguments);
}
protected function formatChoices($name, $value, $choices, $attributes)
{
.....
// new
$inputs[$id] = array(
'input' => sprintf('| test | %s',
$this->renderTag('input', array_merge($baseAttributes, $attributes))
),
'label' => $this->renderContentTag('label', self::escapeOnce($option), array('for' => $id)),
);
}
return call_user_func($this->getOption('formatter'), $this, $inputs);
}
}
And now the form where I call it :
$this->setWidget('aaa', new sfWidgetFormDoctrineChoice(array(
'model' => 'Aaa',
'expanded' => true,
'multiple' => true,
'add_empty' => false,
'query' => $query,
'renderer' => new sfWidgetFormMySelectCheckbox()
)));
Thanks for your help !
According to the docs you have to pass the choices option to the renderer object. Try something like this:
$this->setWidget('aaa', new sfWidgetFormDoctrineChoice(array(
'model' => 'Aaa',
'expanded' => true,
'multiple' => true,
'add_empty' => false,
'query' => $query,
)));
$this->widgetSchema['aaa']->setOption('renderer', new sfWidgetFormMySelectCheckbox(array(
'choices' => new sfCallable(array($this->widgetSchema['aaa'], 'getChoices'))
)));
So basically you want the renderer object get the choices from the parent widget. To do that you have to pass a sfCallable object which takes an array as the first argument in which you pass the instance of your parent widget and the name of the function getChoices.
Remember also that the expanded option is not used when you override the renderer.

Categories