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

  • Association
  • AssociationCollection
  • Behavior
  • BehaviorRegistry
  • EagerLoader
  • Entity
  • Marshaller
  • Query
  • ResultSet
  • RulesChecker
  • SaveOptionsBuilder
  • Table
  • TableRegistry

Interfaces

  • PropertyMarshalInterface

Traits

  • AssociationsNormalizerTrait
  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\ORM;
 16: 
 17: use Cake\Core\Exception\Exception;
 18: use Cake\Core\InstanceConfigTrait;
 19: use Cake\Event\EventListenerInterface;
 20: use ReflectionClass;
 21: use ReflectionMethod;
 22: 
 23: /**
 24:  * Base class for behaviors.
 25:  *
 26:  * Behaviors allow you to simulate mixins, and create
 27:  * reusable blocks of application logic, that can be reused across
 28:  * several models. Behaviors also provide a way to hook into model
 29:  * callbacks and augment their behavior.
 30:  *
 31:  * ### Mixin methods
 32:  *
 33:  * Behaviors can provide mixin like features by declaring public
 34:  * methods. These methods will be accessible on the tables the
 35:  * behavior has been added to.
 36:  *
 37:  * ```
 38:  * function doSomething($arg1, $arg2) {
 39:  *   // do something
 40:  * }
 41:  * ```
 42:  *
 43:  * Would be called like `$table->doSomething($arg1, $arg2);`.
 44:  *
 45:  * ### Callback methods
 46:  *
 47:  * Behaviors can listen to any events fired on a Table. By default
 48:  * CakePHP provides a number of lifecycle events your behaviors can
 49:  * listen to:
 50:  *
 51:  * - `beforeFind(Event $event, Query $query, ArrayObject $options, boolean $primary)`
 52:  *   Fired before each find operation. By stopping the event and supplying a
 53:  *   return value you can bypass the find operation entirely. Any changes done
 54:  *   to the $query instance will be retained for the rest of the find. The
 55:  *   $primary parameter indicates whether or not this is the root query,
 56:  *   or an associated query.
 57:  *
 58:  * - `buildValidator(Event $event, Validator $validator, string $name)`
 59:  *   Fired when the validator object identified by $name is being built. You can use this
 60:  *   callback to add validation rules or add validation providers.
 61:  *
 62:  * - `buildRules(Event $event, RulesChecker $rules)`
 63:  *   Fired when the rules checking object for the table is being built. You can use this
 64:  *   callback to add more rules to the set.
 65:  *
 66:  * - `beforeRules(Event $event, EntityInterface $entity, ArrayObject $options, $operation)`
 67:  *   Fired before an entity is validated using by a rules checker. By stopping this event,
 68:  *   you can return the final value of the rules checking operation.
 69:  *
 70:  * - `afterRules(Event $event, EntityInterface $entity, ArrayObject $options, bool $result, $operation)`
 71:  *   Fired after the rules have been checked on the entity. By stopping this event,
 72:  *   you can return the final value of the rules checking operation.
 73:  *
 74:  * - `beforeSave(Event $event, EntityInterface $entity, ArrayObject $options)`
 75:  *   Fired before each entity is saved. Stopping this event will abort the save
 76:  *   operation. When the event is stopped the result of the event will be returned.
 77:  *
 78:  * - `afterSave(Event $event, EntityInterface $entity, ArrayObject $options)`
 79:  *   Fired after an entity is saved.
 80:  *
 81:  * - `beforeDelete(Event $event, EntityInterface $entity, ArrayObject $options)`
 82:  *   Fired before an entity is deleted. By stopping this event you will abort
 83:  *   the delete operation.
 84:  *
 85:  * - `afterDelete(Event $event, EntityInterface $entity, ArrayObject $options)`
 86:  *   Fired after an entity has been deleted.
 87:  *
 88:  * In addition to the core events, behaviors can respond to any
 89:  * event fired from your Table classes including custom application
 90:  * specific ones.
 91:  *
 92:  * You can set the priority of a behaviors callbacks by using the
 93:  * `priority` setting when attaching a behavior. This will set the
 94:  * priority for all the callbacks a behavior provides.
 95:  *
 96:  * ### Finder methods
 97:  *
 98:  * Behaviors can provide finder methods that hook into a Table's
 99:  * find() method. Custom finders are a great way to provide preset
100:  * queries that relate to your behavior. For example a SluggableBehavior
101:  * could provide a find('slugged') finder. Behavior finders
102:  * are implemented the same as other finders. Any method
103:  * starting with `find` will be setup as a finder. Your finder
104:  * methods should expect the following arguments:
105:  *
106:  * ```
107:  * findSlugged(Query $query, array $options)
108:  * ```
109:  *
110:  * @see \Cake\ORM\Table::addBehavior()
111:  * @see \Cake\Event\EventManager
112:  */
113: class Behavior implements EventListenerInterface
114: {
115:     use InstanceConfigTrait;
116: 
117:     /**
118:      * Table instance.
119:      *
120:      * @var \Cake\ORM\Table
121:      */
122:     protected $_table;
123: 
124:     /**
125:      * Reflection method cache for behaviors.
126:      *
127:      * Stores the reflected method + finder methods per class.
128:      * This prevents reflecting the same class multiple times in a single process.
129:      *
130:      * @var array
131:      */
132:     protected static $_reflectionCache = [];
133: 
134:     /**
135:      * Default configuration
136:      *
137:      * These are merged with user-provided configuration when the behavior is used.
138:      *
139:      * @var array
140:      */
141:     protected $_defaultConfig = [];
142: 
143:     /**
144:      * Constructor
145:      *
146:      * Merges config with the default and store in the config property
147:      *
148:      * @param \Cake\ORM\Table $table The table this behavior is attached to.
149:      * @param array $config The config for this behavior.
150:      */
151:     public function __construct(Table $table, array $config = [])
152:     {
153:         $config = $this->_resolveMethodAliases(
154:             'implementedFinders',
155:             $this->_defaultConfig,
156:             $config
157:         );
158:         $config = $this->_resolveMethodAliases(
159:             'implementedMethods',
160:             $this->_defaultConfig,
161:             $config
162:         );
163:         $this->_table = $table;
164:         $this->setConfig($config);
165:         $this->initialize($config);
166:     }
167: 
168:     /**
169:      * Constructor hook method.
170:      *
171:      * Implement this method to avoid having to overwrite
172:      * the constructor and call parent.
173:      *
174:      * @param array $config The configuration settings provided to this behavior.
175:      * @return void
176:      */
177:     public function initialize(array $config)
178:     {
179:     }
180: 
181:     /**
182:      * Get the table instance this behavior is bound to.
183:      *
184:      * @return \Cake\ORM\Table The bound table instance.
185:      */
186:     public function getTable()
187:     {
188:         return $this->_table;
189:     }
190: 
191:     /**
192:      * Removes aliased methods that would otherwise be duplicated by userland configuration.
193:      *
194:      * @param string $key The key to filter.
195:      * @param array $defaults The default method mappings.
196:      * @param array $config The customized method mappings.
197:      * @return array A de-duped list of config data.
198:      */
199:     protected function _resolveMethodAliases($key, $defaults, $config)
200:     {
201:         if (!isset($defaults[$key], $config[$key])) {
202:             return $config;
203:         }
204:         if (isset($config[$key]) && $config[$key] === []) {
205:             $this->setConfig($key, [], false);
206:             unset($config[$key]);
207: 
208:             return $config;
209:         }
210: 
211:         $indexed = array_flip($defaults[$key]);
212:         $indexedCustom = array_flip($config[$key]);
213:         foreach ($indexed as $method => $alias) {
214:             if (!isset($indexedCustom[$method])) {
215:                 $indexedCustom[$method] = $alias;
216:             }
217:         }
218:         $this->setConfig($key, array_flip($indexedCustom), false);
219:         unset($config[$key]);
220: 
221:         return $config;
222:     }
223: 
224:     /**
225:      * verifyConfig
226:      *
227:      * Checks that implemented keys contain values pointing at callable.
228:      *
229:      * @return void
230:      * @throws \Cake\Core\Exception\Exception if config are invalid
231:      */
232:     public function verifyConfig()
233:     {
234:         $keys = ['implementedFinders', 'implementedMethods'];
235:         foreach ($keys as $key) {
236:             if (!isset($this->_config[$key])) {
237:                 continue;
238:             }
239: 
240:             foreach ($this->_config[$key] as $method) {
241:                 if (!is_callable([$this, $method])) {
242:                     throw new Exception(sprintf('The method %s is not callable on class %s', $method, get_class($this)));
243:                 }
244:             }
245:         }
246:     }
247: 
248:     /**
249:      * Gets the Model callbacks this behavior is interested in.
250:      *
251:      * By defining one of the callback methods a behavior is assumed
252:      * to be interested in the related event.
253:      *
254:      * Override this method if you need to add non-conventional event listeners.
255:      * Or if you want your behavior to listen to non-standard events.
256:      *
257:      * @return array
258:      */
259:     public function implementedEvents()
260:     {
261:         $eventMap = [
262:             'Model.beforeMarshal' => 'beforeMarshal',
263:             'Model.beforeFind' => 'beforeFind',
264:             'Model.beforeSave' => 'beforeSave',
265:             'Model.afterSave' => 'afterSave',
266:             'Model.afterSaveCommit' => 'afterSaveCommit',
267:             'Model.beforeDelete' => 'beforeDelete',
268:             'Model.afterDelete' => 'afterDelete',
269:             'Model.afterDeleteCommit' => 'afterDeleteCommit',
270:             'Model.buildValidator' => 'buildValidator',
271:             'Model.buildRules' => 'buildRules',
272:             'Model.beforeRules' => 'beforeRules',
273:             'Model.afterRules' => 'afterRules',
274:         ];
275:         $config = $this->getConfig();
276:         $priority = isset($config['priority']) ? $config['priority'] : null;
277:         $events = [];
278: 
279:         foreach ($eventMap as $event => $method) {
280:             if (!method_exists($this, $method)) {
281:                 continue;
282:             }
283:             if ($priority === null) {
284:                 $events[$event] = $method;
285:             } else {
286:                 $events[$event] = [
287:                     'callable' => $method,
288:                     'priority' => $priority
289:                 ];
290:             }
291:         }
292: 
293:         return $events;
294:     }
295: 
296:     /**
297:      * implementedFinders
298:      *
299:      * Provides an alias->methodname map of which finders a behavior implements. Example:
300:      *
301:      * ```
302:      *  [
303:      *    'this' => 'findThis',
304:      *    'alias' => 'findMethodName'
305:      *  ]
306:      * ```
307:      *
308:      * With the above example, a call to `$Table->find('this')` will call `$Behavior->findThis()`
309:      * and a call to `$Table->find('alias')` will call `$Behavior->findMethodName()`
310:      *
311:      * It is recommended, though not required, to define implementedFinders in the config property
312:      * of child classes such that it is not necessary to use reflections to derive the available
313:      * method list. See core behaviors for examples
314:      *
315:      * @return array
316:      * @throws \ReflectionException
317:      */
318:     public function implementedFinders()
319:     {
320:         $methods = $this->getConfig('implementedFinders');
321:         if (isset($methods)) {
322:             return $methods;
323:         }
324: 
325:         return $this->_reflectionCache()['finders'];
326:     }
327: 
328:     /**
329:      * implementedMethods
330:      *
331:      * Provides an alias->methodname map of which methods a behavior implements. Example:
332:      *
333:      * ```
334:      *  [
335:      *    'method' => 'method',
336:      *    'aliasedmethod' => 'somethingElse'
337:      *  ]
338:      * ```
339:      *
340:      * With the above example, a call to `$Table->method()` will call `$Behavior->method()`
341:      * and a call to `$Table->aliasedmethod()` will call `$Behavior->somethingElse()`
342:      *
343:      * It is recommended, though not required, to define implementedFinders in the config property
344:      * of child classes such that it is not necessary to use reflections to derive the available
345:      * method list. See core behaviors for examples
346:      *
347:      * @return array
348:      * @throws \ReflectionException
349:      */
350:     public function implementedMethods()
351:     {
352:         $methods = $this->getConfig('implementedMethods');
353:         if (isset($methods)) {
354:             return $methods;
355:         }
356: 
357:         return $this->_reflectionCache()['methods'];
358:     }
359: 
360:     /**
361:      * Gets the methods implemented by this behavior
362:      *
363:      * Uses the implementedEvents() method to exclude callback methods.
364:      * Methods starting with `_` will be ignored, as will methods
365:      * declared on Cake\ORM\Behavior
366:      *
367:      * @return array
368:      * @throws \ReflectionException
369:      */
370:     protected function _reflectionCache()
371:     {
372:         $class = get_class($this);
373:         if (isset(self::$_reflectionCache[$class])) {
374:             return self::$_reflectionCache[$class];
375:         }
376: 
377:         $events = $this->implementedEvents();
378:         $eventMethods = [];
379:         foreach ($events as $e => $binding) {
380:             if (is_array($binding) && isset($binding['callable'])) {
381:                 /* @var string $callable */
382:                 $callable = $binding['callable'];
383:                 $binding = $callable;
384:             }
385:             $eventMethods[$binding] = true;
386:         }
387: 
388:         $baseClass = 'Cake\ORM\Behavior';
389:         if (isset(self::$_reflectionCache[$baseClass])) {
390:             $baseMethods = self::$_reflectionCache[$baseClass];
391:         } else {
392:             $baseMethods = get_class_methods($baseClass);
393:             self::$_reflectionCache[$baseClass] = $baseMethods;
394:         }
395: 
396:         $return = [
397:             'finders' => [],
398:             'methods' => []
399:         ];
400: 
401:         $reflection = new ReflectionClass($class);
402: 
403:         foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
404:             $methodName = $method->getName();
405:             if (in_array($methodName, $baseMethods, true) ||
406:                 isset($eventMethods[$methodName])
407:             ) {
408:                 continue;
409:             }
410: 
411:             if (substr($methodName, 0, 4) === 'find') {
412:                 $return['finders'][lcfirst(substr($methodName, 4))] = $methodName;
413:             } else {
414:                 $return['methods'][$methodName] = $methodName;
415:             }
416:         }
417: 
418:         return self::$_reflectionCache[$class] = $return;
419:     }
420: }
421: 
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