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