June 8, 2016

How to restrict modification to selected properties of an entity while persisting?

Let’s suppose we have an entity class and a generic FormType corresponding to the entity

class Entry {
    protected $start_time;
    protected $end_time;
    protected $confirmed; // Boolean

    // ... Other fields and getters and setters
}

On the CRUD of this entity, you might not want to allow any modification on start_time or end_time if the entity has been confirmed or in the above case when $confirmed === true

Here are couple of ways this can be solved:

  1. Using the EntityManager you can retrieve original data of the entity. $em->getUnitOfWork()->getOriginalEntityData($entity) returns an array with old data of an entity which can be used to reset the data.

    if($form->isSubmitted() && $editForm->isValid()) {
        // The form was submitted
        if($confirmed === true) { // if the entity was confirmed previously
            $oldData = $em->getUnitOfWork()->getOriginalEntityData($entity);
            $entity->setStartTime($oldData['start_time']);
            $entity->setEndTime($oldData['end_time']);
        }
        // After this you can happily persist the data
        $em->persist($entity);
        $em->flush();
    }
    
  2. Using Form Events

    The following is a Symfony 3 Solution, try this solution for Symfony 2.

    class EntityType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            // ....
            // ....
            // Your form fields
    
            $builder->addEventListener(FormEvents::POST_SET_DATA, array($this, 'onPreSetData'));
        }
    
    
        public function onPreSetData(FormEvent $event) {
            /** @var YourEntity $entity */
            $entity = $event->getData();
            $form = $event->getForm();
    
            if($entity instanceof YourEntity) {
                if ($entity->getTimesheetEntry()->getTimeApproved() === true) {
                    $config = $form->get('start_time')->getConfig();
                    $options = $config->getOptions();
                    $options['disabled'] = true;
                    $form->add('start_time', get_class($config->getType()->getInnerType()), $options);
    
                    $config = $form->get('end_time')->getConfig();
                    $options = $config->getOptions();
                    $options['disabled'] = true;
                    $form->add('end_time', get_class($config->getType()->getInnerType()), $options);
                }
            }
    
        }
    }
    
March 31, 2016

Update schema for create longtext field on MySQL data base on symfony

Ehsan’s Question:

I want to update MySQL field from text to longtext using Doctrine schema.

Now my code is like this:

/**
 *@var string
 *@ORMColumn(name="head_fa", type="string", length=1000, nullable=true)
 */
private $head_fa;

/**
 *@var string
 *@ORMColumn(name="head_en", type="string", length=1000, nullable=true)
 */
private $head_en;

/**
 *@var string
 *@ORMColumn(name="body_fa", type="text", length=1000, nullable=true)
 */
private $body_fa;

/**
 *@var string
 *@ORMColumn(name="body_en", type="text", length=1000, nullable=true)
 */
private $body_en;

and the problem is when i change this field to this code

/**
 *@var string
 *@ORMColumn(name="head_fa", type="string", length=1000, nullable=true)
 */
private $head_fa;

/**
 *@var string
 *@ORMColumn(name="head_en", type="string", length=1000, nullable=true)
 */
private $head_en;

/**
 *@var string
 *@ORMColumn(name="body_fa", type="text", nullable=true)
 */
private $body_fa;

/**
 *@var string
 *@ORMColumn(name="body_en", type="text", nullable=true)
 */
private $body_en;

and run “php app/console doctrine:schema:update –force” command on console it said that “Nothing to update – your database is already in sync with the current entity metadata.” How to change this field to longtext on mysql database.

I do the same on different part of the project.
this is the code

/**
 * @ORMColumn(name="body", type="text", nullable=true)
 */
protected $body;

and after executing the “php app/console doctrine:schema:update –force” command on terminal this field is changed to longtext on MySQL database.

If you don’t specify a length parameter, it will automatically the column as LONGTEXT in MySQL.

December 2, 2015

Count Rows in Doctrine QueryBuilder

Acyra’s Question:

I’m using Doctrine’s QueryBuilder to build a query, and I want to get the total count of results from the query.

$repository = $em->getRepository('FooBundle:Foo');

$qb = $repository->createQueryBuilder('n')
        ->where('n.bar = :bar')
        ->setParameter('bar', $bar);

$query = $qb->getQuery();

//this doesn't work
$totalrows = $query->getResult()->count();

I just want to run a count on this query to get the total rows, but not return the actual results. (After this count query, I’m going to further modify the query with maxResults for pagination.)

Something like:

$qb = $entityManager->createQueryBuilder();
$qb->select('count(account.id)');
$qb->from('ZaysoCoreBundle:Account','account');

$count = $qb->getQuery()->getSingleScalarResult();

For people who are using only Doctrine DBAL and not the Doctrine ORM, they will not be able to access the getQuery() method because it doesn’t exists. They need to do something like the following.

$qb = new QueryBuilder($conn);
$count = $qb->select("count(id)")->from($tableName)->execute()->fetchColumn(0);
...

Please fill the form - I will response as fast as I can!