Is there a way in Symfony to convert a string like
VendorBundle:Foo
into a FQCN like
Vendor\Bundle\Entity\Foo
Extra question
How Doctrine handle this? Because I've seen you can do something like (pseudocode)
->leftJoin( ..., ..., 'WITH', 'alias INSTANCE OF VendorBundle:Entity');
My question is due to
$foo = new \Vendor\Bundle\Entity\Foo();
$foo instanceof 'VendorBundle:Foo'; //false
You can use the php keyword ::class PHP.net
In your case, try something like Foo::class
This should output a string like Vendor\Bundle\Entity\Foo. If you see the comments at the link however, this is not guaranteed if you do not include the correct use statement in your code(use Vendor\Bundle\Entity\Foo) in your controller. If you correctly include that, then you can call Foo::class.
With doctrine functions, you can use the syntax you mentioned VendorBundle:Foo like this:
$manager = $this->getDoctrine()->getManager();
$fooRepository = $manager->getRepository('VendorBundle:Foo');
$fooBar = $fooRepository->find($someId);
For your verification, you have to check
$someStringToCheck = Foo::class;
$foo = new \Vendor\Bundle\Entity\Foo();
$foo instanceof $someStringToCheck //true
Oddly, if you do
$foo instanceof Foo::class
It returns an error
But to use VendorBundle:Foo, then take a look at the AbstractManagerRegistry.php in \Doctrine\Common\Persistence\AbstractManagerRegistry, at the function getManagerForClass($class). You can do something in your code like:
$doctrineStyleString = 'VendorBundle:Foo';
if (strpos($doctrineStyleString, ':') !== false)
{
list($namespaceAlias, $simpleClassName) = explode(':', $doctrineStyleString, 2);
$stringWithPath = $this->getDoctrine()->getAliasNamespace($namespaceAlias) . '\\' . $simpleClassName;
}
I took the code from that function and tried it out, so stringWithPath should print you Vendor\Bundle\Entity\Foo
Related
'''
QuestionModel getQuestionModelFromDatasnapshot(
DocumentSnapshot questionSnapshot) {
QuestionModel questionModel = new QuestionModel();
questionModel.question = questionSnapshot.data()'question'];
List<String> options = [
questionSnapshot.data()["option1"],
questionSnapshot.data()["option2"],
questionSnapshot.data()["option3"],
questionSnapshot.data()["option4"]
];
options.shuffle();
questionModel.option1 = options[0];
questionModel.option2 = options[1];
questionModel.option3 = options[2];
questionModel.option4 = options[3];
questionModel.correctOption = questionSnapshot.data()["option1"];
questionModel.answered = false;
print(questionModel.correctOption.toLowerCase());
return questionModel;
}
'''
It looks like you're using dart with null safety on and you are accessing a list or map that might be null. It's hard to tell from your code, but I'm guessing the offending line is
questionModel.correctOption = questionSnapshot.data()["option1"];
It might be one of the other [] calls earlier in your code (such as
questionSnapshot.data()["option1"]), but the solution is the same.
The problem is that questionSnapshot.data() might return null, and the compiler is flagging it.
If you are sure the data is not null, you can use the ! operator, like this:
questionModel.correctOption = questionSnapshot.data()!["option1"];
Another solution is a conditional null-safe operator ?, with a default value. In this case, the code would look like this:
questionModel.correctOption = questionSnapshot.data()?["option1"]??"DefaultValue;
But I would recommend checking if the returned data is null. It's easier for others to read and can be logged more easily:
var data = questionSnapshot.data();
if (data != null) {
questionModel.correctOption = data["option1"];
}
else {
//do something in that case
}
I'v got simple m2m relation (book -> book_mark <- mark). I want to find item(book) by 1-2-3... x-count of tags(marks). Example: Book1 got these tags: [Mark1, Mark2, Mark3], Book2 got these tags: [Mark1, Mark3, Mark4]. Search list is [Mark1, Mark2]. I want to find only items, which have ALL tags from Search list, i.e. only Book1 in this example.
I have tried many ways and spend much time google it, but didn't find the answer.
Closest that I have is this:
return $this->createQueryBuilder('b')
->select('b, m')
->leftJoin('b.marks_list', 'm')
->andWhere(':marks_list MEMBER OF b.marks_list')
->setParameter('marks_list', $marksList)
->getQuery()->getArrayResult();
But it's looking for books which have at least 1of the parameters, not all of them together
Next, I'v decided that I'm absolutely wrong and start thinking this way:
public function findAllByMarksList(array $marksList)
{
$qb = $this->createQueryBuilder('b')
->select('b, m')
->leftJoin('b.marks_list', 'm');
for ($i = 0; $i<count($marksList); $i++){
$qb->andWhere('m.id in (:mark'.$i.')')
->setParameter('mark'.$i, $marksList[$i]);
}
return $qb->getQuery()->getArrayResult();
}
But here I faced another problem: This code is checking only 1 mark and then always returns an empty set if the number of parameters is more than 1.
Best regards.
So, updated answer... It works (I have relation many to many between reviews and brands) it's the same situation, but for example if you have
Book 1 - mark1, mark2, mark3
Book 2 - mark1, mark2, mark3, mark4
with this code you will also find the book2, because all of it marks are in this list.
If you need to find book which haves only these 3 tags, you additionally need to add checking for count. (Count of tags = count of tagList)
public function test()
{
// just selecting for list for test
$brandsList = $this->_em->createQueryBuilder()
->select('b')
->from('ReviewsAdminBundle:Brands', 'b')
->where('b.id in (:brandIds)')
->setParameter('brandIds', [6,4])
->getQuery()
->getResult();
dump($brandsList);
// query part
$qb = $this->createQueryBuilder('r')
->select('r')
->leftJoin('r.brand', 'brands')
->where('r.published = 1');
foreach ($brandsList as $oneBrand) {
/** #var Brands $oneBrand */
$identifier = $oneBrand->getId();
$qb->andWhere(':brand'.$identifier.' MEMBER OF r.brand')
->setParameter('brand'.$identifier, $identifier);
}
dump($qb->getQuery()->getResult());
die;
}
ps. Additionally you can check doctrine2 queryBuilder must return only result matching with array values (ids): 0/Null and/or One and/or Many id(s) have to return One result (close to our situation)
And, I think there's not better way of accomplishing this. Either you use multiple andWheres to compare id OR use MEMBER OF
I'm new to Symfony, and I got an error while running a query :
public function getFilteredArticles($page, $nbPerPage, $data) {
$query = $this->createQueryBuilder('a')
->leftJoin('a.images', 'i')
->addSelect('i')
->leftJoin('a.type_stockage', 't')
->addSelect('t')
->leftJoin('a.famille', 'f')
->addSelect('f');
if ($data['famille'] != '') {
$query->where('f.id = :famille')
->setParameter('famille', $data['famille']);
}
if ($data['rds'] == false) {
$query->where('a.stock_actuel > 0');
}
if ($data['recherche'] != '' && $data['recherche'] != null) {
$query->where('a.ref_article LIKE :recherche')
->setParameter('recherche', '%' . $data['recherche'] . '%');
}
$query->leftJoin('a.sousfamille', 's')
->orderBy('a.ref_article', 'ASC')
->getQuery();
$query->setFirstResult(($page - 1) * $nbPerPage)
->setMaxResults($nbPerPage);
return new Paginator($query, true);
}
This query have conditionnals parameters as you can see, that returns the list of articles I need for a table. But when I run this query to fill my table, I got the error :
An exception has been thrown during the rendering of a template ("Too
many parameters: the query defines 0 parameters and you bound 1").
I don't know why he is expecting 0 parameters. I tried using setParameters instead, but the result is the same.
Does anyone has an idea?
You should use andWhere() methods instead of where().
where() method removes all previous where, but setParameter() does not. That's why he found more parameters than where clauses.
I personally never use where if the condition has no sense to be the first condition, to avoid this kinds of errors.
if ($data['famille'] != '') {
$query->andWhere('f.id = :famille')
->setParameter('famille', $data['famille']);
}
if ($data['rds'] == false) {
$query->andWhere('a.stock_actuel > 0');
}
if ($data['recherche'] != '' && $data['recherche'] != null) {
$query->andWhere('a.ref_article LIKE :recherche')
->setParameter('recherche', '%' . $data['recherche'] . '%');
}
where() php doc
Specifies one or more restrictions to the query result.
Replaces any previously specified restrictions, if any.
andWhere() php doc
Adds one or more restrictions to the query results, forming a logical
conjunction with any previously specified restrictions.
My error, in Symfony 4, using Doctrine 2.6 was
Too many parameters: the query defines 0 parameters and you bound 2
The problem was that I wasn't defining the parameters in andWhere method as
$this->createQueryBuilder('q')
...
->andWhere('q.propertyDate IS NOT NULL') //this also couldn't find anywhere
->andWhere('q.parameterName = :parameterName')
->setParameters(['q.parameterName' => $parameterName, ...2nd parameter])
As I couldn't find any answer to my problem, but was similar to this one, I thought to maybe help someone who is struggling like I was.
also in symfony 5 and 6 you should use andWhere() methods instead of where().
where() method removes all previous where, but setParameter() does not. That's why he found more parameters than where clauses.
I would like to upgrade my symfony 2 project from 2.3 to 2.7 LTS version. I have a problem in a repository to get result of a query. In 2.3, this query give me something :
public function findProtectedPublications( $steps, $start, $end)
{
$query= $this->getEntityManager()
->createQueryBuilder()
->select('d.pubRefs')
->from('ImpressionDemandBundle:Event', 'h')
->innerJoin('h.demand','d')
->where('d.protectedPublications = :pub')
->setParameter('pub', 1 )
->andWhere('h.date >= :start')
->setParameter('start', $start )
->andWhere('h.date <= :end')
->setParameter('end', $end )
->andWhere('h.stepId in (:steps)')
->setParameter('steps', $steps )
->orderBy('d.id','ASC')
->getQuery();
$results = $query->getResult();
$publications = array();
if ($results && ! empty ($results)){
foreach($results as $result){
$pubs = $result['pubRefs'];
if ($pubs && ! empty($pubs)){
foreach($pubs as $pub){
$publications[] = $pub;
}
}
}
}
return $publications;
}
But this code doesn't work in earlier version because $pubs variable in an ArrayCollection. So I changed the end of my code with this :
$results = $query->getResult();
$publications = array();
if ($results && ! empty ($results)){
foreach($results as $result){
$pubs = $result['pubRefs'];
var_dump($pubs);
if (! $pubs->isEmpty()){
$arrayPubs = $pubs->toArray();
foreach($arrayPubs as $pub){
$publications[] = $pub;
}
}
}
}
return $publications;
In this part, when I dump the $pubs variable, I have :
object(Doctrine\Common\Collections\ArrayCollection)#131 (2) {
["elements":"Doctrine\Common\Collections\ArrayCollection":private]=>
NULL
["_elements":"Doctrine\Common\Collections\ArrayCollection":private]=>
array(1) {
[0]=>
object(Impression\DemandBundle\Entity\Publication)#125 (5) {
["editor":"Impression\DemandBundle\Entity\Publication":private]=>
string(24) "Journal Le Monde 4-10-13"
["coauthors":"Impression\DemandBundle\Entity\Publication":private]=>
string(12) "Machin Machin"
["title":"Impression\DemandBundle\Entity\Publication":private]=>
string(57) "La tragédie de Lampedusa: s"émouvoir, comprendre, agir."
["nbPages":"Impression\DemandBundle\Entity\Publication":private]=>
float(1)
["nbCopies":"Impression\DemandBundle\Entity\Publication":private]=>
float(40)
}
}
}
So it seems that there are elements in this ArrayCollection, but the test $pubs->isEmpty() gives a true result, so I have nothing in $publications array.
Edit: In fact, the problem seems to be due to my data in the database : for an object previous from my upgrade, I have something like this in the database :
O:43:"Doctrine\Common\Collections\ArrayCollection":1:{s:54:"Doctrine\Common\Collections\ArrayCollection_elements";a:1:{i:0;O:42:"Impression\DemandBundle\Entity\Publication":5:{s:50:"Impression\DemandBundle\Entity\Publicationeditor";s:5:"BREAL";s:53:"Impression\DemandBundle\Entity\Publicationcoauthors";s:5:"MONOT";s:49:"Impression\DemandBundle\Entity\Publicationtitle";s:18:"USA Canada mexique";s:51:"Impression\DemandBundle\Entity\PublicationnbPages";d:150;s:52:"Impression\DemandBundle\Entity\PublicationnbCopies";d:150;}}}
and this gives the error.
For a object add after my upgrade, I have something like this in the database :
O:43:"Doctrine\Common\Collections\ArrayCollection":1:{s:53:"Doctrine\Common\Collections\ArrayCollectionelements";a:1:{i:0;O:42:"Impression\DemandBundle\Entity\Publication":5:{s:50:"Impression\DemandBundle\Entity\Publicationeditor";s:8:"dfg dfgd";s:53:"Impression\DemandBundle\Entity\Publicationcoauthors";s:7:"dfg dfg";s:49:"Impression\DemandBundle\Entity\Publicationtitle";s:5:"fdg d";s:51:"Impression\DemandBundle\Entity\PublicationnbPages";d:5;s:52:"Impression\DemandBundle\Entity\PublicationnbCopies";d:3;}}}
and the function findProtectedPublications() works without errors.
The difference between the two versions is ArrayCollection_elements for the first and ArrayCollectionelements for the second.
To correct this data, I tried with
UPDATE demand SET pub_refs = REPLACE (pub_refs, "ArrayCollection_elements', 'ArrayCollectionelements')
but this doesn't work because of special chars. Trying with
UPDATE demand SET pub_refs = REPLACE (pub_refs, "ArrayCollection�_elements', 'ArrayCollection�elements')
doesn't work better. How can I correct this data ?
Doctrine can populate results as an Array instead of an ArrayCollection, simply change the getResult() call to:
$results = $query->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
This would be the most efficient way to complete your task however you could also use ArrayCollection's built-in toArray() method to convert its own data to array format:
$publications = $results->toArray();
As the problem seems to be due to a change in the storage of ArrayCollection in database between 2.3 and 2.7 version of symfony, I created an line command to update these in database.
I have this function,
public function getWall(){
$q = $this->createQueryBuilder('f');
$q->leftJoin("f.profilo", 'p');
$q->leftJoin("p.utente", 'u');
$q->where('(f.foto_eliminata IS NULL OR f.foto_eliminata != 1)');
$q->andWhere('p.fase_registrazione = :fase');
$q->andWhere('u.locked = :false');
$q->slice(0, 20);
$q->setParameter(':fase', 100);
$q->setParameter('false', false);
$q->orderBy('f.created_at', 'desc');
$dql = $q->getQuery();
$results = $dql->execute();
return $results;
}
but I get this error,
Call to undefined method Doctrine\ORM\QueryBuilder::slice()
Ok, so, u get this error, cause QueryBuilder has no such method. But Collection has. If u want to use slice, a possible variant is:
use Doctrine\Common\Collections;
public function getWall(){
$result = $this->createQueryBuilder('f')
->leftJoin("f.profilo", 'p')
->leftJoin("p.utente", 'u')
->where('(f.foto_eliminata IS NULL OR f.foto_eliminata != 1)')
->andWhere('p.fase_registrazione = :fase')
->andWhere('u.locked = :false')
->setParameter('fase', 100)
->setParameter('false', false)
->orderBy('f.created_at', 'desc')
->getQuery()
->getResult();
// $result typed as array
return new Collections\ArrayCollection($result))->slice(0,20); // convert array to collection, then slice
}
By the way, it is not a good idea to 'limit' result of the query in a such way.
U can use setMaxResults(20), and not to select all objects at all.
About lazy collections (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/extra-lazy-associations.html): after selecting result objects, u can take some object from result collection: $r = $result[0] after that:
$portfilos = $r->getPortfolio(); // returns for example Collection with some objects;
// its Lazy, without SQL query!
$portfolios->slice(0, 20); // queries first 20 potfolios
To use slice is a rather good idea, if u have lots of objects in some relation.
p.s. sry, mb I didn't recognized your problem, but tried :)
EDITED
fixed errors in code.