In a Doctrine repository class, the following code produces the following result:
$rsm = new ResultSetMapping;
$rsm->addEntityResult($this->_entityName, 'g');
$rsm->addFieldResult('g', 'geonameid', 'id');
$nativeQuery = $this->_em->createNativeQuery(
"SELECT g.geonameid FROM mydb.geoname g WHERE g.geonameid = 2998268",
$rsm
);
$r = $nativeQuery->getResult();
Debug::dump($r);
Result:
array(1) {
[0]=>
object(stdClass)#461 (20) {
["__CLASS__"]=>
string(40) "My\Bundle\Entity\Geonames\Geoname"
["id"]=>
int(2998268)
["name"]=>
NULL
["asciiname"]=>
NULL
["latitude"]=>
NULL
["longitude"]=>
NULL
["fclass"]=>
NULL
["fcode"]=>
NULL
["countryCode"]=>
NULL
["cc2"]=>
NULL
["admin1Code"]=>
NULL
["admin2Code"]=>
NULL
["admin3Code"]=>
NULL
["admin4Code"]=>
NULL
["population"]=>
NULL
["elevation"]=>
NULL
["gtopo30"]=>
NULL
["timezone"]=>
NULL
["moddate"]=>
NULL
}
}
This (almost) empty object is a correct result. It's what I expect to get. However, If I prepend the code with a $test = $this->find(2998268);, my $nativequery result is not empty anymore:
array(1) {
[0]=>
object(stdClass)#424 (20) {
["__CLASS__"]=>
string(40) "My\Bundle\Entity\Geonames\Geoname"
["id"]=>
int(2998268)
["name"]=>
string(8) "Limousin"
["asciiname"]=>
string(8) "Limousin"
["latitude"]=>
string(10) "45.7666700"
["longitude"]=>
string(9) "1.7000000"
["fclass"]=>
string(1) "A"
["fcode"]=>
string(4) "ADM1"
["countryCode"]=>
string(2) "FR"
["cc2"]=>
string(0) ""
["admin1Code"]=>
string(2) "B1"
["admin2Code"]=>
string(0) ""
["admin3Code"]=>
string(0) ""
["admin4Code"]=>
string(0) ""
["population"]=>
int(737001)
["elevation"]=>
int(0)
["gtopo30"]=>
int(534)
["timezone"]=>
string(12) "Europe/Paris"
["moddate"]=>
string(8) "DateTime"
}
}
I highly suspect that my $nativequery now fetches the object from some cache (which I did not set up), but I don't want it to. I still want the same result as if I hadn't called find() before.
How can I do?
I tried the following:
$r = $nativeQuery
->setCacheMode(Cache::MODE_GET)
->setCacheable(true)
->getResult();
But I get an error message saying Call to undefined method Doctrine\ORM\NativeQuery::setCacheMode().
I also tried to set $nativeQuery->useResultCache(false) but with no effect.
I'm using the following versions of Doctrine components:
doctrine/annotations v1.2.6
doctrine/cache v1.4.1
doctrine/collections v1.3.0
doctrine/common v2.5.0
doctrine/dbal v2.5.1
doctrine/doctrine-bundle v1.5.0
doctrine/doctrine-cache-bundle v1.0.1
doctrine/inflector v1.0.1
doctrine/instantiator 1.0.5
doctrine/lexer v1.0.1
doctrine/orm v2.4.7
My guess is that when you call $this->find(2998268);, Doctrine loads the full entity. Then when you call the NativeQuery, the EntityManager finds that is is already managing the exact same entity with the same id, and returns the already hydrated entity. If you call EntityManager->clear() in between find() and your NativeQuery, you should get your expected result.
Create a new instance of EntityManager. Then, merge the entity into this new EntityManager. After that, call clear method, to "enforce loading objects from database".
/**
* #var \Doctrine\ORM\Configuration
*/
$config = $em->getConfiguration();
/**
* #var \Doctrine\DBAL\Connection
*/
$connection = $em->getConnection();
/**
* #var \Doctrine\ORM\EntityManager $em
*/
$em = $this->getEntityManager()
->create($connection, $config);
$entityClass = get_class($entity);
$em->merge($entity);
$em->clear($entityClass);
$oldEntity = $em->find($entityClass, $entity->getId());
Related
My method:
public function getUpdatedColumns(Shop $shop): array
{
$uow = $this->entityManager->getUnitOfWork();
$uow->computeChangeSets();
return $uow->getEntityChangeSet($shop);
}
What I get is this:
array(1) {
["mailConfig"]=>
array(2) {
[0]=>
string(25) "{"transport": "sendgrid"}"
[1]=>
string(24) "{"transport":"sendgrid"}"
}
}
and because of this whitespace, getEntityChangeSet returns result when the field is not actually updated. Is there a workaround when we are working with JSON ? The database field is JSON as well if that matters.
I'm trying to use partials on an entity which contains a ManyToOne or OneToMany relation.
My DQL looks like this:
SELECT partial a.{created, updated} , partial b.{id, value, entity} FROM App\Entity\DataSetting a INNER JOIN a.fileEntityValues b
The problem is that "partial b" has a property called "entity" which is another field with relation defined like this.
/**
* #ORM\ManyToOne(targetEntity="App\Entity\FileEntity")
* #ORM\JoinColumn(name="file_entity_id", referencedColumnName="id")
*/
private $entity;
But when i execute the previous query I don't get errors but the "entity" field is just not displayed in the result:
[0]=>
array(9) {
["id"]=>
int(36)
["created"]=>
object(DateTime)#3022 (3) {
["date"]=>
string(26) "2020-12-31 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
["updated"]=>
object(DateTime)#3021 (3) {
["date"]=>
string(26) "2020-12-31 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
["fileEntityValues"]=>
array(4) {
[0]=>
array(2) {
["id"]=>
int(72)
["value"]=>
string(4) "1112"
// WHY entity field not displayed
}
[1]=>
array(2) {
["id"]=>
int(73)
["value"]=>
string(4) "1111"
}
WHY ?
#claudio how did you print the debug output?
see, if you used dump(), or var_dump(), fileEntityValues.entities should be an ArrayCollection()
I guess you dumped an object serialization, excluding in some way fileEntityValues.entity
can you:
paste how you printed the debug
paste both entities, or at least the constructors
paste the result of dump($entity)
hint: don't use partials, they are in some way discouraged also by Doctrine and can lead to incoherent behaviors
I'm trying to create a query using the LIKE clause in Doctrine Query Language.
My query is as following:
public function findByName($keyword){
$em = $this->getEntityManager();
$consulta = $em->createQuery('SELECT o FROM AppBundle:Items o WHERE o.name LIKE :keyword');
$consulta->setParameter('keyword', '%'.$keyword.'%');
return $consulta->getResult();
}
I'm getting the next errors:
Notice: Trying to access array offset on value of type null
While if I do the same query but instead of LIKE i simply use =, the query executes correctly and I get the results. What could I be doing wrong here?
Thanks for the help.
Debug info:
object(Doctrine\ORM\Query)#901 (24) {
["_state":"Doctrine\ORM\Query":private]=> int(2)
["_parsedTypes":"Doctrine\ORM\Query":private]=> array(0) { }
["_dql":"Doctrine\ORM\Query":private]=> string(57) "SELECT o FROM
AppBundle:Coche o WHERE o.modelo = :keyword"
["_parserResult":"Doctrine\ORM\Query":private]=> NULL
["_firstResult":"Doctrine\ORM\Query":private]=> NULL
["_maxResults":"Doctrine\ORM\Query":private]=> NULL
["_queryCache":"Doctrine\ORM\Query":private]=> NULL
["_expireQueryCache":"Doctrine\ORM\Query":private]=> bool(false)
["_queryCacheTTL":"Doctrine\ORM\Query":private]=> NULL
["_useQueryCache":"Doctrine\ORM\Query":private]=> bool(true)
["parameters":protected]=>
object(Doctrine\Common\Collections\ArrayCollection)#946 (1) {
["elements":"Doctrine\Common\Collections\ArrayCollection":private]=>
array(1) { [0]=> object(Doctrine\ORM\Query\Parameter)#913 (3) {
["name":"Doctrine\ORM\Query\Parameter":private]=> string(7) "keyword"
["value":"Doctrine\ORM\Query\Parameter":private]=> int(1)
["type":"Doctrine\ORM\Query\Parameter":private]=> string(7) "integer"
} } } ["_resultSetMapping":protected]=> NULL ["_em":protected]=>
object(Doctrine\ORM\EntityManager)#740 (11) {
["config":"Doctrine\ORM\EntityManager":private]=>
object(Doctrine\ORM\Configuration)#564 (1) {
["_attributes":protected]=> array(14) { ["entityNamespaces"]=>
array(1) { ["AppBundle"]=> string(16) "AppBundle\Entity" }
["metadataCacheImpl"]=> object(Doctrine\Common\Cache\ArrayCache)#566
(6) { ["data":"Doctrine\Common\Cache\ArrayCache":private]=> array(0) {
} ["hitsCount":"Doctrine\Common\Cache\ArrayCache":private]=> int(0)
["missesCount":"Doctrine\Common\Cache\ArrayCache":private]=> int(0)
["upTime":"Doctrine\Common\Cache\ArrayCache":private]=>
int(1598445780)
["namespace":"Doctrine\Common\Cache\CacheProvider":private]=>
string(79)
"sf_orm_default_061d80f6e71229c042b639f23634872f7045193d957ba060c640bf0458feeae2"
["namespaceVersion":"Doctrine\Common\Cache\CacheProvider":private]=>
NULL } ["queryCacheImpl"]=>
public function LikeExpression()
{
$stringExpr = $this->StringExpression();
$not = false;
if ($this->lexer->isNextToken(Lexer::T_NOT)) {
$this->match(Lexer::T_NOT);
$not = true;
}
$this->match(Lexer::T_LIKE);
if ($this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
$this->match(Lexer::T_INPUT_PARAMETER);
$stringPattern = new AST\InputParameter($this->lexer->token['value']);
} else {
$stringPattern = $this->StringPrimary();
}
$escapeChar = null;
//////// Highlighted error area//////////
if ($this->lexer->lookahead['type'] === Lexer::T_ESCAPE) {
$this->match(Lexer::T_ESCAPE);
$this->match(Lexer::T_STRING);
$escapeChar = new AST\Literal(AST\Literal::STRING, $this->lexer->token['value']);
}
////////////////////////////////////////
$likeExpr = new AST\LikeExpression($stringExpr, $stringPattern, $escapeChar);
$likeExpr->not = $not;
return $likeExpr;
}
Since PHP 7.1, they introduced const visibility, and I need to read it thorugh reflection. I went as far as creating my ReflectionClass like this:
$rc = new ReflectionClass(static::class);
The function getConstants() returns a name/value map and getConstant($name) just its value. Both doesn't return visibility information. Shouldn't there be a ReflectionConst class similarly to functions, properties, etc.?
Is there any other way to obtain this information?
Reflection changes for this are touched on in the feature's RFC, though I don't know if they've been documented elsewhere yet.
The new class is ReflectionClassConstant with relevant methods (among others):
isPublic()
isPrivate()
isProtected()
ReflectionClass has two new methods:
getReflectionConstants() - returns an array of ReflectionClassConstants
getReflectionConstant() - retrieves a ReflectionClassConstant by name
Example:
class Foo
{
private const BAR = 42;
}
$r = new ReflectionClass(Foo::class);
var_dump(
$r->getReflectionConstants(),
$r->getReflectionConstant('BAR')->isPrivate()
);
Outputs:
array(1) {
[0]=>
object(ReflectionClassConstant)#2 (2) {
["name"]=>
string(3) "BAR"
["class"]=>
string(3) "Foo"
}
}
bool(true)
Running a test which has this line:
$authorizeForm = $crawler->selectButton('Authorize')->form();
outputs this error:
There was 1 error:
1) Citiqa\ApiBundle\Tests\Controller\SecurityControllerTest::testLoginAndAuthorize
InvalidArgumentException: The current node list is empty.
/home/oris/src/citiqa-api/vendor/symfony/symfony/src/Symfony/Component/DomCrawler/Crawler.php:648
/home/oris/src/citiqa-api/src/Citiqa/ApiBundle/Tests/Controller/SecurityControllerTest.php:28
I've taken a look at Crawler.php and saw the problematic function:
public function form(array $values = null, $method = null)
{
//var_dump($this);
if (!count($this)) {
throw new \InvalidArgumentException('The current node list is empty.');
}
$form = new Form($this->getNode(0), $this->uri, $method);
if (null !== $values) {
$form->setValues($values);
}
return $form;
}
$this is in this case the crawler object which extends \SplObjectStorage which implements the Countable interface, so we should be fine. I've tried to var_dump($this); on form() and I see this:
object(Symfony\Component\DomCrawler\Crawler)#1354 (2) {
["uri":"Symfony\Component\DomCrawler\Crawler":private]=>
string(37) "https://localhost/oauth/v2/auth_login"
["storage":"SplObjectStorage":private]=>
array(1) {
["0000000075b694bd000000002b32afe0"]=>
array(2) {
["obj"]=>
object(DOMElement)#529 (18) {
["tagName"]=>
string(6) "button"
["schemaTypeInfo"]=>
NULL
["nodeName"]=>
string(6) "button"
["nodeValue"]=>
string(5) "login"
["nodeType"]=>
int(1)
["parentNode"]=>
string(22) "(object value omitted)"
["childNodes"]=>
string(22) "(object value omitted)"
["firstChild"]=>
string(22) "(object value omitted)"
["lastChild"]=>
string(22) "(object value omitted)"
["previousSibling"]=>
string(22) "(object value omitted)"
["nextSibling"]=>
string(22) "(object value omitted)"
["attributes"]=>
string(22) "(object value omitted)"
["ownerDocument"]=>
string(22) "(object value omitted)"
["namespaceURI"]=>
NULL
["prefix"]=>
string(0) ""
["localName"]=>
string(6) "button"
["baseURI"]=>
NULL
["textContent"]=>
string(5) "login"
}
["inf"]=>
NULL
}
}
}
object(Symfony\Component\DomCrawler\Crawler)#1852 (2) {
["uri":"Symfony\Component\DomCrawler\Crawler":private]=>
string(155) "https://localhost/oauth/v2/auth?client_id=1_5ndcb2XXXXX&redirect_uri=http%3A%2F%2Fwww.google.com&response_type=token"
["storage":"SplObjectStorage":private]=>
array(0) {
}
}
phpunit version is 3.6.10
Funny thing is, this test is completing successfully on another machine, with a different phpunit version (3.7.21). could this be a version / error reporting level issue?