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

  • 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: 
116:     use InstanceConfigTrait;
117: 
118:     /**
119:      * Table instance.
120:      *
121:      * @var \Cake\ORM\Table
122:      */
123:     protected $_table;
124: 
125:     /**
126:      * Reflection method cache for behaviors.
127:      *
128:      * Stores the reflected method + finder methods per class.
129:      * This prevents reflecting the same class multiple times in a single process.
130:      *
131:      * @var array
132:      */
133:     protected static $_reflectionCache = [];
134: 
135:     /**
136:      * Default configuration
137:      *
138:      * These are merged with user-provided configuration when the behavior is used.
139:      *
140:      * @var array
141:      */
142:     protected $_defaultConfig = [];
143: 
144:     /**
145:      * Constructor
146:      *
147:      * Merges config with the default and store in the config property
148:      *
149:      * @param \Cake\ORM\Table $table The table this behavior is attached to.
150:      * @param array $config The config for this behavior.
151:      */
152:     public function __construct(Table $table, array $config = [])
153:     {
154:         $config = $this->_resolveMethodAliases(
155:             'implementedFinders',
156:             $this->_defaultConfig,
157:             $config
158:         );
159:         $config = $this->_resolveMethodAliases(
160:             'implementedMethods',
161:             $this->_defaultConfig,
162:             $config
163:         );
164:         $this->_table = $table;
165:         $this->setConfig($config);
166:         $this->initialize($config);
167:     }
168: 
169:     /**
170:      * Constructor hook method.
171:      *
172:      * Implement this method to avoid having to overwrite
173:      * the constructor and call parent.
174:      *
175:      * @param array $config The configuration settings provided to this behavior.
176:      * @return void
177:      */
178:     public function initialize(array $config)
179:     {
180:     }
181: 
182:     /**
183:      * Get the table instance this behavior is bound to.
184:      *
185:      * @return \Cake\ORM\Table The bound table instance.
186:      */
187:     public function getTable()
188:     {
189:         return $this->_table;
190:     }
191: 
192:     /**
193:      * Removes aliased methods that would otherwise be duplicated by userland configuration.
194:      *
195:      * @param string $key The key to filter.
196:      * @param array $defaults The default method mappings.
197:      * @param array $config The customized method mappings.
198:      * @return array A de-duped list of config data.
199:      */
200:     protected function _resolveMethodAliases($key, $defaults, $config)
201:     {
202:         if (!isset($defaults[$key], $config[$key])) {
203:             return $config;
204:         }
205:         if (isset($config[$key]) && $config[$key] === []) {
206:             $this->setConfig($key, [], false);
207:             unset($config[$key]);
208: 
209:             return $config;
210:         }
211: 
212:         $indexed = array_flip($defaults[$key]);
213:         $indexedCustom = array_flip($config[$key]);
214:         foreach ($indexed as $method => $alias) {
215:             if (!isset($indexedCustom[$method])) {
216:                 $indexedCustom[$method] = $alias;
217:             }
218:         }
219:         $this->setConfig($key, array_flip($indexedCustom), false);
220:         unset($config[$key]);
221: 
222:         return $config;
223:     }
224: 
225:     /**
226:      * verifyConfig
227:      *
228:      * Checks that implemented keys contain values pointing at callable.
229:      *
230:      * @return void
231:      * @throws \Cake\Core\Exception\Exception if config are invalid
232:      */
233:     public function verifyConfig()
234:     {
235:         $keys = ['implementedFinders', 'implementedMethods'];
236:         foreach ($keys as $key) {
237:             if (!isset($this->_config[$key])) {
238:                 continue;
239:             }
240: 
241:             foreach ($this->_config[$key] as $method) {
242:                 if (!is_callable([$this, $method])) {
243:                     throw new Exception(sprintf('The method %s is not callable on class %s', $method, get_class($this)));
244:                 }
245:             }
246:         }
247:     }
248: 
249:     /**
250:      * Gets the Model callbacks this behavior is interested in.
251:      *
252:      * By defining one of the callback methods a behavior is assumed
253:      * to be interested in the related event.
254:      *
255:      * Override this method if you need to add non-conventional event listeners.
256:      * Or if you want your behavior to listen to non-standard events.
257:      *
258:      * @return array
259:      */
260:     public function implementedEvents()
261:     {
262:         $eventMap = [
263:             'Model.beforeMarshal' => 'beforeMarshal',
264:             'Model.beforeFind' => 'beforeFind',
265:             'Model.beforeSave' => 'beforeSave',
266:             'Model.afterSave' => 'afterSave',
267:             'Model.afterSaveCommit' => 'afterSaveCommit',
268:             'Model.beforeDelete' => 'beforeDelete',
269:             'Model.afterDelete' => 'afterDelete',
270:             'Model.afterDeleteCommit' => 'afterDeleteCommit',
271:             'Model.buildValidator' => 'buildValidator',
272:             'Model.buildRules' => 'buildRules',
273:             'Model.beforeRules' => 'beforeRules',
274:             'Model.afterRules' => 'afterRules',
275:         ];
276:         $config = $this->getConfig();
277:         $priority = isset($config['priority']) ? $config['priority'] : null;
278:         $events = [];
279: 
280:         foreach ($eventMap as $event => $method) {
281:             if (!method_exists($this, $method)) {
282:                 continue;
283:             }
284:             if ($priority === null) {
285:                 $events[$event] = $method;
286:             } else {
287:                 $events[$event] = [
288:                     'callable' => $method,
289:                     'priority' => $priority
290:                 ];
291:             }
292:         }
293: 
294:         return $events;
295:     }
296: 
297:     /**
298:      * implementedFinders
299:      *
300:      * Provides an alias->methodname map of which finders a behavior implements. Example:
301:      *
302:      * ```
303:      *  [
304:      *    'this' => 'findThis',
305:      *    'alias' => 'findMethodName'
306:      *  ]
307:      * ```
308:      *
309:      * With the above example, a call to `$Table->find('this')` will call `$Behavior->findThis()`
310:      * and a call to `$Table->find('alias')` will call `$Behavior->findMethodName()`
311:      *
312:      * It is recommended, though not required, to define implementedFinders in the config property
313:      * of child classes such that it is not necessary to use reflections to derive the available
314:      * method list. See core behaviors for examples
315:      *
316:      * @return array
317:      * @throws \ReflectionException
318:      */
319:     public function implementedFinders()
320:     {
321:         $methods = $this->getConfig('implementedFinders');
322:         if (isset($methods)) {
323:             return $methods;
324:         }
325: 
326:         return $this->_reflectionCache()['finders'];
327:     }
328: 
329:     /**
330:      * implementedMethods
331:      *
332:      * Provides an alias->methodname map of which methods a behavior implements. Example:
333:      *
334:      * ```
335:      *  [
336:      *    'method' => 'method',
337:      *    'aliasedmethod' => 'somethingElse'
338:      *  ]
339:      * ```
340:      *
341:      * With the above example, a call to `$Table->method()` will call `$Behavior->method()`
342:      * and a call to `$Table->aliasedmethod()` will call `$Behavior->somethingElse()`
343:      *
344:      * It is recommended, though not required, to define implementedFinders in the config property
345:      * of child classes such that it is not necessary to use reflections to derive the available
346:      * method list. See core behaviors for examples
347:      *
348:      * @return array
349:      * @throws \ReflectionException
350:      */
351:     public function implementedMethods()
352:     {
353:         $methods = $this->getConfig('implementedMethods');
354:         if (isset($methods)) {
355:             return $methods;
356:         }
357: 
358:         return $this->_reflectionCache()['methods'];
359:     }
360: 
361:     /**
362:      * Gets the methods implemented by this behavior
363:      *
364:      * Uses the implementedEvents() method to exclude callback methods.
365:      * Methods starting with `_` will be ignored, as will methods
366:      * declared on Cake\ORM\Behavior
367:      *
368:      * @return array
369:      * @throws \ReflectionException
370:      */
371:     protected function _reflectionCache()
372:     {
373:         $class = get_class($this);
374:         if (isset(self::$_reflectionCache[$class])) {
375:             return self::$_reflectionCache[$class];
376:         }
377: 
378:         $events = $this->implementedEvents();
379:         $eventMethods = [];
380:         foreach ($events as $e => $binding) {
381:             if (is_array($binding) && isset($binding['callable'])) {
382:                 /* @var string $callable */
383:                 $callable = $binding['callable'];
384:                 $binding = $callable;
385:             }
386:             $eventMethods[$binding] = true;
387:         }
388: 
389:         $baseClass = 'Cake\ORM\Behavior';
390:         if (isset(self::$_reflectionCache[$baseClass])) {
391:             $baseMethods = self::$_reflectionCache[$baseClass];
392:         } else {
393:             $baseMethods = get_class_methods($baseClass);
394:             self::$_reflectionCache[$baseClass] = $baseMethods;
395:         }
396: 
397:         $return = [
398:             'finders' => [],
399:             'methods' => []
400:         ];
401: 
402:         $reflection = new ReflectionClass($class);
403: 
404:         foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
405:             $methodName = $method->getName();
406:             if (in_array($methodName, $baseMethods) ||
407:                 isset($eventMethods[$methodName])
408:             ) {
409:                 continue;
410:             }
411: 
412:             if (substr($methodName, 0, 4) === 'find') {
413:                 $return['finders'][lcfirst(substr($methodName, 4))] = $methodName;
414:             } else {
415:                 $return['methods'][$methodName] = $methodName;
416:             }
417:         }
418: 
419:         return self::$_reflectionCache[$class] = $return;
420:     }
421: }
422: 
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