Hi I like to add a custom function to doctrine.
I need to add a mysql Field function to be able to order by size like here:
mysql custom order by with mixed data types
So I use this as exemple: https://github.com/beberlei/DoctrineExtensions/blob/master/lib/DoctrineExtensions/Query/Mysql/Field.php
and try to add it to Symfony2 like that: http://symfony.com/fr/doc/current/cookbook/doctrine/custom_dql_functions.html
When I do:
$queryBuilder->addOrderBy("FIELD(size, 'XS', 'S', 'M', 'L', 'XL', 'XXL', 'XXXL'), size, length", 'ASC');
I always get the error:
Error: Expected end of string, got '('
Any idea how to implement it?
You cannot use DQL functions within ORDER BY clause. You must select the result of FIELD() function into hidden field and sort results using that field:
SELECT ..., FIELD(size, ...) AS HIDDEN sizeOrder
FROM ...
ORDER BY sizeOrder
sizeOrder field won't affect your results as it won't be even hydrated.
Related
I am using Entity Query to select nodes of two different types say article and page. The fetching seems to be working but now i have to apply sorting to it. Both the content types have different date field say field_date_1 and field_date_2. Now i know i could do this by adding expression$query->addExpression('COALESCE( field_date_1, field_date_2)', 'Date'); in SQL query and sort on $query->sort('Date', 'DESC');
But, addExpression() or adding COALESCE to sort() in Entity Query is throwing Error: Call to undefined method Drupal\Core\Entity\Query\Sql\Query::addExpression()
So, could anyone help me with how to apply sort on more than 2 date fields or how to add an Expression.
This has helped me:
Add tag to the query:
$query->addTag('my_module_tag');
And add expressions in the module file by implementing hook_query_TAG_alter() -
/**
* Implements hook_query_TAG_alter().
*/
function hook_query_my_module_tag_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
$query->addExpression('COALESCE( field_date_1, field_date_2)', 'Date');
}
I have a Symfony3 CRM that implements a form to create an invoice. In this form there is a list of different costs, such as labour, service and materials. I have coded this so it's in a multidimensional array since the user can create any number of fields with whatever they want.
An example of the post array:
[costings] => Array
(
[labour] => 80.30
[materials] => 75.00
[service] => 43.50
....
)
I want to use Doctrine to get the data. To retrieve the costings array, I use this:
$request->request->get('costings');
But I do not know how to get the values within that array. I tried:
$costings->get('labour');
But I get a warning saying I'm trying to call get() on an array. Is there a way to do this or do I need to revert back to just using $_POST?
Simply use this, since you POST costings as normal array.
$costings = $request->request->get('costings');
$labourCostings = $costings['labour'];
Did you try:
$labour = $request->request->get('costings')['labour'];
?
If it doesn't work, try to dump the result of $request->request->get('costings')
I'm trying to make a custom request in my repository with a WHERE clause inside an array field. I tried something like that, not working, but can better show my problem :
$qb ->andWhere( "p.addresses[:index] = :address" )
->setParameter( "index" , $p_idLang )
->setParameter( "address" , $p_address );
Extracted from the documentation about array type:
Maps and converts array data based on PHP serialization. If you need
to store an exact representation of your array data, you should
consider using this type as it uses serialization to represent an
exact copy of your array as string in the database. Values retrieved
from the database are always converted to PHP’s array type using
deserialization or null if no data is present.
Your query doesn't make sense. You have a few options though:
Retrieve p.adresses and check using php if p.adresses[$index] = $address
Try something much less reliable but that could work:
$val_length = strlen($p_address);
$qb ->andWhere( "p.addresses LIKE :indexAddress" )
->setParameter( "indexAddress" , "%i:$p_idLang;s:$val_length:$p_address%" );
Create a new entity and a relation oneToMany between this entity and the new one.
I'd definetely try option 3. Option 1 isn't an option if the array is big or will become big in the future. I wouldn't go for option 2, but as an experiment could be worth trying.
I'm new with Symfony2 and I built successfully my first join through QueryBuilder and Doctrine 2.
Probably this is a stupid question but both on-line and in the Symfony2's methods I was unable to find anything for understanding the difference between the join clauses "WITH" and "ON".
For example this is my join code:
->leftJoin('EcommerceProductBundle:ProductData', 'pdata', 'WITH', 'prod.id = IDENTITY(pdata.product)')
It works good but if I put ON instead of WITH I get the following error:
[Syntax Error] line 0, col 200: Error: Expected
Doctrine\ORM\Query\Lexer::T_WITH, got 'ON'
Why? I've seen among the objects that there are both the T_ON and T_WITH like join clauses, but which is their usage difference? What is their uses like?
#florian gave you the correct answer but let me try to explain it on example:
In sql, joins are done like this:
SELECT * FROM category
LEFT JOIN product ON product.category_id = category.id
(or something like this)
Now in Doctrine, you don't need to use ON clause because doctrine knows that from relations annotations in your entities. So above example would be:
// CategoryRepository.php
public function getCategoriesAndJoinProducts()
{
return $this->createQueryBuilder("o")
->leftJoin("o.products", "p")->addSelect("p")
->getQuery()->getResult() ;
}
Both would fetch all categories and join products associated with them.
Now comes the WITH clause. If you want to join only products with price bigger than 50, you would do this in SQL:
SELECT * FROM category
LEFT JOIN product ON product.category_id = category.id AND product.price>50
In Doctrine:
// CategoryRepository.php
public function getCategoriesAndJoinProductsWithPriceBiggerThan($price)
{
return $this->createQueryBuilder("o")
->leftJoin("o.products", "p", "WITH", "p.price>:price")
->setParameter("price", price)->addSelect("p")
->getQuery()->getResult() ;
}
So, in reality you should never, ever use ON if you are using Doctrine. If you have a need for something like that, you can be almost sure that you screwed something else.
In theory, ON permits you to give the full join criterias, while WITH permits to add additional criterias to the default ones (IMHO).
But, what DQL permits is to avoid giving the JOIN criterias:
You just have to say: $qb->leftJoin('prod.pdata', 'pdata');
And doctrine2 will handle the join correctly.
Here is a related question about that: Can I use "ON" keyword in DQL or do I need to use Native Query?
I'm trying to join a table that has no association defined in my config file. Why? Because I don't want to pollute this entity (Section) because many other entity can be related to this one with a "Many to One" relation. So, I define the relation only on one side, so it doesn't pollute my Section entity.
What I'm trying to do is :
// Find all sections with this bundle linked
$query = $this->getEntityManager()->getRepository('CompanyBackendSectionBundle:Section')->createQueryBuilder('s')
->select('s', 'st')
->innerJoin('s.translations', 'st')
->innerJoin('s.sectionBundles', 'sb')
->innerJoin('Company\Backend\FaqBundle\Entity\FaqQuestion', 'fq')
->where('st.locale = :locale')
->andWhere('sb.bundle = :bundleId')
->orderBy('st.name')
->setParameters(array(
'locale' => $this->getLocale(),
'bundleId' => $bundle->getId()
));
The problem is with "->innerJoin('Company\Backend\FaqBundle\Entity\FaqQuestion', 'fq')", I got :
[Semantical Error] line 0, col 179 near 'fq WHERE st.locale': Error: Identification Variable Company\Backend\FaqBundle\Entity\FaqQuestion used in join path expression but was not defined before.
Is there a way to do it other than using Doctrine Native Query?
No. Doctrine Query Language needs you to define the relation in the direction you wanna use it...