Ответ 1
решаемая. Динамически генерируйте SQL-запрос и подключите его к $this->db->where()
. Спасибо, ребята!
Я хочу создать следующий код SQL, используя Active Records в Codeigniter:
WHERE name != 'Joe' AND (age < 69 OR id > 50)
Выполнение следующего, кажется, насколько я могу получить, я не могу понять, как сгруппировать их
$this->db->select()->from('users')->where('name !=', 'Joe')->where('age <', 69)->or_where('id <', $id);
Любые идеи? Мой SQL-запрос слишком сложный, поэтому я не хочу переписывать все в традиционном SQL.
UPDATE
Мой SQL-код динамически генерируется в зависимости от значений некоторых параметров, переданных в модельный метод. Проблема с невозможностью использования скобок вызывает проблему, поскольку приоритет оператора таков, что AND
оценивается сначала до OR
.
* Вот фрагмент моего активного кода записи, где есть и другой код до и после него:
... 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() ...
Проблема возникает из-за того, что я использую $this->db->or_where()
, который вводит предложение OR
, которое бросает приоритет оператора в беспорядок, не имея возможности использовать ( )
для изменения порядка.
** Есть ли способ решить это? **
решаемая. Динамически генерируйте SQL-запрос и подключите его к $this->db->where()
. Спасибо, ребята!
В Codeigniter 3.0.3 вы можете сделать это просто:
$this->db->select()
->from('users')
->where('name !=', 'Joe')
->group_start() // Open bracket
->where('age <', 69)
->or_where('id <', $id)
->group_end(); // Close bracket
Возможно, это поможет
Вы можете использовать одну большую строку.
$this->db->select()->from('users')->where("name != 'Joe' AND (age < 69 OR id > 50)
");
По умолчанию группировка предложений where отсутствует в CI. Вы должны расширить ядро и добавить способность. Я сделал это, сделав что-то следующим образом:
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;
}
}
Использование:
group_where_start(key,value)->where(key,value)->group_where_close()
или
сложные запросы, такие как
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))
То, что я сделал, - это дублировать предложение и после того, где оно фактически совпадает с выбором длинной строки.
$this->db->select()
->from('users')
->where('name !=', 'Joe')
->where('age <', 69)
->or_where('id <', $id)
->where('name !=', 'Joe');
Вероятно, один большой строковый путь.
У CI3 есть все, что вам нужно!
$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