How to update a field in doctrine to set it null - php

I want to set null to a field in doctrine and here is the sentence
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$query = $qb->update('Model\Example', 'u')->set('u.deletedAt', ':deletedAt')
->where("u.id IN (:ids)")->setParameter('deletedAt', null)
->setParameter('ids', $ids)
->getQuery();
$query->execute();
i think that this code should do the job, but im getting this exception
An exception occurred while executing 'UPDATE example SET deleted_at = ?
WHERE (id IN (?)) AND (example.deleted_at IS NULL)' with params
[null, "5,6"]: SQLSTATE[22P02]: Invalid text representation: 7 ERROR:
la sintaxis de entrada no es válida para integer: «5,6»
first of all why doctrine is adding that AND (example.deleted_at IS NULL) am i doing something wrong ?

Your original query looks like it should work. I duplicated and tested with:
$em = $this->getService('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
$qb->update('Cerad\Bundle\PersonBundle\Entity\Person','person');
$qb->set('person.verified',':verified');
$qb->setParameter('verified',null);
$qb->where('person.id IN (:ids)');
$qb->setParameter('ids',array(1,2,3));
echo $qb->getQuery()->getSql(); // UPDATE persons SET verified = ? WHERE id IN (?)
$qb->getQuery()->execute();
Works as expected.
Are you sure you copy/pasted your exact code? No editing after the fact? Verify your ids array really is an array of integers. That is the only spot I could see where there might be an issue. And do make sure your error is coming from the code you posted. Maybe something else is going on? Try isolating your code in a command object. And of course deletedAt has it's is nullable set to true?
There is no real need to use the expr object for this case. Doctrine 2 correctly handles arrays for IN statements.
====================================
I suspect you have $ids = '5,6'? Try setting it to: $ids = array(5,6); Though even with a string I don't see how it's messing up the query.

When you set the value with PHP null script , it's not understood for doctrine because when transforming to the native sql ,he will not replace null with null value as string , so to resolve , pass the null value as string like
$qb->set('q.deletedAt','NULL');

thanks #Cerad the problem was that i was using the soft-delete extension from StofDoctrineExtensionsBundle and the bundle was adding the soft delete filter, so i just disabled the soft delete filter and now it works as expected,posting the solution many thanks.
$em = $this->getDoctrine()->getManager();
$em->getFilters()->disable('softdeleteable'); // this was the problem when you use the soft delete extension you need to disable the filter if you want to reactivate deleted records
$qb = $em->createQueryBuilder();
$qb->update('Model\Example', 'q');
$qb->set('q.deletedAt',':deletedAt');
$qb->setParameter('deletedAt',null);
$qb->where("q.id IN (:ids)");
$qb->setParameter('ids', $ids);

the problem is that you $ids is a string. you can make:
$arrayOfIds = explode(",", $ids);
and after in you update query:
->setParameter('ids', $arrayOfIds)

Related

From TYPO3 DB wrapper to doctrine. Select Statement

I have to migrate some code from the TYPO3 DB wrapper to Doctrine with the QueryBuilder. In my database are four entries.
The original statement:
$statementToMigrate = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
'job_id,uid,pid,hash',
'tx_test',
'deleted = 0',
null,
null,
null,
'job_id'
);
And my QueryBuilder version:
$table = 'tx_test';
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($table);
$sql = $queryBuilder
->select(
"job_id,uid,pid,hash"
)
->from($table)
->where(
$queryBuilder->expr()->eq('deleted', 0)
)
->execute()
->fetchAll();
The original statement provides me all four entries.
The new version only two. Where are the differences?
And how can I set " $uidIndexField= ''" in doctrine?
Solution:
I added
$queryBuilder
->getRestrictions()
->removeByType(StartTimeRestriction::class)
->removeByType(EndTimeRestriction::class);
and now it works
hi the Querybuilder takes into account the common "restrictions" like start/end date, language, hidden/ deleted. i guess you records are filtered out by some other restrictions.
see here for more about restrictions: https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Database/RestrictionBuilder/Index.html#database-restriction-builder
And how can I set " $uidIndexField= ''" in doctrine?
Doctrine doesn't have such functionality by itself, afaik. Earlier in old Typo3 in the exec_SELECTgetRows method the array was simply traversed to set that index before return. Now it seems you have to do the same on your own. I searched for quite a long time to find good, fast and hopefully native way to achieve that effect with no luck, but finally I stumbled upon that snip:
...
// return $preparedStatement->fetchAll(\PDO::FETCH_ASSOC);
$result = $preparedStatement->fetchAll(\PDO::FETCH_ASSOC);
return array_column($result, null, $uidIndexField);
and finally it looks like that does the trick.

Doctrine-Query IS NOT NULL still returns datasets with NULL column

doctrine/symfony project:
i try to only get results if a reference is set.
so the colum for the relation can be filled with reference ids or it can be null if no reference is "set"... im not able to exclude the actual datasets with a null column
$qb = $this->em->createQueryBuilder();
$qb->select('am', 'lb')->from('MyBundle:Brand', 'am')
->leftJoin('MyBundle:XBuyer', 'lb')
->where('lb.id = am.buyer')
->andWhere('am.buyer IS NOT NULL');
another format i tried
$qb->select('am', 'lb')->from('MyBundle:Brand', 'am')
->leftJoin('MyBundle:XBuyer', 'lb')
->where('lb.id = am.buyer')
->andWhere('am.buyer != :buyer_id_val')
->setParameter('buyer_id_val', '');
also
$qb->select('am', 'lb')->from('MyBundle:Brand', 'am')
->leftJoin('MyBundle:XBuyer', 'lb')
->where('lb.id = am.buyer')
->andWhere($qb->expr()->isNotNull('am.buyer'));
am.buyer is the reference to another table - its actually buyer_id in the brands table
followed by
$data = $qb->getQuery()->execute(null, Query::HYDRATE_SCALAR);
no idea what im doing wrong here
the problem was that i'm still thinking in the context of the database (other projects) but in the case of using doctrine it was necessary to think in the context of an object - more specific if there is an relation between entities.
the actual IS NOT NULL expression wasnt the problem - the problem was the actual leftJoin on an entitiy instead of the relation-"name".
$qb->select('am', 'lb')->from('MyBundle:Brand', 'am')
->leftJoin('am.buyer', 'lb')
->where('am.buyer IS NOT NULL')
->andWhere('lb.id = am.buyer');
thanks guys for all the comments and support in this little timeframe
in my case,
$qb = $this->em->createQueryBuilder();
generated :
Too few arguments to function Doctrine\ORM\EntityRepository::createQueryBuilder()…
I finally wrote:
$qb = $this->em->createQueryBuilder('am');
$qb->select('am')
->leftJoin('am.buyer', 'lb')
->where('lb.id = am.buyer')
->andWhere('am.buyer IS NOT NULL');
->orderBy('am.id', 'ASC')
->setMaxResults(30)
->getQuery()
->getResult()
;
which works fine!
Nota: with Symfony 4.2.3

Symfony JSON output including field name

I'm trying to pull a value from my DB in the field 'action', it is a JSON string however I'm storing it as a single value for now, this is it:
'command'=>'get','target'=>'location'
However when I pull it from the DB it includes the field name, which I don't want, see below:
[{"action":"'command'=>'get','target'=>'location'"}]
My code is here:
$em = $this->getDoctrine()->getManager();
$query = $em->createQueryBuilder();
$q = $query->select('z.action')
->from('AppBundle:ZeusUsers', 'z')
->where('z.id = ?1')
->setParameter(1, $id)
->getQuery();
$action = $q->getResult();
return new Response(json_encode($action));
So I just need to know how to grab the field value not including the field name?
try this method getSingleScalarResult()
but remember that if it wouldn't find anything it will throw exception
http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html#single-scalar-hydration
You want to use getSingleResult() instead of getResult() to get value of your field. It will throw exception if there are no results found or there are more than one result (setMaxResults(1) will remedy this part) though.
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/AbstractQuery.php#L802

Doctrine query builder ~ datetime

I'm trying to create a simple chatbox in symfony2 / doctrine 2.
For testing I'm checking for new messages every 5 seconds, so in my query I try to get all messages by getting all messages with a datetime greater than the current one minus 5 seconds.
I try to do so the following way, but it returns all messages in the database instead of the ones posted in the last 5 seconds
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$qb->select('m')
->from('ChatboxBundle:ChatMessage', 'm')
->where(':new > :last')
->setParameter('new', 'm.postdate' )
->setParameter('last', new \DateTime('-5 second'), \Doctrine\DBAL\Types\Type::DATETIME);
$updatedata = $qb->getQuery()->getResult();
Any ideas on what I'm doing wrong?
m.postdate is a field name and therefore shouldn't be passed in as a parameter. Try this
$qb = $em->createQueryBuilder();
$qb->select('m')
->from('ChatboxBundle:ChatMessage', 'm')
->where('m.postdate > :last')
->setParameter('last', new \DateTime('-5 second'), \Doctrine\DBAL\Types\Type::DATETIME);
$updatedata = $qb->getQuery()->getResult();
Note thats You don't need to use \Doctrine\DBAL\Types\Type::DATETIME
The doc say :
Calling setParameter() automatically infers which type you are setting as value. This works for integers, arrays of strings/integers, DateTime instances and for managed entities. If you want to set a type explicitly you can call the third argument to setParameter() explicitly. It accepts either a PDO type or a DBAL Type name for conversion.

Doctrine ORM, two different querys produce the same result set

I'm using Doctrine 1.2 and Symfony 1.4.
In my action, I have two different query that return different result set. Somehow the second query seem to change the result (or the reference?) of the first one and I don't have any clue why..
Here is an example:
$this->categories = Doctrine_Query::create()
->from('Categorie AS c')
->innerJoin('c.Activite AS a')
->where('a.archive = ?', false)
->execute();
print_r($this->categories->toArray()); // Return $this->categories results, normal behavior.
$this->evil_query = Doctrine_Query::create()
->from('Categorie AS c')
->innerJoin('c.Activite AS a')
->where('a.archive = ?', true)
->execute();
print_r($this->categories->toArray()); // Should be the same as before, but it return $this->evil_query results instead!
Why Doctrine behave this way ? It's totally driving me crazy. Thanks!
To make it simple it seem like the Query 2 are hijacking the Query 1 result.
Use something like this between queries ($em - entity manager):
$em->clear(); // Detaches all objects from Doctrine!
http://docs.doctrine-project.org/en/2.0.x/reference/batch-processing.html
In the API docs for the toArray() method in Doctrine_Collection it says:
Mimics the result of a $query->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
I suspect to answer this question to your satisfaction you're going to have to go through the source code.
This seems like it has to be an issue of $this->categories and $this->evil_query pointing to the same place. What are the results of $this->evil_query === $this->categories and $this->evil_query == $this->categories?
Hubert, have you tried storing the query into a separate variable and then calling the execute() method on it?
I mean something like:
$good_query = Doctrine_Query::create()
->from('...')
->innerJoin('...')
->where('...', false)
;
$evil_query = Doctrine_Query::create()
->from('...')
->innerJoin('...')
->where('...', true)
;
$this->categories = $good_query->execute();
$this->evil_query = $evil_query->execute();
It seems like both attributes (categories and evil_query) are pointing at the same object.
Erm, after both queries you print_r the result of the first query - change the last line to print_r($this->evil_query->toArray()); to see the difference :)

Categories