Skip to content

Commit

Permalink
Merge pull request j4mie#201 from lrlopez/where_any_is
Browse files Browse the repository at this point in the history
Multiple OR'ed conditions support
  • Loading branch information
treffynnon committed May 28, 2014
2 parents a1b30b9 + 3f86f09 commit de4a611
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
48 changes: 48 additions & 0 deletions docs/querying.rst
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,54 @@ Similarly, to add a ``WHERE ... NOT LIKE`` clause, use:
<?php
$people = ORM::for_table('person')->where_not_like('name', '%bob%')->find_many();
Multiple OR'ed conditions
'''''''''''''''''''''''''

You can add simple OR'ed conditions to the same WHERE clause using ``where_any_is``. You
should specify multiple conditions using an array of items. Each item will be an
associative array that contains a multiple conditions.

.. code-block:: php
<?php
$people = ORM::for_table('person')
->where_any_is(array(
array('name' => 'Joe', 'age' => 10),
array('name' => 'Fred', 'age' => 20)))
->find_many();
// Creates SQL:
SELECT * FROM `widget` WHERE (( `name` = 'Joe' AND `age` = '10' ) OR ( `name` = 'Fred' AND `age` = '20' ));
By default, it uses the equal operator for every column, but it can be overriden for any
column using a second parameter:

.. code-block:: php
<?php
$people = ORM::for_table('person')
->where_any_is(array(
array('name' => 'Joe', 'age' => 10),
array('name' => 'Fred', 'age' => 20)), array('age' => '>'))
->find_many();
// Creates SQL:
SELECT * FROM `widget` WHERE (( `name` = 'Joe' AND `age` > '10' ) OR ( `name` = 'Fred' AND `age` > '20' ));
If you want to set the default operator for all the columns, just pass it as the second parameter:

.. code-block:: php
<?php
$people = ORM::for_table('person')
->where_any_is(array(
array('score' => '5', 'age' => 10),
array('score' => '15', 'age' => 20)), '>')
->find_many();
// Creates SQL:
SELECT * FROM `widget` WHERE (( `score` > '5' AND `age` > '10' ) OR ( `score` > '15' AND `age` > '20' ));
Set membership: ``where_in`` and ``where_not_in``
'''''''''''''''''''''''''''''''''''''''''''''''''

Expand Down
37 changes: 37 additions & 0 deletions idiorm.php
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,43 @@ public function where_id_is($id) {
$this->where($this->_get_id_column_name(), $id);
}

/**
* Allows adding a WHERE clause that matches any of the conditions
* specified in the array. Each element in the associative array will
* be a different condition, where the key will be the column name.
*
* By default, an equal operator will be used against all columns, but
* it can be overriden for any or every column using the second parameter.
*
* Each condition will be ORed together when added to the final query.
*/
public function where_any_is($values, $operator='=') {
$data = array();
$query = array("((");
$first = true;
foreach ($values as $item) {
if ($first) {
$first = false;
} else {
$query[] = ") OR (";
}
$firstsub = true;
foreach($item as $key => $item) {
$op = is_string($operator) ? $operator : (isset($operator[$key]) ? $operator[$key] : '=');
if ($firstsub) {
$firstsub = false;
} else {
$query[] = "AND";
}
$query[] = $this->_quote_identifier($key);
$data[] = $item;
$query[] = $op . " ?";
}
}
$query[] = "))";
return $this->where_raw(join($query, ' '), $data);
}

/**
* Add a WHERE ... LIKE clause to your query.
*/
Expand Down
24 changes: 24 additions & 0 deletions test/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,30 @@ public function testWhereNotIn() {
$this->assertEquals($expected, ORM::get_last_query());
}

public function testWhereAnyIs() {
ORM::for_table('widget')->where_any_is(array(
array('name' => 'Joe', 'age' => 10),
array('name' => 'Fred', 'age' => 20)))->find_many();
$expected = "SELECT * FROM `widget` WHERE (( `name` = 'Joe' AND `age` = '10' ) OR ( `name` = 'Fred' AND `age` = '20' ))";
$this->assertEquals($expected, ORM::get_last_query());
}

public function testWhereAnyIsOverrideOneColumn() {
ORM::for_table('widget')->where_any_is(array(
array('name' => 'Joe', 'age' => 10),
array('name' => 'Fred', 'age' => 20)), array('age' => '>'))->find_many();
$expected = "SELECT * FROM `widget` WHERE (( `name` = 'Joe' AND `age` > '10' ) OR ( `name` = 'Fred' AND `age` > '20' ))";
$this->assertEquals($expected, ORM::get_last_query());
}

public function testWhereAnyIsOverrideAllOperators() {
ORM::for_table('widget')->where_any_is(array(
array('score' => '5', 'age' => 10),
array('score' => '15', 'age' => 20)), '>')->find_many();
$expected = "SELECT * FROM `widget` WHERE (( `score` > '5' AND `age` > '10' ) OR ( `score` > '15' AND `age` > '20' ))";
$this->assertEquals($expected, ORM::get_last_query());
}

public function testLimit() {
ORM::for_table('widget')->limit(5)->find_many();
$expected = "SELECT * FROM `widget` LIMIT 5";
Expand Down

0 comments on commit de4a611

Please sign in to comment.