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.8 Red Velvet API

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