Error with subquery in doctrine2 query builder - php

I have this query with a subquery:
$query = $this->getEntityManager()->createQueryBuilder();
$subquery = $query;
$subquery
->select('f.following')
->from('ApiBundle:Follow', 'f')
->where('f.follower = :follower_id')
->setParameter('follower_id', $id)
;
$query
->select('c')
->from('ApiBundle:Chef', 'c')
->where('c.id <> :id')
->setParameter('id', $id)
;
$query
->andWhere(
$query->expr()->notIn('c.id', $subquery->getDQL())
);
return $query->getQuery()->getResult();
And I get this error:
[Semantical Error] line 0, col 116 near 'f, ApiBundle:Chef': Error: 'f' is already defined.
I can't find the cause of the error, the alias f is defined only one time. Any suggestions?

This issue is about objects and references in PHP.
When you do $subquery = $query;, $query being an object, you simply have $subquery pointing to the same value.
A PHP reference is an alias, which allows two different variables to
write to the same value. As of PHP 5, an object variable doesn't
contain the object itself as value anymore. It only contains an object
identifier which allows object accessors to find the actual object.
When an object is [...] assigned to another
variable, the different variables are not aliases: they hold a copy of
the identifier, which points to the same object.
Reference: http://us1.php.net/manual/en/language.oop5.references.php
It means in your code that when you write this:
$subquery
->select('f.following')
->from('ApiBundle:Follow', 'f')
->where('f.follower = :follower_id')
->setParameter('follower_id', $id)
;
This is equivalent to:
$query
->select('f.following')
->from('ApiBundle:Follow', 'f')
->where('f.follower = :follower_id')
->setParameter('follower_id', $id)
;
So when at the end you call:
$query->andWhere(
$query->expr()->notIn('c.id', $subquery->getDQL())
);
You are using 2 times the same object pointed by 2 different variables ($query === $subquery).
To solve this issue, you can either use:
$query = $this->getEntityManager()->createQueryBuilder();
$subquery = $this->getEntityManager()->createQueryBuilder();
Or the clone keyword:
$query = $this->getEntityManager()->createQueryBuilder();
$subquery = clone $query;

I would like to share my solution which requires ORM mapping:
Following entities are mapped like this:
Event 1:M Participant
Participant class
/**
* #ORM\ManyToOne(targetEntity="KKB\TestBundle\Entity\Event", inversedBy="participants")
* #ORM\JoinColumn(name="event_id", referencedColumnName="id", nullable=false)
*/
private $event;
Event class
/**
* #ORM\OneToMany(targetEntity="KKB\TestBundle\Entity\Participant", mappedBy="event", cascade={"persist"})
*/
private $participants;
class EventRepository extends \Doctrine\ORM\EntityRepository
{
public function getEventList($userId)
{
$query = $this->createQueryBuilder('e');
$subquery = $this->createQueryBuilder('se');
$subquery
->leftJoin('se.participants', 'p')
->where('p.user = :userId')
;
return $query->where($query->expr()->notIn('e.id', $subquery->getDQL()))
->setParameter('userId', $userId)
;
}
}

Related

Call to undefined method CI_DB_mysqli_driver::start_group_where() [duplicate]

I want to produce the following SQL code using Active Records in Codeigniter:
WHERE name != 'Joe' AND (age < 69 OR id > 50)
Doing the following seems to be as far as I can get, I cant figure out how to group them
$this->db->select()->from('users')->where('name !=', 'Joe')->where('age <', 69)->or_where('id <', $id);
Any ideas? My SQL query is too complex so I dont wish to rewrite everything in traditional SQL.
UPDATE
My SQL code is dynamically generated depending on the values of certain parameters passed into the model method. The problem with not being able to use parenthesis causes a problem because the operator precedence is such that AND is evaluated first before OR.
*Here is a chunk of my active records code, where there are some other code before and after it:
... some $this->db->where() ...
... some $this->db->where() ...
if($price_range) {
$price_array = explode('.', $price_range);
for($i = 0; $i < count($price_array); $i++) {
if($i == 0) {
$this->db->where('places.price_range', $price_array[$i]);
} else {
$this->db->or_where('places.price_range', $price_array[$i]);
}
}
}
... some $this->db->where() ...
... some $this->db->where() ...
The problem comes because I am using $this->db->or_where() which introduces a OR clause that throws the operator precedence into disarray without being able to use ( ) to change the order.
** Is there any way to solve this? **
In Codeigniter 3.0.3 you can do it simple like this :
$this->db->select()
->from('users')
->where('name !=', 'Joe')
->group_start() // Open bracket
->where('age <', 69)
->or_where('id <', $id)
->group_end(); // Close bracket
Perhaps it can help
You can use one large string.
$this->db->select()->from('users')->where("name != 'Joe' AND (age < 69 OR id > 50)
");
The grouping of where clauses is not in CI by default. You have to extend the core and add in the ability. I have done so by doing something as follows:
class MY_DB_mysql_driver extends CI_DB_mysql_driver
{
public function __construct($params)
{
parent::__construct($params);
}
/**
* This function will allow you to do complex group where clauses in to c and (a AND b) or ( d and e)
* This function is needed as else the where clause will append an automatic AND in front of each where Thus if you wanted to do something
* like a AND ((b AND c) OR (d AND e)) you won't be able to as the where would insert it as a AND (AND (b...)) which is incorrect.
* Usage: start_group_where(key,value)->where(key,value)->close_group_where() or complex queries like
* open_bracket()->start_group_where(key,value)->where(key,value)->close_group_where()
* ->start_group_where(key,value,'','OR')->close_group_where()->close_bracket() would produce AND ((a AND b) OR (d))
* #param $key mixed the table columns prefix.columnname
* #param $value mixed the value of the key
* #param $escape string any escape as per CI
* #param $type the TYPE of query. By default it is set to 'AND'
* #return db object.
*/
function start_group_where($key,$value=NULL,$escape,$type="AND")
{
$this->open_bracket($type);
return parent::_where($key, $value,'',$escape);
}
/**
* Strictly used to have a consistent close function as the start_group_where. This essentially callse the close_bracket() function.
*/
function close_group_where()
{
return $this->close_bracket();
}
/**
* Allows to place a simple ( in a query and prepend it with the $type if needed.
* #param $type string add a ( to a query and prepend it with type. Default is $type.
* #param $return db object.
*/
function open_bracket($type="AND")
{
$this->ar_where[] = $type . " (";
return $this;
}
/**
* Allows to place a simple ) to a query.
*/
function close_bracket()
{
$this->ar_where[] = ")";
return $this;
}
}
Usage:
group_where_start(key,value)->where(key,value)->group_where_close()
or
complex queries like
open_bracket()->start_group_where(key,value)->where(key,value)->close_group_where()->start_group_where(key,value,'','OR')->close_group_where()->close_bracket() would produce AND ((a AND b) OR (d))
CI3 has all you need!
$this->db->select('*')->from('my_table')
->group_start()
->where('a', 'a')
->or_group_start()
->where('b', 'b')
->where('c', 'c')
->group_end()
->group_end()
->where('d', 'd')
->get();
https://www.codeigniter.com/userguide3/database/query_builder.html#query-grouping
What I've done is duplicate the and clause after the where, which is effectively the same as the long string selection.
$this->db->select()
->from('users')
->where('name !=', 'Joe')
->where('age <', 69)
->or_where('id <', $id)
->where('name !=', 'Joe');
The one large string way is probably better.
Solved. Dynamically generate the SQL query and plug it into $this->db->where(). Thanks guys!

Error: 'c' is used outside the scope of its declaration

An application has a page of statistics representing dozens of calculations. To avoid duplicating code in a repository the error
Error: 'c' is used outside the scope of its declaration
occurs when attempting to insert DQL with conditions into a QueryBuilder.
The basic entities include Household and Contact. Calculations are based on contact date range, site (location of contact), and type (type of contact). There is a service that creates an array of where clauses and query parameters, as will be evident in the code below.
I know the calculation works if all the code occurs in a single function. It seems the problem arises from the join with the Contact entity and its necessary constraints. Can DRY be accomplished in this scenario?
All of the following appear in the Household entity's repository.
The DQL is:
private function reportHousehold($criteria)
{
return $this->createQueryBuilder('i')
->select('i.id')
->join('TruckeeProjectmanaBundle:Contact', 'c', 'WITH',
'c.household = i')
->where($criteria['betweenWhereClause'])
->andWhere($criteria['siteWhereClause'])
->andWhere($criteria['contactWhereClause'])
->getDQL()
;
}
Example of $criteria: $criteria['betweenWhereClause'] = 'c.contactDate BETWEEN :startDate AND :endDate'
One of the calculations on Household:
public function res($criteria)
{
$parameters = array_merge(
$criteria['betweenParameters'], $criteria['siteParameters'],
$criteria['startParameters'], $criteria['startParameters'],
$criteria['contactParameters']);
$qb = $this->getEntityManager()->createQueryBuilder();
return $this->getEntityManager()->createQueryBuilder()
->select('h.id, 12*(YEAR(:startDate) - h.arrivalyear) + (MONTH(:startDate) - h.arrivalmonth) Mos')
->from('TruckeeProjectmanaBundle:Household', 'h')
->distinct()
//DQL inserted here:
->where($qb->expr()->in('h.id', $this->reportHousehold($criteria)))
->andWhere($qb->expr()->isNotNull('h.arrivalyear'))
->andWhere($qb->expr()->isNotNull('h.arrivalmonth'))
->andWhere($criteria['startWhereClause'])
->setParameters($parameters)
->getQuery()->getResult()
;
}
You're either missing getRepository() or from()
Try this (my prefered choice) :
private function reportHousehold($criteria) {
return $this->getEntityManager
->createQueryBuilder()
->select("i.id")
->from(YourEntity::class, "i")
->join("TruckeeProjectmanaBundle:Contact", "c", "WITH", "c.household=i.id")
->where($criteria['betweenWhereClause'])
->andWhere($criteria['siteWhereClause'])
->andWhere($criteria['contactWhereClause'])
->getQuery()
->execute();
}
Or this
private function reportHousehold($criteria) {
return $this->getEntityManager
->getRepository(YourEntity::class)
->createQueryBuilder("i")
->select("i.id")
->join("TruckeeProjectmanaBundle:Contact", "c", "WITH", "c.household=i.id")
->where($criteria['betweenWhereClause'])
->andWhere($criteria['siteWhereClause'])
->andWhere($criteria['contactWhereClause'])
->getQuery()
->execute();
}
Careful, I'm assuming you're on Symfony 3 or above.
If not, replace YourEntity::class by Symfony 2 syntax which is "YourBundle:YourEntity"
In a sense Preciel is correct: the solution does require the use of $this->getEntityManager()->createQueryBuilder(). Instead of injecting DQL as a subquery, the trick is to return an array of ids and use the array in an IN clause. The effect is to remove any consideration of entities other than the Household entity from the calculation. Here's the result:
public function res($criteria)
{
$parameters = array_merge($criteria['startParameters'], $criteria['startParameters'], ['hArray' => $this->reportHousehold($criteria)]);
$qb = $this->getEntityManager()->createQueryBuilder();
return $this->getEntityManager()->createQueryBuilder()
->select('h.id, 12*(YEAR(:startDate) - h.arrivalyear) + (MONTH(:startDate) - h.arrivalmonth) Mos')
->from('TruckeeProjectmanaBundle:Household', 'h')
->distinct()
->where('h.id IN (:hArray)')
->andWhere($qb->expr()->isNotNull('h.arrivalyear'))
->andWhere($qb->expr()->isNotNull('h.arrivalmonth'))
->setParameters($parameters)
->getQuery()->getResult()
;
}
private function reportHousehold($criteria)
{
$parameters = array_merge($criteria['betweenParameters'], $criteria['siteParameters'], $criteria['contactParameters']);
return $this->createQueryBuilder('i')
->select('i.id')
->join('TruckeeProjectmanaBundle:Contact', 'c', 'WITH', 'c.household = i')
->where($criteria['betweenWhereClause'])
->andWhere($criteria['siteWhereClause'])
->andWhere($criteria['contactWhereClause'])
->setParameters($parameters)
->getQuery()->getResult()
;
}

Symfony Order entities by field OneToMany

Who knows how to solved this simple question?
I have entity project with field likedUsers and in twig count up this field but I want order projects by this count up (DESC) - first who have more likedUsers. How to do it? In query builder or in twig create filter?Help with doctrine I know count
"likes_user" => count($this->getLikedUsers()->getValues())
how to sort my all projects from this field?
or how its solved with query builder?
something like that, but this is not work:
public function getProjects()
{
$qb = $this->getEntityManager()->createQueryBuilder('d');
$qb
->select('d')
->from('AppBundle:Project', 'd')
->where('d.confirm = :identifier')
->setParameter('identifier', 'approved')
->orderBy('COUNT(d.likedUsers)', 'DESC')
->getQuery()
->getResult()
;
$query = $qb->getQuery();
$results = $query->getResult();
return $results;
}
entity:
/**
* Project
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Entity\ProjectRepository")
*/
class Project implements \JsonSerializable
{
/**
* #var Collection
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\User", mappedBy="likedProjects")
*/
private $likedUsers;
{% for project in projects %}
<div>LIked: <span>{{ project.likedUsers|length|number_format(0, '.', ' ') }}</span></div>
{% endfor %}
I think maybe like that:
{% for project in projects.likedUsers|length|sort %}
but not effect
maybe who knows? How array projects sort by count of field LikedUser. I don’t know how do this. Query builder or twig extension or usort..
IMHO, this seems like a job for PHP instead of Doctrine. Not sure if t could be achieved by Doctrine and, if possible, what would be an impact.
One way to do this is usort().
$projects = ...;
usort($projects, function($p1, $p2){
// Both $p1 and $p2 are instance of Project
// Assuming that `getLikedUsers()` return Doctrine `Collection`...
return count($p1->getLikedUsers()) > count($p2->getLikedUsers());
});
usort takes an array and in each pass offers two items (two projects in your case) for you to decide which one is "greater". In your case, the project with more likes is definitely "greater", right?
Hope this helps...
I solved with query builder. And I add only project who have like user - user live in some city no all city
public function getProject()
{
$qb = $this->getEntityManager()->createQueryBuilder('d');
$qb
->select('d')
->from('AppBundle:Project', 'd')
->addSelect('COUNT(m.id) as nMethods')
->join('d.likedUsers', 'm')
->join('m.location', 'l')
->where('l.city = :identifier')
->setParameter('identifier', 'someCity')
->groupBy('d.id')
->orderBy("nMethods", 'DESC')
->getQuery()
->getResult()
;
$query = $qb->getQuery();
$results = $query->getResult();
return $results;
}

Converting two simple SQL queries into Doctrine

First of all, I want to apologize for the length of this question; I didn't know how to properly ask my question without a lot of background. Please bear with me.
I'm converting a simple application that I use to hone my skills from my own custom database access schema to Doctrine. I chose Doctrine for a number of reasons, not the least of which is that I use it at my day job regularly. I also like how Doctrine is generally a pretty thin (appearing) layer that stays out of the way while still adding a lot of features.
I've converted the data access layer for the users table in my database to Doctrine.
It's very unremarkable (simply getters and setters), except for a few fine details:
I need to have a custom repository for some specific queries and
the User object has a default ArrayCollection instantiated in the constructor
namespace model\entities;
/**
* #Entity(repositoryClass="model\repositories\UserRepository")
* #Table(name="users")
*/
class User{
/* snip variables */
/**
* #OneToOne(targetEntity="Authentication", mappedBy="user", cascade="persist")
*/
private $authentication;
/**
* #OneToMany(targetEntity="Contact", mappedBy="user", cascade="persist")
*/
private $contacts;
public function __construct() {
$this->contacts = new \Doctrine\Common\Collections\ArrayCollection();
}
/* snip getters and setters */
}
In my old schema, I had two custom queries that selected a subset of the users table.
They are:
public function search( $term = null ){
if( !$term ){
$sql = "SELECT *
FROM
" . $this->tableName . "
ORDER BY
lname ASC,
fname ASC";
$res = $this->db->q($sql);
}
else{
$sql = "SELECT *
FROM
" . $this->tableName . "
WHERE
lname LIKE ?
OR fname LIKE ?
OR CONCAT(fname, ' ', lname) LIKE ?
ORDER BY
lname ASC,
fname ASC";
$values = array( '%' . $term . '%', '%' . $term . '%', '%' . $term . '%' );
$res = $this->db->qwv( $sql, $values );
}
return $this->wrap( $res );
}
and:
public function getAllWithRestrictions(){
$sql = "SELECT *
FROM
" . $this->tableName . "
WHERE
userid IN
(
SELECT
userid
FROM
" . $this->uiPre . "authentications
WHERE
resetPassword = 1
OR disabled = 1
)";
$res = $this->db->q( $sql );
return $this->wrap($res);
}
where $this->db is a thin PHP PDO wrapper and $this->wrap does magic with zero/single/multiple rows returned and converting them into data objects.
Now, I figured this would be very easy to convert to Doctrine. In the case of getAllWithRestrictions it's simply a ->where, ->orWhere set, right? I don't know anymore.
I found these Stackoverflow questions that I used to try to construct my queries, but I'm running into error after error, and I'm not sure how far down the rabbit hole I need to go:
SQL Multiple sorting and grouping
Order by multiple columns with Doctrine
Doctrine: Multiple (whereIn OR whereIn) query?
Doctrine - or where?
My custom repository currently looks like this, but I can't say it's even close to correct as I've been fiddling with it for a long time, and it's just a hodge-podge of what I thought might work:
<?php
namespace model\repositories;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr;
class UserRepository extends EntityRepository{
public function search( $term ){
if( !$term ){
return $this
->_em
->createQuery('SELECT u FROM model\entities\User u')
->addOrderBy( 'u.lname' )
->addOrderBy( 'u.fname' )
->getResult();
}
else{
$qb = $this->_em->createQueryBuilder();
$qb ->select(array('u'))
->from('model\entities\User', 'u')
->where( $qb->expr()->like( 'u.lname', '?1' ) )
->orWhere( $qb->expr()->like( 'u.fname', '?2' ) )
->orWhere( $qb->expr()->like( 'CONCAT(u.fname, \' \', u.lname)', '?3' ) )
->addOrderBy( 'u.lname' )
->addOrderBy( 'u.fname' )
->setParameters(
array(
1 => $term,
2 => $term,
3 => $term
)
);
$query = $qb->getQuery();
return $query->getResult();
}
}
public function getAllWithRestrictions(){
$qb = $this->_em->createQueryBuilder();
$qb ->select(array('u'))
->from('model\entities\User', 'u')
->add('where', $qb->expr()->orx(
$qb->expr()->eq('u.disabled', '1'),
$qb->expr()->eq('u.resetPassword', '1')
));
$query = $qb->getQuery();
return $query->getResult();
}
}
EDIT: I just realized that I'm doing the getAllWithRestrictions query on the wrong table (it should be authentications.) In any case, it's the search method causing my issues right now. However, I will also need to know how to do something like $qb->expr()->eq('u.Authentication.disabled = '1') and I have no idea how DQL really works.
The particular error I'm getting right now is
Fatal error: Uncaught exception 'Doctrine\ORM\Query\QueryException' with message 'SELECT u FROM model\entities\User u WHERE u.lname LIKE ?1 OR u.fname LIKE ?2 OR CONCAT(u.fname, ' ', u.lname) LIKE ?3 ORDER BY u.lname ASC, u.fname ASC'
followed by
Doctrine\ORM\Query\QueryException: [Syntax Error] line 0, col 99: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got ','
But I've had a slew of different issues depending on how I construct the DQL/Query Builder.
Again, I expected these two SQL queries to be simple to convert to Doctrine / DQL. I'd like to do this without resorting to raw SQL through Doctrine (as many of the accepted answers I linked suggest). This MUST be easy. Does anyone know how to construct elegant Doctrine queries?
According to the CONCAT function parser in doctrine, it only takes 2 parameters separated by a comma,
//Doctrine/ORM/Query/AST/Functions/ConcatFunction.php
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->firstStringPrimary = $parser->StringPrimary();
$parser->match(Lexer::T_COMMA);
$this->secondStringPrimary = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
So this
->orWhere( $qb->expr()->like( 'CONCAT(u.fname, \' \', u.lname)', '?3' ) )
should be
->orWhere( $qb->expr()->like( 'CONCAT(u.fname, u.lname)', '?3' ) )
This will not throw any errors, but may be not what you actually need. In that case, you will have to roll your own custom function for CONCAT :)
In addition to #Broncha's answer above (which helped solve the error by adding a nested CONCAT like 'CONCAT(u.fname, CONCAT(\' \', u.lname))'), the other function can be fixed by joining on the entity required, then adding WHERE clauses on the join like so:
$qb ->select(array('u'))
->from('model\entities\User', 'u')
->leftJoin('u.authentication', 'a')
->add('where', $qb->expr()->orx(
$qb->expr()->eq('a.disabled', '1'),
$qb->expr()->eq('a.resetPassword', '1')
));

Grouping WHERE clauses in Codeigniter

I want to produce the following SQL code using Active Records in Codeigniter:
WHERE name != 'Joe' AND (age < 69 OR id > 50)
Doing the following seems to be as far as I can get, I cant figure out how to group them
$this->db->select()->from('users')->where('name !=', 'Joe')->where('age <', 69)->or_where('id <', $id);
Any ideas? My SQL query is too complex so I dont wish to rewrite everything in traditional SQL.
UPDATE
My SQL code is dynamically generated depending on the values of certain parameters passed into the model method. The problem with not being able to use parenthesis causes a problem because the operator precedence is such that AND is evaluated first before OR.
*Here is a chunk of my active records code, where there are some other code before and after it:
... some $this->db->where() ...
... some $this->db->where() ...
if($price_range) {
$price_array = explode('.', $price_range);
for($i = 0; $i < count($price_array); $i++) {
if($i == 0) {
$this->db->where('places.price_range', $price_array[$i]);
} else {
$this->db->or_where('places.price_range', $price_array[$i]);
}
}
}
... some $this->db->where() ...
... some $this->db->where() ...
The problem comes because I am using $this->db->or_where() which introduces a OR clause that throws the operator precedence into disarray without being able to use ( ) to change the order.
** Is there any way to solve this? **
In Codeigniter 3.0.3 you can do it simple like this :
$this->db->select()
->from('users')
->where('name !=', 'Joe')
->group_start() // Open bracket
->where('age <', 69)
->or_where('id <', $id)
->group_end(); // Close bracket
Perhaps it can help
You can use one large string.
$this->db->select()->from('users')->where("name != 'Joe' AND (age < 69 OR id > 50)
");
The grouping of where clauses is not in CI by default. You have to extend the core and add in the ability. I have done so by doing something as follows:
class MY_DB_mysql_driver extends CI_DB_mysql_driver
{
public function __construct($params)
{
parent::__construct($params);
}
/**
* This function will allow you to do complex group where clauses in to c and (a AND b) or ( d and e)
* This function is needed as else the where clause will append an automatic AND in front of each where Thus if you wanted to do something
* like a AND ((b AND c) OR (d AND e)) you won't be able to as the where would insert it as a AND (AND (b...)) which is incorrect.
* Usage: start_group_where(key,value)->where(key,value)->close_group_where() or complex queries like
* open_bracket()->start_group_where(key,value)->where(key,value)->close_group_where()
* ->start_group_where(key,value,'','OR')->close_group_where()->close_bracket() would produce AND ((a AND b) OR (d))
* #param $key mixed the table columns prefix.columnname
* #param $value mixed the value of the key
* #param $escape string any escape as per CI
* #param $type the TYPE of query. By default it is set to 'AND'
* #return db object.
*/
function start_group_where($key,$value=NULL,$escape,$type="AND")
{
$this->open_bracket($type);
return parent::_where($key, $value,'',$escape);
}
/**
* Strictly used to have a consistent close function as the start_group_where. This essentially callse the close_bracket() function.
*/
function close_group_where()
{
return $this->close_bracket();
}
/**
* Allows to place a simple ( in a query and prepend it with the $type if needed.
* #param $type string add a ( to a query and prepend it with type. Default is $type.
* #param $return db object.
*/
function open_bracket($type="AND")
{
$this->ar_where[] = $type . " (";
return $this;
}
/**
* Allows to place a simple ) to a query.
*/
function close_bracket()
{
$this->ar_where[] = ")";
return $this;
}
}
Usage:
group_where_start(key,value)->where(key,value)->group_where_close()
or
complex queries like
open_bracket()->start_group_where(key,value)->where(key,value)->close_group_where()->start_group_where(key,value,'','OR')->close_group_where()->close_bracket() would produce AND ((a AND b) OR (d))
CI3 has all you need!
$this->db->select('*')->from('my_table')
->group_start()
->where('a', 'a')
->or_group_start()
->where('b', 'b')
->where('c', 'c')
->group_end()
->group_end()
->where('d', 'd')
->get();
https://www.codeigniter.com/userguide3/database/query_builder.html#query-grouping
What I've done is duplicate the and clause after the where, which is effectively the same as the long string selection.
$this->db->select()
->from('users')
->where('name !=', 'Joe')
->where('age <', 69)
->or_where('id <', $id)
->where('name !=', 'Joe');
The one large string way is probably better.
Solved. Dynamically generate the SQL query and plug it into $this->db->where(). Thanks guys!

Categories