Symfony2 andWhere not working - just leave empty - symfony

I'm trying to build something based on options, and I use a QueryBuilder to make a request with JOIN and ORDER
Here's a simple example of code I could produce :
$query = $this->createQueryBuilder('s')
->leftJoin('s.ville', 'v')
->andWhere('s.name = :name')->setParameter('name', 'test')
->orderBy('s.id');
This lead to an exception... "Expected Literal, got 'ORDER'" 'cause in the final request, the WHERE clause is empty...
Any idea ?

Just do a where ? andWhere mean you have many where in your query :).
(Take care I think you want the name of the 'ville', because of your leftJoin).
$query = $this->createQueryBuilder('s')
->leftJoin('s.ville', 'v')
//v.name ?
->where('s.name = :name')->setParameter('name', 'test')
->orderBy('s.id');

I have the same problem using doctrine/orm < 2.4. In previous versions you had to use where() before an andWhere(). In Doctrine docs from version 2.5 they say:
// NOTE: ->andWhere() can be used directly, without any ->where() before
However, It's fixed in version 2.4.8 too, so you could use that version too.

Related

Doctrine duplicating query results?

I have the following code
$this->em = $this->container->get('doctrine.orm.entity_manager');
$qb = $this->em->getRepository('CoreBundle:ServiceProvider')->createQueryBuilder('c');
$qb->select('count(venue.id) as vencount');
$qb->from('CoreBundle:ServiceProvider','venue');
$count = $qb->getQuery()->getOneOrNullResult()['vencount'];
which is write its returning a number of venues but the problem is that this number is mistaken because in the ServiceProvider table i have only 5 records but this query is returning 25. I tried to add a new record so they are 6 and yes the result was 36.
So I added group by the id and it fixed the issue anyone can tell me why is this happening ?
It's because when you create a query from a repository Doctrine assumes its a select and inject the select and from clausule's for you.
This is the sql you get from using the getRepository method:
SELECT count(i0_.id) AS sclr_0 FROM Entity i1_, Entity i0_
(Note that the entity is twice in the FROM).
Using just:
$qb = $this->em->createQueryBuilder();
$qb->select('count(venue.id) as vencount');
$qb->from('CoreBundle:ServiceProvider','venue');
You get:
SELECT count(i0_.id) AS sclr_0 FROM Entity i0_
Which is probably what you are looking for.
Another alternative is to get it from the repository but clear the sql parts with:
$qb = $this->em->getRepository('CoreBundle:ServiceProvider')->createQueryBuilder('c')->resetDQLParts();
But this way you lost the very purpose of using the repository in the first place.

Parameters in QueryBuilder (Doctrine/Symfony)

I have this code:
$sort = (is_null($sort)) ? 'i.name' : $sort;
$order = (!is_null($order) && $order == 'ASC') ? 'ASC' : 'DESC';
$queryBuilder
->select('s')
->from('Model:Item', 'i')
->where('i.isRemoved = false')
->orderBy(':sort', $order)
->setParameter('sort', $sort);
But I get this error:
[1/2] QueryException: SELECT i FROM Model:Item i WHERE i.isRemoved = false ORDER BY :sort DESC
I must be doing something wrong with the setParameter() call, but I can't figure out what?
Any ideas? Thanks
setParameter() is used to prevent SQL injection attacks, since many WHERE clauses rely on user input.
And this might be the cause of the problem here -- I'm not entirely sure that the ORDER BY clause supports parameter replacement. I may be wrong on that, but your error seems to indicate that either (1) it doesn't support it, or (2) you're getting bad input.
Where exactly are you getting your $sort from? If it's coming from some user input, then you might want to perform the sanitization logic here instead, and just set the resolved value in the orderBy() method.
Consider an example where id and name are actual fields. What happens when someone tries to pass in i.description? The entire SQL would fail. But not if you did something like this:
$sort = (in_array($sort, array('i.id', 'i.name')))
? $sort
: 'i.name';
// Now you've effectively sanitized the value
// i.e. It's *always* going to be either 'i.id' or 'i.name'
// So there's no reason to need something like setParameter()
$queryBuilder
->select('s')
->from('Model:Item', 'i')
->where('i.isRemoved = false')
->orderBy($sort);

Silverstripe 3 query with variable

I have used the following query in Silverstripe 2.x projects:
$obj = DataObject::get_one('Post', "\"URLSegment\" = '$segment'")
Does anyone know how I would replicate this query in the new ORM?
I have tried :
$obj = Post::get()->filter("\"URLSegment\" = '$segment'")
$obj = Post::get()->where("\"URLSegment\" = '$segment'")
And neither appear to work.
Thanks!
The issue you're having is that DataObject::get() will return a collection of objects, whereas DataObject::get_one() will return a single object of the specified class. The Silverstripe 3 equivalent is:
$obj = Post::get()->where("\"URLSegment\" = '$segment'")->First();
With this scenario (as with SS2) you would need to make sure you're explicitly taking care escaping to avoid injection vulnerabilities. However the filter function will now take care of that for you. So what you really want now is:
$obj = Post::get()->filter('URLSegment', $segment)->First();
The related documentation is at: http://doc.silverstripe.org/framework/en/topics/datamodel
DataList::create('Post')->filter(array('URLSegment' => $segment))->First();
will also work.

Doctrine Querybuilder issues in symfony2. Usage questions

Using doctrine for the first time in a project, and I'm having a few issues with the query builder.
First up, in a controller I used the following:
$conn = $this->get('database_connection');
$users = $conn->fetchAll('SELECT * FROM Users');
This worked fine and returns an array of users from my DB.
I then tried to use the query builder to fetch the forenames of all users. By looking at examples i found the following:
$conn = $this->get('database_connection');
$qb = $conn->createQueryBuilder();
$qb->select("forename")
->from("Users", "u")
->where("u.id = :user_id")
->setParameter('user_id', 1);
$query = $qb->getQuery();
$results = $query->getResults();
I get told that the gDoctrine\DBAL\Query\QueryBuilder::getQuery() method is not defined, which I found odd as almost all the examples I found use it.
I did a search and found Doctrine documentation but I'm now confused how to use it at all.
Would someone be kind enough to give me an example of how to use the above to retrieve the forename for the User with id 1. I'm sure that once I have a simple example that work I will be fine from there.
Thanks!
Now Resolved:
After looking at the Documentation (and with help from others), I found the general layout for the queryBuilder is as follows:
$conn = $this->get('database_connection');
$qb = $conn->createQueryBuilder();
$stmt = $qb->select("forename")
->from("Users", "u")
->where("u.id = :user_id")
->setParameter('user_id', 1)
->execute();
$userNames = $stmt->fetchAll();
The general idea being that the execute method returns a Doctrine\DBAL\Driver\Statement, with the parameters set as specified. From this statement you can call one of the various method stated here to get the results from the DB.
Hope this helps someone else who is having problems!
I think you might be confused slightly by the documents on doctrine and using it with symfony. From the error message you are getting a DBAL\Query\QueryBuilder. There is not a method getQuery for that object. You should be able to use the execute method to get the results you want.
Now with that being said the way I would do it is through either a repository class for the Users entity, or I would do
$em = $this->get('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
then do what you were doing before...

Drupal: Return SQL string from db_query

Is it possible to return the actual SQL query as a string from the result of db_query?
Or otherwise take the returned resource ID from db_query and get the SQL string?
Edit:
As an addendum, I recently found out about db_queryd() from the Devel module, which echoes the query passed (as well as execute it). Doesn't return the string as this question asked, but really helpful for copying and pasting a complete query.
I don't think it is. However if you are only doing so for the purpose of debugging you can turn on the devel module and that will show you the queries run.
Actually you could just set the variable 'dev_query' to 1 and then access the global array $queries, but I wouldn't recommend it.
Drupal 7, if debug, you could find at \includes\database\database.inc:
function query($query, array $args = array(), $options = array())
$stmt's queryString
or
print_r($stmt->getQueryString());
If you have D7 but don't have Devel to hand, the following snippet could come in useful — it may not handle every type of placeholder however... it currently wrongly assumes all placeholders are strings (which has been fine for my usage).
function stringify_query( $query ){
$s = preg_replace('/\}|\{/', '', $query->__toString());
$a = $query->arguments();
foreach ( $a as $key => $val ) {
$a[$key] = '\'' . $val . '\'';
}
return strtr($s, $a);
}
It also rudely strips out Drupal's curly braces used to handle table prefixes, if you rely on table prefixes then you should find the correct Drupal function to have them replaced correctly.
I would recommend the use of the devel module. There is a setting devel offers which will show all queries run during the generation of a page at the bottom of the page, with data on query execution time and the function that called db_query(). If you have a general idea of what your query will look like or the function that called it, you could search for it within your browser and you can see what was actually send to the database.
Late answer, but you can often turn
$result = db_query($query, $arg1, $arg2);
quickly into
drupal_set_message(sprintf($query, $arg1, $arg2), "status");
And get what you want.
This doesn't help you if you are using an array as your argument to db_query as sprintf doesn't support that, but is often useful in your debugging toolkit.
For those using Drupal 7.x and the Devel module, the correct function to call to output the built SQL statement to the drupal message area is dpq(). It needs to be passed the query object though. e.g.
// to see the built SQL
$query = db_select('node', 'n')->fields('n');
dpq($query);
// to see the results of the query
$results = $query->execute()->fetchAssoc();
dsm($results);
Hope that can help!
D7 version with devel.
>= PHP 5.4
dpm(str_replace(['{', '}'], '', dpq($query, TRUE)));
< PHP 5.4
dpm(str_replace(array('{', '}'), '', dpq($query, TRUE)));

Resources