CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.7 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.7
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • ConnectionManager
  • ConnectionRegistry
  • FactoryLocator
  • Paginator
  • QueryCacher
  • ResultSetDecorator
  • RulesChecker

Interfaces

  • ConnectionInterface
  • EntityInterface
  • FixtureInterface
  • InvalidPropertyInterface
  • PaginatorInterface
  • QueryInterface
  • RepositoryInterface
  • ResultSetInterface
  • SchemaInterface
  • TableSchemaInterface

Traits

  • EntityTrait
  • ModelAwareTrait
  • QueryTrait
  • RulesAwareTrait
  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.0.0
 13:  * @license       https://opensource.org/licenses/mit-license.php MIT License
 14:  */
 15: namespace Cake\Datasource;
 16: 
 17: use BadMethodCallException;
 18: use Cake\Collection\Iterator\MapReduce;
 19: use Cake\Datasource\Exception\RecordNotFoundException;
 20: 
 21: /**
 22:  * Contains the characteristics for an object that is attached to a repository and
 23:  * can retrieve results based on any criteria.
 24:  */
 25: trait QueryTrait
 26: {
 27: 
 28:     /**
 29:      * Instance of a table object this query is bound to
 30:      *
 31:      * @var \Cake\Datasource\RepositoryInterface
 32:      */
 33:     protected $_repository;
 34: 
 35:     /**
 36:      * A ResultSet.
 37:      *
 38:      * When set, query execution will be bypassed.
 39:      *
 40:      * @var \Cake\Datasource\ResultSetInterface|null
 41:      * @see \Cake\Datasource\QueryTrait::setResult()
 42:      */
 43:     protected $_results;
 44: 
 45:     /**
 46:      * List of map-reduce routines that should be applied over the query
 47:      * result
 48:      *
 49:      * @var array
 50:      */
 51:     protected $_mapReduce = [];
 52: 
 53:     /**
 54:      * List of formatter classes or callbacks that will post-process the
 55:      * results when fetched
 56:      *
 57:      * @var callable[]
 58:      */
 59:     protected $_formatters = [];
 60: 
 61:     /**
 62:      * A query cacher instance if this query has caching enabled.
 63:      *
 64:      * @var \Cake\Datasource\QueryCacher|null
 65:      */
 66:     protected $_cache;
 67: 
 68:     /**
 69:      * Holds any custom options passed using applyOptions that could not be processed
 70:      * by any method in this class.
 71:      *
 72:      * @var array
 73:      */
 74:     protected $_options = [];
 75: 
 76:     /**
 77:      * Whether the query is standalone or the product of an eager load operation.
 78:      *
 79:      * @var bool
 80:      */
 81:     protected $_eagerLoaded = false;
 82: 
 83:     /**
 84:      * Returns the default table object that will be used by this query,
 85:      * that is, the table that will appear in the from clause.
 86:      *
 87:      * When called with a Table argument, the default table object will be set
 88:      * and this query object will be returned for chaining.
 89:      *
 90:      * @param \Cake\Datasource\RepositoryInterface|null $table The default table object to use
 91:      * @return \Cake\Datasource\RepositoryInterface|$this
 92:      */
 93:     public function repository(RepositoryInterface $table = null)
 94:     {
 95:         if ($table === null) {
 96:             deprecationWarning(
 97:                 'Using Query::repository() as getter is deprecated. ' .
 98:                 'Use getRepository() instead.'
 99:             );
100: 
101:             return $this->getRepository();
102:         }
103: 
104:         $this->_repository = $table;
105: 
106:         return $this;
107:     }
108: 
109:     /**
110:      * Returns the default table object that will be used by this query,
111:      * that is, the table that will appear in the from clause.
112:      *
113:      * @return \Cake\Datasource\RepositoryInterface
114:      */
115:     public function getRepository()
116:     {
117:         return $this->_repository;
118:     }
119: 
120:     /**
121:      * Set the result set for a query.
122:      *
123:      * Setting the resultset of a query will make execute() a no-op. Instead
124:      * of executing the SQL query and fetching results, the ResultSet provided to this
125:      * method will be returned.
126:      *
127:      * This method is most useful when combined with results stored in a persistent cache.
128:      *
129:      * @param \Cake\Datasource\ResultSetInterface $results The results this query should return.
130:      * @return $this
131:      */
132:     public function setResult($results)
133:     {
134:         $this->_results = $results;
135: 
136:         return $this;
137:     }
138: 
139:     /**
140:      * Executes this query and returns a results iterator. This function is required
141:      * for implementing the IteratorAggregate interface and allows the query to be
142:      * iterated without having to call execute() manually, thus making it look like
143:      * a result set instead of the query itself.
144:      *
145:      * @return \Iterator
146:      */
147:     public function getIterator()
148:     {
149:         return $this->all();
150:     }
151: 
152:     /**
153:      * Enable result caching for this query.
154:      *
155:      * If a query has caching enabled, it will do the following when executed:
156:      *
157:      * - Check the cache for $key. If there are results no SQL will be executed.
158:      *   Instead the cached results will be returned.
159:      * - When the cached data is stale/missing the result set will be cached as the query
160:      *   is executed.
161:      *
162:      * ### Usage
163:      *
164:      * ```
165:      * // Simple string key + config
166:      * $query->cache('my_key', 'db_results');
167:      *
168:      * // Function to generate key.
169:      * $query->cache(function ($q) {
170:      *   $key = serialize($q->clause('select'));
171:      *   $key .= serialize($q->clause('where'));
172:      *   return md5($key);
173:      * });
174:      *
175:      * // Using a pre-built cache engine.
176:      * $query->cache('my_key', $engine);
177:      *
178:      * // Disable caching
179:      * $query->cache(false);
180:      * ```
181:      *
182:      * @param false|string|\Closure $key Either the cache key or a function to generate the cache key.
183:      *   When using a function, this query instance will be supplied as an argument.
184:      * @param string|\Cake\Cache\CacheEngine $config Either the name of the cache config to use, or
185:      *   a cache config instance.
186:      * @return $this
187:      */
188:     public function cache($key, $config = 'default')
189:     {
190:         if ($key === false) {
191:             $this->_cache = null;
192: 
193:             return $this;
194:         }
195:         $this->_cache = new QueryCacher($key, $config);
196: 
197:         return $this;
198:     }
199: 
200:     /**
201:      * Returns the current configured query `_eagerLoaded` value
202:      *
203:      * @return bool
204:      */
205:     public function isEagerLoaded()
206:     {
207:         return $this->_eagerLoaded;
208:     }
209: 
210:     /**
211:      * Sets the query instance to be an eager loaded query. If no argument is
212:      * passed, the current configured query `_eagerLoaded` value is returned.
213:      *
214:      * @deprecated 3.5.0 Use isEagerLoaded() for the getter part instead.
215:      * @param bool|null $value Whether or not to eager load.
216:      * @return $this|bool
217:      */
218:     public function eagerLoaded($value = null)
219:     {
220:         if ($value === null) {
221:             deprecationWarning(
222:                 'Using ' . get_called_class() . '::eagerLoaded() as a getter is deprecated. ' .
223:                 'Use isEagerLoaded() instead.'
224:             );
225: 
226:             return $this->_eagerLoaded;
227:         }
228:         $this->_eagerLoaded = $value;
229: 
230:         return $this;
231:     }
232: 
233:     /**
234:      * Returns a key => value array representing a single aliased field
235:      * that can be passed directly to the select() method.
236:      * The key will contain the alias and the value the actual field name.
237:      *
238:      * If the field is already aliased, then it will not be changed.
239:      * If no $alias is passed, the default table for this query will be used.
240:      *
241:      * @param string $field The field to alias
242:      * @param string|null $alias the alias used to prefix the field
243:      * @return array
244:      */
245:     public function aliasField($field, $alias = null)
246:     {
247:         $namespaced = strpos($field, '.') !== false;
248:         $aliasedField = $field;
249: 
250:         if ($namespaced) {
251:             list($alias, $field) = explode('.', $field);
252:         }
253: 
254:         if (!$alias) {
255:             $alias = $this->getRepository()->getAlias();
256:         }
257: 
258:         $key = sprintf('%s__%s', $alias, $field);
259:         if (!$namespaced) {
260:             $aliasedField = $alias . '.' . $field;
261:         }
262: 
263:         return [$key => $aliasedField];
264:     }
265: 
266:     /**
267:      * Runs `aliasField()` for each field in the provided list and returns
268:      * the result under a single array.
269:      *
270:      * @param array $fields The fields to alias
271:      * @param string|null $defaultAlias The default alias
272:      * @return array
273:      */
274:     public function aliasFields($fields, $defaultAlias = null)
275:     {
276:         $aliased = [];
277:         foreach ($fields as $alias => $field) {
278:             if (is_numeric($alias) && is_string($field)) {
279:                 $aliased += $this->aliasField($field, $defaultAlias);
280:                 continue;
281:             }
282:             $aliased[$alias] = $field;
283:         }
284: 
285:         return $aliased;
286:     }
287: 
288:     /**
289:      * Fetch the results for this query.
290:      *
291:      * Will return either the results set through setResult(), or execute this query
292:      * and return the ResultSetDecorator object ready for streaming of results.
293:      *
294:      * ResultSetDecorator is a traversable object that implements the methods found
295:      * on Cake\Collection\Collection.
296:      *
297:      * @return \Cake\Datasource\ResultSetInterface
298:      */
299:     public function all()
300:     {
301:         if ($this->_results !== null) {
302:             return $this->_results;
303:         }
304: 
305:         if ($this->_cache) {
306:             $results = $this->_cache->fetch($this);
307:         }
308:         if (!isset($results)) {
309:             $results = $this->_decorateResults($this->_execute());
310:             if ($this->_cache) {
311:                 $this->_cache->store($this, $results);
312:             }
313:         }
314:         $this->_results = $results;
315: 
316:         return $this->_results;
317:     }
318: 
319:     /**
320:      * Returns an array representation of the results after executing the query.
321:      *
322:      * @return array
323:      */
324:     public function toArray()
325:     {
326:         return $this->all()->toArray();
327:     }
328: 
329:     /**
330:      * Register a new MapReduce routine to be executed on top of the database results
331:      * Both the mapper and caller callable should be invokable objects.
332:      *
333:      * The MapReduce routing will only be run when the query is executed and the first
334:      * result is attempted to be fetched.
335:      *
336:      * If the first argument is set to null, it will return the list of previously
337:      * registered map reduce routines. This is deprecated as of 3.6.0 - use getMapReducers() instead.
338:      *
339:      * If the third argument is set to true, it will erase previous map reducers
340:      * and replace it with the arguments passed.
341:      *
342:      * @param callable|null $mapper The mapper callable.
343:      * @param callable|null $reducer The reducing function.
344:      * @param bool $overwrite Set to true to overwrite existing map + reduce functions.
345:      * @return $this|array
346:      * @see \Cake\Collection\Iterator\MapReduce for details on how to use emit data to the map reducer.
347:      */
348:     public function mapReduce(callable $mapper = null, callable $reducer = null, $overwrite = false)
349:     {
350:         if ($overwrite) {
351:             $this->_mapReduce = [];
352:         }
353:         if ($mapper === null) {
354:             if (!$overwrite) {
355:                 deprecationWarning(
356:                     'Using QueryTrait::mapReduce() as a getter is deprecated. ' .
357:                     'Use getMapReducers() instead.'
358:                 );
359:             }
360: 
361:             return $this->_mapReduce;
362:         }
363:         $this->_mapReduce[] = compact('mapper', 'reducer');
364: 
365:         return $this;
366:     }
367: 
368:     /**
369:      * Returns the list of previously registered map reduce routines.
370:      *
371:      * @return array
372:      */
373:     public function getMapReducers()
374:     {
375:         return $this->_mapReduce;
376:     }
377: 
378:     /**
379:      * Registers a new formatter callback function that is to be executed when trying
380:      * to fetch the results from the database.
381:      *
382:      * Formatting callbacks will get a first parameter, an object implementing
383:      * `\Cake\Collection\CollectionInterface`, that can be traversed and modified at will.
384:      *
385:      * Callbacks are required to return an iterator object, which will be used as
386:      * the return value for this query's result. Formatter functions are applied
387:      * after all the `MapReduce` routines for this query have been executed.
388:      *
389:      * If the first argument is set to null, it will return the list of previously
390:      * registered format routines. This is deprecated as of 3.6.0 - use getResultFormatters() instead.
391:      *
392:      * If the second argument is set to true, it will erase previous formatters
393:      * and replace them with the passed first argument.
394:      *
395:      * ### Example:
396:      *
397:      * ```
398:      * // Return all results from the table indexed by id
399:      * $query->select(['id', 'name'])->formatResults(function ($results) {
400:      *   return $results->indexBy('id');
401:      * });
402:      *
403:      * // Add a new column to the ResultSet
404:      * $query->select(['name', 'birth_date'])->formatResults(function ($results) {
405:      *   return $results->map(function ($row) {
406:      *     $row['age'] = $row['birth_date']->diff(new DateTime)->y;
407:      *     return $row;
408:      *   });
409:      * });
410:      * ```
411:      *
412:      * @param callable|null $formatter The formatting callable.
413:      * @param bool|int $mode Whether or not to overwrite, append or prepend the formatter.
414:      * @return $this|array
415:      */
416:     public function formatResults(callable $formatter = null, $mode = 0)
417:     {
418:         if ($mode === self::OVERWRITE) {
419:             $this->_formatters = [];
420:         }
421:         if ($formatter === null) {
422:             if ($mode !== self::OVERWRITE) {
423:                 deprecationWarning(
424:                     'Using QueryTrait::formatResults() as a getter is deprecated. ' .
425:                     'Use getResultFormatters() instead.'
426:                 );
427:             }
428: 
429:             return $this->_formatters;
430:         }
431: 
432:         if ($mode === self::PREPEND) {
433:             array_unshift($this->_formatters, $formatter);
434: 
435:             return $this;
436:         }
437: 
438:         $this->_formatters[] = $formatter;
439: 
440:         return $this;
441:     }
442: 
443:     /**
444:      * Returns the list of previously registered format routines.
445:      *
446:      * @return array
447:      */
448:     public function getResultFormatters()
449:     {
450:         return $this->_formatters;
451:     }
452: 
453:     /**
454:      * Returns the first result out of executing this query, if the query has not been
455:      * executed before, it will set the limit clause to 1 for performance reasons.
456:      *
457:      * ### Example:
458:      *
459:      * ```
460:      * $singleUser = $query->select(['id', 'username'])->first();
461:      * ```
462:      *
463:      * @return \Cake\Datasource\EntityInterface|array|null The first result from the ResultSet.
464:      */
465:     public function first()
466:     {
467:         if ($this->_dirty) {
468:             $this->limit(1);
469:         }
470: 
471:         return $this->all()->first();
472:     }
473: 
474:     /**
475:      * Get the first result from the executing query or raise an exception.
476:      *
477:      * @throws \Cake\Datasource\Exception\RecordNotFoundException When there is no first record.
478:      * @return \Cake\Datasource\EntityInterface|array The first result from the ResultSet.
479:      */
480:     public function firstOrFail()
481:     {
482:         $entity = $this->first();
483:         if (!$entity) {
484:             /** @var \Cake\ORM\Table $table */
485:             $table = $this->getRepository();
486:             throw new RecordNotFoundException(sprintf(
487:                 'Record not found in table "%s"',
488:                 $table->getTable()
489:             ));
490:         }
491: 
492:         return $entity;
493:     }
494: 
495:     /**
496:      * Returns an array with the custom options that were applied to this query
497:      * and that were not already processed by another method in this class.
498:      *
499:      * ### Example:
500:      *
501:      * ```
502:      *  $query->applyOptions(['doABarrelRoll' => true, 'fields' => ['id', 'name']);
503:      *  $query->getOptions(); // Returns ['doABarrelRoll' => true]
504:      * ```
505:      *
506:      * @see \Cake\Datasource\QueryInterface::applyOptions() to read about the options that will
507:      * be processed by this class and not returned by this function
508:      * @return array
509:      */
510:     public function getOptions()
511:     {
512:         return $this->_options;
513:     }
514: 
515:     /**
516:      * Enables calling methods from the result set as if they were from this class
517:      *
518:      * @param string $method the method to call
519:      * @param array $arguments list of arguments for the method to call
520:      * @return mixed
521:      * @throws \BadMethodCallException if no such method exists in result set
522:      */
523:     public function __call($method, $arguments)
524:     {
525:         $resultSetClass = $this->_decoratorClass();
526:         if (in_array($method, get_class_methods($resultSetClass))) {
527:             $results = $this->all();
528: 
529:             return $results->$method(...$arguments);
530:         }
531:         throw new BadMethodCallException(
532:             sprintf('Unknown method "%s"', $method)
533:         );
534:     }
535: 
536:     /**
537:      * Populates or adds parts to current query clauses using an array.
538:      * This is handy for passing all query clauses at once.
539:      *
540:      * @param array $options the options to be applied
541:      * @return $this
542:      */
543:     abstract public function applyOptions(array $options);
544: 
545:     /**
546:      * Executes this query and returns a traversable object containing the results
547:      *
548:      * @return \Traversable
549:      */
550:     abstract protected function _execute();
551: 
552:     /**
553:      * Decorates the results iterator with MapReduce routines and formatters
554:      *
555:      * @param \Traversable $result Original results
556:      * @return \Cake\Datasource\ResultSetInterface
557:      */
558:     protected function _decorateResults($result)
559:     {
560:         $decorator = $this->_decoratorClass();
561:         foreach ($this->_mapReduce as $functions) {
562:             $result = new MapReduce($result, $functions['mapper'], $functions['reducer']);
563:         }
564: 
565:         if (!empty($this->_mapReduce)) {
566:             $result = new $decorator($result);
567:         }
568: 
569:         foreach ($this->_formatters as $formatter) {
570:             $result = $formatter($result);
571:         }
572: 
573:         if (!empty($this->_formatters) && !($result instanceof $decorator)) {
574:             $result = new $decorator($result);
575:         }
576: 
577:         return $result;
578:     }
579: 
580:     /**
581:      * Returns the name of the class to be used for decorating results
582:      *
583:      * @return string
584:      */
585:     protected function _decoratorClass()
586:     {
587:         return ResultSetDecorator::class;
588:     }
589: }
590: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs