1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 3.1
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15:
16: namespace Cake\Datasource;
17:
18: /**
19: * The basis for every query object
20: *
21: * @method $this andWhere($conditions, $types = [])
22: * @method $this select($fields = [], $overwrite = false)
23: * @method \Cake\Datasource\RepositoryInterface getRepository()
24: */
25: interface QueryInterface
26: {
27: const JOIN_TYPE_INNER = 'INNER';
28: const JOIN_TYPE_LEFT = 'LEFT';
29: const JOIN_TYPE_RIGHT = 'RIGHT';
30:
31: /**
32: * Returns a key => value array representing a single aliased field
33: * that can be passed directly to the select() method.
34: * The key will contain the alias and the value the actual field name.
35: *
36: * If the field is already aliased, then it will not be changed.
37: * If no $alias is passed, the default table for this query will be used.
38: *
39: * @param string $field The field to alias
40: * @param string|null $alias the alias used to prefix the field
41: * @return string
42: */
43: public function aliasField($field, $alias = null);
44:
45: /**
46: * Runs `aliasField()` for each field in the provided list and returns
47: * the result under a single array.
48: *
49: * @param array $fields The fields to alias
50: * @param string|null $defaultAlias The default alias
51: * @return string[]
52: */
53: public function aliasFields($fields, $defaultAlias = null);
54:
55: /**
56: * Fetch the results for this query.
57: *
58: * Will return either the results set through setResult(), or execute this query
59: * and return the ResultSetDecorator object ready for streaming of results.
60: *
61: * ResultSetDecorator is a traversable object that implements the methods found
62: * on Cake\Collection\Collection.
63: *
64: * @return \Cake\Datasource\ResultSetInterface
65: */
66: public function all();
67:
68: /**
69: * Populates or adds parts to current query clauses using an array.
70: * This is handy for passing all query clauses at once. The option array accepts:
71: *
72: * - fields: Maps to the select method
73: * - conditions: Maps to the where method
74: * - limit: Maps to the limit method
75: * - order: Maps to the order method
76: * - offset: Maps to the offset method
77: * - group: Maps to the group method
78: * - having: Maps to the having method
79: * - contain: Maps to the contain options for eager loading
80: * - join: Maps to the join method
81: * - page: Maps to the page method
82: *
83: * ### Example:
84: *
85: * ```
86: * $query->applyOptions([
87: * 'fields' => ['id', 'name'],
88: * 'conditions' => [
89: * 'created >=' => '2013-01-01'
90: * ],
91: * 'limit' => 10
92: * ]);
93: * ```
94: *
95: * Is equivalent to:
96: *
97: * ```
98: * $query
99: * ->select(['id', 'name'])
100: * ->where(['created >=' => '2013-01-01'])
101: * ->limit(10)
102: * ```
103: *
104: * @param array $options list of query clauses to apply new parts to.
105: * @return $this
106: */
107: public function applyOptions(array $options);
108:
109: /**
110: * Apply custom finds to against an existing query object.
111: *
112: * Allows custom find methods to be combined and applied to each other.
113: *
114: * ```
115: * $repository->find('all')->find('recent');
116: * ```
117: *
118: * The above is an example of stacking multiple finder methods onto
119: * a single query.
120: *
121: * @param string $finder The finder method to use.
122: * @param array $options The options for the finder.
123: * @return $this Returns a modified query.
124: */
125: public function find($finder, array $options = []);
126:
127: /**
128: * Returns the first result out of executing this query, if the query has not been
129: * executed before, it will set the limit clause to 1 for performance reasons.
130: *
131: * ### Example:
132: *
133: * ```
134: * $singleUser = $query->select(['id', 'username'])->first();
135: * ```
136: *
137: * @return mixed the first result from the ResultSet
138: */
139: public function first();
140:
141: /**
142: * Returns the total amount of results for the query.
143: *
144: * @return int
145: */
146: public function count();
147:
148: /**
149: * Sets the number of records that should be retrieved from database,
150: * accepts an integer or an expression object that evaluates to an integer.
151: * In some databases, this operation might not be supported or will require
152: * the query to be transformed in order to limit the result set size.
153: *
154: * ### Examples
155: *
156: * ```
157: * $query->limit(10) // generates LIMIT 10
158: * $query->limit($query->newExpr()->add(['1 + 1'])); // LIMIT (1 + 1)
159: * ```
160: *
161: * @param int $num number of records to be returned
162: * @return $this
163: */
164: public function limit($num);
165:
166: /**
167: * Sets the number of records that should be skipped from the original result set
168: * This is commonly used for paginating large results. Accepts an integer or an
169: * expression object that evaluates to an integer.
170: *
171: * In some databases, this operation might not be supported or will require
172: * the query to be transformed in order to limit the result set size.
173: *
174: * ### Examples
175: *
176: * ```
177: * $query->offset(10) // generates OFFSET 10
178: * $query->offset($query->newExpr()->add(['1 + 1'])); // OFFSET (1 + 1)
179: * ```
180: *
181: * @param int $num number of records to be skipped
182: * @return $this
183: */
184: public function offset($num);
185:
186: /**
187: * Adds a single or multiple fields to be used in the ORDER clause for this query.
188: * Fields can be passed as an array of strings, array of expression
189: * objects, a single expression or a single string.
190: *
191: * If an array is passed, keys will be used as the field itself and the value will
192: * represent the order in which such field should be ordered. When called multiple
193: * times with the same fields as key, the last order definition will prevail over
194: * the others.
195: *
196: * By default this function will append any passed argument to the list of fields
197: * to be selected, unless the second argument is set to true.
198: *
199: * ### Examples:
200: *
201: * ```
202: * $query->order(['title' => 'DESC', 'author_id' => 'ASC']);
203: * ```
204: *
205: * Produces:
206: *
207: * `ORDER BY title DESC, author_id ASC`
208: *
209: * ```
210: * $query->order(['title' => 'DESC NULLS FIRST'])->order('author_id');
211: * ```
212: *
213: * Will generate:
214: *
215: * `ORDER BY title DESC NULLS FIRST, author_id`
216: *
217: * ```
218: * $expression = $query->newExpr()->add(['id % 2 = 0']);
219: * $query->order($expression)->order(['title' => 'ASC']);
220: * ```
221: *
222: * Will become:
223: *
224: * `ORDER BY (id %2 = 0), title ASC`
225: *
226: * If you need to set complex expressions as order conditions, you
227: * should use `orderAsc()` or `orderDesc()`.
228: *
229: * @param array|string $fields fields to be added to the list
230: * @param bool $overwrite whether to reset order with field list or not
231: * @return $this
232: */
233: public function order($fields, $overwrite = false);
234:
235: /**
236: * Set the page of results you want.
237: *
238: * This method provides an easier to use interface to set the limit + offset
239: * in the record set you want as results. If empty the limit will default to
240: * the existing limit clause, and if that too is empty, then `25` will be used.
241: *
242: * Pages must start at 1.
243: *
244: * @param int $num The page number you want.
245: * @param int|null $limit The number of rows you want in the page. If null
246: * the current limit clause will be used.
247: * @return $this
248: * @throws \InvalidArgumentException If page number < 1.
249: */
250: public function page($num, $limit = null);
251:
252: /**
253: * Returns an array representation of the results after executing the query.
254: *
255: * @return array
256: */
257: public function toArray();
258:
259: /**
260: * Returns the default repository object that will be used by this query,
261: * that is, the repository that will appear in the from clause.
262: *
263: * @param \Cake\Datasource\RepositoryInterface|null $repository The default repository object to use
264: * @return \Cake\Datasource\RepositoryInterface|$this
265: */
266: public function repository(RepositoryInterface $repository = null);
267:
268: /**
269: * Adds a condition or set of conditions to be used in the WHERE clause for this
270: * query. Conditions can be expressed as an array of fields as keys with
271: * comparison operators in it, the values for the array will be used for comparing
272: * the field to such literal. Finally, conditions can be expressed as a single
273: * string or an array of strings.
274: *
275: * When using arrays, each entry will be joined to the rest of the conditions using
276: * an AND operator. Consecutive calls to this function will also join the new
277: * conditions specified using the AND operator. Additionally, values can be
278: * expressed using expression objects which can include other query objects.
279: *
280: * Any conditions created with this methods can be used with any SELECT, UPDATE
281: * and DELETE type of queries.
282: *
283: * ### Conditions using operators:
284: *
285: * ```
286: * $query->where([
287: * 'posted >=' => new DateTime('3 days ago'),
288: * 'title LIKE' => 'Hello W%',
289: * 'author_id' => 1,
290: * ], ['posted' => 'datetime']);
291: * ```
292: *
293: * The previous example produces:
294: *
295: * `WHERE posted >= 2012-01-27 AND title LIKE 'Hello W%' AND author_id = 1`
296: *
297: * Second parameter is used to specify what type is expected for each passed
298: * key. Valid types can be used from the mapped with Database\Type class.
299: *
300: * ### Nesting conditions with conjunctions:
301: *
302: * ```
303: * $query->where([
304: * 'author_id !=' => 1,
305: * 'OR' => ['published' => true, 'posted <' => new DateTime('now')],
306: * 'NOT' => ['title' => 'Hello']
307: * ], ['published' => boolean, 'posted' => 'datetime']
308: * ```
309: *
310: * The previous example produces:
311: *
312: * `WHERE author_id = 1 AND (published = 1 OR posted < '2012-02-01') AND NOT (title = 'Hello')`
313: *
314: * You can nest conditions using conjunctions as much as you like. Sometimes, you
315: * may want to define 2 different options for the same key, in that case, you can
316: * wrap each condition inside a new array:
317: *
318: * `$query->where(['OR' => [['published' => false], ['published' => true]])`
319: *
320: * Keep in mind that every time you call where() with the third param set to false
321: * (default), it will join the passed conditions to the previous stored list using
322: * the AND operator. Also, using the same array key twice in consecutive calls to
323: * this method will not override the previous value.
324: *
325: * ### Using expressions objects:
326: *
327: * ```
328: * $exp = $query->newExpr()->add(['id !=' => 100, 'author_id' != 1])->tieWith('OR');
329: * $query->where(['published' => true], ['published' => 'boolean'])->where($exp);
330: * ```
331: *
332: * The previous example produces:
333: *
334: * `WHERE (id != 100 OR author_id != 1) AND published = 1`
335: *
336: * Other Query objects that be used as conditions for any field.
337: *
338: * ### Adding conditions in multiple steps:
339: *
340: * You can use callable functions to construct complex expressions, functions
341: * receive as first argument a new QueryExpression object and this query instance
342: * as second argument. Functions must return an expression object, that will be
343: * added the list of conditions for the query using the AND operator.
344: *
345: * ```
346: * $query
347: * ->where(['title !=' => 'Hello World'])
348: * ->where(function ($exp, $query) {
349: * $or = $exp->or_(['id' => 1]);
350: * $and = $exp->and_(['id >' => 2, 'id <' => 10]);
351: * return $or->add($and);
352: * });
353: * ```
354: *
355: * * The previous example produces:
356: *
357: * `WHERE title != 'Hello World' AND (id = 1 OR (id > 2 AND id < 10))`
358: *
359: * ### Conditions as strings:
360: *
361: * ```
362: * $query->where(['articles.author_id = authors.id', 'modified IS NULL']);
363: * ```
364: *
365: * The previous example produces:
366: *
367: * `WHERE articles.author_id = authors.id AND modified IS NULL`
368: *
369: * Please note that when using the array notation or the expression objects, all
370: * values will be correctly quoted and transformed to the correspondent database
371: * data type automatically for you, thus securing your application from SQL injections.
372: * If you use string conditions make sure that your values are correctly quoted.
373: * The safest thing you can do is to never use string conditions.
374: *
375: * @param string|array|callable|null $conditions The conditions to filter on.
376: * @param array $types associative array of type names used to bind values to query
377: * @param bool $overwrite whether to reset conditions with passed list or not
378: * @return $this
379: */
380: public function where($conditions = null, $types = [], $overwrite = false);
381: }
382: