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

  • BelongsTo
  • BelongsToMany
  • HasMany
  • HasOne

Traits

  • DependentDeleteTrait
  1: <?php
  2: /**
  3:  *
  4:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6:  *
  7:  * Licensed under The MIT License
  8:  * For full copyright and license information, please see the LICENSE.txt
  9:  * Redistributions of files must retain the above copyright notice.
 10:  *
 11:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 12:  * @link          https://cakephp.org CakePHP(tm) Project
 13:  * @since         3.0.0
 14:  * @license       https://opensource.org/licenses/mit-license.php MIT License
 15:  */
 16: namespace Cake\ORM\Association;
 17: 
 18: use Cake\Collection\Collection;
 19: use Cake\Database\Expression\FieldInterface;
 20: use Cake\Database\Expression\QueryExpression;
 21: use Cake\Datasource\EntityInterface;
 22: use Cake\Datasource\QueryInterface;
 23: use Cake\ORM\Association;
 24: use Cake\ORM\Association\DependentDeleteHelper;
 25: use Cake\ORM\Association\Loader\SelectLoader;
 26: use Cake\ORM\Table;
 27: use InvalidArgumentException;
 28: use Traversable;
 29: 
 30: /**
 31:  * Represents an N - 1 relationship where the target side of the relationship
 32:  * will have one or multiple records per each one in the source side.
 33:  *
 34:  * An example of a HasMany association would be Author has many Articles.
 35:  */
 36: class HasMany extends Association
 37: {
 38:     /**
 39:      * Order in which target records should be returned
 40:      *
 41:      * @var mixed
 42:      */
 43:     protected $_sort;
 44: 
 45:     /**
 46:      * The type of join to be used when adding the association to a query
 47:      *
 48:      * @var string
 49:      */
 50:     protected $_joinType = QueryInterface::JOIN_TYPE_INNER;
 51: 
 52:     /**
 53:      * The strategy name to be used to fetch associated records.
 54:      *
 55:      * @var string
 56:      */
 57:     protected $_strategy = self::STRATEGY_SELECT;
 58: 
 59:     /**
 60:      * Valid strategies for this type of association
 61:      *
 62:      * @var array
 63:      */
 64:     protected $_validStrategies = [
 65:         self::STRATEGY_SELECT,
 66:         self::STRATEGY_SUBQUERY
 67:     ];
 68: 
 69:     /**
 70:      * Saving strategy that will only append to the links set
 71:      *
 72:      * @var string
 73:      */
 74:     const SAVE_APPEND = 'append';
 75: 
 76:     /**
 77:      * Saving strategy that will replace the links with the provided set
 78:      *
 79:      * @var string
 80:      */
 81:     const SAVE_REPLACE = 'replace';
 82: 
 83:     /**
 84:      * Saving strategy to be used by this association
 85:      *
 86:      * @var string
 87:      */
 88:     protected $_saveStrategy = self::SAVE_APPEND;
 89: 
 90:     /**
 91:      * Returns whether or not the passed table is the owning side for this
 92:      * association. This means that rows in the 'target' table would miss important
 93:      * or required information if the row in 'source' did not exist.
 94:      *
 95:      * @param \Cake\ORM\Table $side The potential Table with ownership
 96:      * @return bool
 97:      */
 98:     public function isOwningSide(Table $side)
 99:     {
100:         return $side === $this->getSource();
101:     }
102: 
103:     /**
104:      * Sets the strategy that should be used for saving.
105:      *
106:      * @param string $strategy the strategy name to be used
107:      * @throws \InvalidArgumentException if an invalid strategy name is passed
108:      * @return $this
109:      */
110:     public function setSaveStrategy($strategy)
111:     {
112:         if (!in_array($strategy, [self::SAVE_APPEND, self::SAVE_REPLACE], true)) {
113:             $msg = sprintf('Invalid save strategy "%s"', $strategy);
114:             throw new InvalidArgumentException($msg);
115:         }
116: 
117:         $this->_saveStrategy = $strategy;
118: 
119:         return $this;
120:     }
121: 
122:     /**
123:      * Gets the strategy that should be used for saving.
124:      *
125:      * @return string the strategy to be used for saving
126:      */
127:     public function getSaveStrategy()
128:     {
129:         return $this->_saveStrategy;
130:     }
131: 
132:     /**
133:      * Sets the strategy that should be used for saving. If called with no
134:      * arguments, it will return the currently configured strategy
135:      *
136:      * @deprecated 3.4.0 Use setSaveStrategy()/getSaveStrategy() instead.
137:      * @param string|null $strategy the strategy name to be used
138:      * @throws \InvalidArgumentException if an invalid strategy name is passed
139:      * @return string the strategy to be used for saving
140:      */
141:     public function saveStrategy($strategy = null)
142:     {
143:         deprecationWarning(
144:             'HasMany::saveStrategy() is deprecated. ' .
145:             'Use setSaveStrategy()/getSaveStrategy() instead.'
146:         );
147:         if ($strategy !== null) {
148:             $this->setSaveStrategy($strategy);
149:         }
150: 
151:         return $this->getSaveStrategy();
152:     }
153: 
154:     /**
155:      * Takes an entity from the source table and looks if there is a field
156:      * matching the property name for this association. The found entity will be
157:      * saved on the target table for this association by passing supplied
158:      * `$options`
159:      *
160:      * @param \Cake\Datasource\EntityInterface $entity an entity from the source table
161:      * @param array $options options to be passed to the save method in the target table
162:      * @return bool|\Cake\Datasource\EntityInterface false if $entity could not be saved, otherwise it returns
163:      * the saved entity
164:      * @see \Cake\ORM\Table::save()
165:      * @throws \InvalidArgumentException when the association data cannot be traversed.
166:      */
167:     public function saveAssociated(EntityInterface $entity, array $options = [])
168:     {
169:         $targetEntities = $entity->get($this->getProperty());
170: 
171:         $isEmpty = in_array($targetEntities, [null, [], '', false], true);
172:         if ($isEmpty) {
173:             if ($entity->isNew() ||
174:                 $this->getSaveStrategy() !== self::SAVE_REPLACE
175:             ) {
176:                 return $entity;
177:             }
178: 
179:             $targetEntities = [];
180:         }
181: 
182:         if (!is_array($targetEntities) &&
183:             !($targetEntities instanceof Traversable)
184:         ) {
185:             $name = $this->getProperty();
186:             $message = sprintf('Could not save %s, it cannot be traversed', $name);
187:             throw new InvalidArgumentException($message);
188:         }
189: 
190:         $foreignKeyReference = array_combine(
191:             (array)$this->getForeignKey(),
192:             $entity->extract((array)$this->getBindingKey())
193:         );
194: 
195:         $options['_sourceTable'] = $this->getSource();
196: 
197:         if ($this->_saveStrategy === self::SAVE_REPLACE &&
198:             !$this->_unlinkAssociated($foreignKeyReference, $entity, $this->getTarget(), $targetEntities, $options)
199:         ) {
200:             return false;
201:         }
202: 
203:         if (!$this->_saveTarget($foreignKeyReference, $entity, $targetEntities, $options)) {
204:             return false;
205:         }
206: 
207:         return $entity;
208:     }
209: 
210:     /**
211:      * Persists each of the entities into the target table and creates links between
212:      * the parent entity and each one of the saved target entities.
213:      *
214:      * @param array $foreignKeyReference The foreign key reference defining the link between the
215:      * target entity, and the parent entity.
216:      * @param \Cake\Datasource\EntityInterface $parentEntity The source entity containing the target
217:      * entities to be saved.
218:      * @param array|\Traversable $entities list of entities to persist in target table and to
219:      * link to the parent entity
220:      * @param array $options list of options accepted by `Table::save()`.
221:      * @return bool `true` on success, `false` otherwise.
222:      */
223:     protected function _saveTarget(array $foreignKeyReference, EntityInterface $parentEntity, $entities, array $options)
224:     {
225:         $foreignKey = array_keys($foreignKeyReference);
226:         $table = $this->getTarget();
227:         $original = $entities;
228: 
229:         foreach ($entities as $k => $entity) {
230:             if (!($entity instanceof EntityInterface)) {
231:                 break;
232:             }
233: 
234:             if (!empty($options['atomic'])) {
235:                 $entity = clone $entity;
236:             }
237: 
238:             if ($foreignKeyReference !== $entity->extract($foreignKey)) {
239:                 $entity->set($foreignKeyReference, ['guard' => false]);
240:             }
241: 
242:             if ($table->save($entity, $options)) {
243:                 $entities[$k] = $entity;
244:                 continue;
245:             }
246: 
247:             if (!empty($options['atomic'])) {
248:                 $original[$k]->setErrors($entity->getErrors());
249:                 $entity->set($this->getProperty(), $original);
250: 
251:                 return false;
252:             }
253:         }
254: 
255:         $parentEntity->set($this->getProperty(), $entities);
256: 
257:         return true;
258:     }
259: 
260:     /**
261:      * Associates the source entity to each of the target entities provided.
262:      * When using this method, all entities in `$targetEntities` will be appended to
263:      * the source entity's property corresponding to this association object.
264:      *
265:      * This method does not check link uniqueness.
266:      * Changes are persisted in the database and also in the source entity.
267:      *
268:      * ### Example:
269:      *
270:      * ```
271:      * $user = $users->get(1);
272:      * $allArticles = $articles->find('all')->toArray();
273:      * $users->Articles->link($user, $allArticles);
274:      * ```
275:      *
276:      * `$user->get('articles')` will contain all articles in `$allArticles` after linking
277:      *
278:      * @param \Cake\Datasource\EntityInterface $sourceEntity the row belonging to the `source` side
279:      * of this association
280:      * @param array $targetEntities list of entities belonging to the `target` side
281:      * of this association
282:      * @param array $options list of options to be passed to the internal `save` call
283:      * @return bool true on success, false otherwise
284:      */
285:     public function link(EntityInterface $sourceEntity, array $targetEntities, array $options = [])
286:     {
287:         $saveStrategy = $this->getSaveStrategy();
288:         $this->setSaveStrategy(self::SAVE_APPEND);
289:         $property = $this->getProperty();
290: 
291:         $currentEntities = array_unique(
292:             array_merge(
293:                 (array)$sourceEntity->get($property),
294:                 $targetEntities
295:             )
296:         );
297: 
298:         $sourceEntity->set($property, $currentEntities);
299: 
300:         $savedEntity = $this->getConnection()->transactional(function () use ($sourceEntity, $options) {
301:             return $this->saveAssociated($sourceEntity, $options);
302:         });
303: 
304:         $ok = ($savedEntity instanceof EntityInterface);
305: 
306:         $this->setSaveStrategy($saveStrategy);
307: 
308:         if ($ok) {
309:             $sourceEntity->set($property, $savedEntity->get($property));
310:             $sourceEntity->setDirty($property, false);
311:         }
312: 
313:         return $ok;
314:     }
315: 
316:     /**
317:      * Removes all links between the passed source entity and each of the provided
318:      * target entities. This method assumes that all passed objects are already persisted
319:      * in the database and that each of them contain a primary key value.
320:      *
321:      * ### Options
322:      *
323:      * Additionally to the default options accepted by `Table::delete()`, the following
324:      * keys are supported:
325:      *
326:      * - cleanProperty: Whether or not to remove all the objects in `$targetEntities` that
327:      * are stored in `$sourceEntity` (default: true)
328:      *
329:      * By default this method will unset each of the entity objects stored inside the
330:      * source entity.
331:      *
332:      * Changes are persisted in the database and also in the source entity.
333:      *
334:      * ### Example:
335:      *
336:      * ```
337:      * $user = $users->get(1);
338:      * $user->articles = [$article1, $article2, $article3, $article4];
339:      * $users->save($user, ['Associated' => ['Articles']]);
340:      * $allArticles = [$article1, $article2, $article3];
341:      * $users->Articles->unlink($user, $allArticles);
342:      * ```
343:      *
344:      * `$article->get('articles')` will contain only `[$article4]` after deleting in the database
345:      *
346:      * @param \Cake\Datasource\EntityInterface $sourceEntity an entity persisted in the source table for
347:      * this association
348:      * @param array $targetEntities list of entities persisted in the target table for
349:      * this association
350:      * @param array $options list of options to be passed to the internal `delete` call
351:      * @throws \InvalidArgumentException if non persisted entities are passed or if
352:      * any of them is lacking a primary key value
353:      * @return void
354:      */
355:     public function unlink(EntityInterface $sourceEntity, array $targetEntities, $options = [])
356:     {
357:         if (is_bool($options)) {
358:             $options = [
359:                 'cleanProperty' => $options
360:             ];
361:         } else {
362:             $options += ['cleanProperty' => true];
363:         }
364:         if (count($targetEntities) === 0) {
365:             return;
366:         }
367: 
368:         $foreignKey = (array)$this->getForeignKey();
369:         $target = $this->getTarget();
370:         $targetPrimaryKey = array_merge((array)$target->getPrimaryKey(), $foreignKey);
371:         $property = $this->getProperty();
372: 
373:         $conditions = [
374:             'OR' => (new Collection($targetEntities))
375:                 ->map(function ($entity) use ($targetPrimaryKey) {
376:                     /** @var \Cake\Datasource\EntityInterface $entity */
377:                     return $entity->extract($targetPrimaryKey);
378:                 })
379:                 ->toList()
380:         ];
381: 
382:         $this->_unlink($foreignKey, $target, $conditions, $options);
383: 
384:         $result = $sourceEntity->get($property);
385:         if ($options['cleanProperty'] && $result !== null) {
386:             $sourceEntity->set(
387:                 $property,
388:                 (new Collection($sourceEntity->get($property)))
389:                 ->reject(
390:                     function ($assoc) use ($targetEntities) {
391:                         return in_array($assoc, $targetEntities);
392:                     }
393:                 )
394:                 ->toList()
395:             );
396:         }
397: 
398:         $sourceEntity->setDirty($property, false);
399:     }
400: 
401:     /**
402:      * Replaces existing association links between the source entity and the target
403:      * with the ones passed. This method does a smart cleanup, links that are already
404:      * persisted and present in `$targetEntities` will not be deleted, new links will
405:      * be created for the passed target entities that are not already in the database
406:      * and the rest will be removed.
407:      *
408:      * For example, if an author has many articles, such as 'article1','article 2' and 'article 3' and you pass
409:      * to this method an array containing the entities for articles 'article 1' and 'article 4',
410:      * only the link for 'article 1' will be kept in database, the links for 'article 2' and 'article 3' will be
411:      * deleted and the link for 'article 4' will be created.
412:      *
413:      * Existing links are not deleted and created again, they are either left untouched
414:      * or updated.
415:      *
416:      * This method does not check link uniqueness.
417:      *
418:      * On success, the passed `$sourceEntity` will contain `$targetEntities` as value
419:      * in the corresponding property for this association.
420:      *
421:      * Additional options for new links to be saved can be passed in the third argument,
422:      * check `Table::save()` for information on the accepted options.
423:      *
424:      * ### Example:
425:      *
426:      * ```
427:      * $author->articles = [$article1, $article2, $article3, $article4];
428:      * $authors->save($author);
429:      * $articles = [$article1, $article3];
430:      * $authors->getAssociation('articles')->replace($author, $articles);
431:      * ```
432:      *
433:      * `$author->get('articles')` will contain only `[$article1, $article3]` at the end
434:      *
435:      * @param \Cake\Datasource\EntityInterface $sourceEntity an entity persisted in the source table for
436:      * this association
437:      * @param array $targetEntities list of entities from the target table to be linked
438:      * @param array $options list of options to be passed to the internal `save`/`delete` calls
439:      * when persisting/updating new links, or deleting existing ones
440:      * @throws \InvalidArgumentException if non persisted entities are passed or if
441:      * any of them is lacking a primary key value
442:      * @return bool success
443:      */
444:     public function replace(EntityInterface $sourceEntity, array $targetEntities, array $options = [])
445:     {
446:         $property = $this->getProperty();
447:         $sourceEntity->set($property, $targetEntities);
448:         $saveStrategy = $this->getSaveStrategy();
449:         $this->setSaveStrategy(self::SAVE_REPLACE);
450:         $result = $this->saveAssociated($sourceEntity, $options);
451:         $ok = ($result instanceof EntityInterface);
452: 
453:         if ($ok) {
454:             $sourceEntity = $result;
455:         }
456:         $this->setSaveStrategy($saveStrategy);
457: 
458:         return $ok;
459:     }
460: 
461:     /**
462:      * Deletes/sets null the related objects according to the dependency between source and targets and foreign key nullability
463:      * Skips deleting records present in $remainingEntities
464:      *
465:      * @param array $foreignKeyReference The foreign key reference defining the link between the
466:      * target entity, and the parent entity.
467:      * @param \Cake\Datasource\EntityInterface $entity the entity which should have its associated entities unassigned
468:      * @param \Cake\ORM\Table $target The associated table
469:      * @param array $remainingEntities Entities that should not be deleted
470:      * @param array $options list of options accepted by `Table::delete()`
471:      * @return bool success
472:      */
473:     protected function _unlinkAssociated(array $foreignKeyReference, EntityInterface $entity, Table $target, array $remainingEntities = [], array $options = [])
474:     {
475:         $primaryKey = (array)$target->getPrimaryKey();
476:         $exclusions = new Collection($remainingEntities);
477:         $exclusions = $exclusions->map(
478:             function ($ent) use ($primaryKey) {
479:                 /** @var \Cake\Datasource\EntityInterface $ent */
480:                 return $ent->extract($primaryKey);
481:             }
482:         )
483:         ->filter(
484:             function ($v) {
485:                 return !in_array(null, $v, true);
486:             }
487:         )
488:         ->toList();
489: 
490:         $conditions = $foreignKeyReference;
491: 
492:         if (count($exclusions) > 0) {
493:             $conditions = [
494:                 'NOT' => [
495:                     'OR' => $exclusions
496:                 ],
497:                 $foreignKeyReference
498:             ];
499:         }
500: 
501:         return $this->_unlink(array_keys($foreignKeyReference), $target, $conditions, $options);
502:     }
503: 
504:     /**
505:      * Deletes/sets null the related objects matching $conditions.
506:      * The action which is taken depends on the dependency between source and targets and also on foreign key nullability
507:      *
508:      * @param array $foreignKey array of foreign key properties
509:      * @param \Cake\ORM\Table $target The associated table
510:      * @param array $conditions The conditions that specifies what are the objects to be unlinked
511:      * @param array $options list of options accepted by `Table::delete()`
512:      * @return bool success
513:      */
514:     protected function _unlink(array $foreignKey, Table $target, array $conditions = [], array $options = [])
515:     {
516:         $mustBeDependent = (!$this->_foreignKeyAcceptsNull($target, $foreignKey) || $this->getDependent());
517: 
518:         if ($mustBeDependent) {
519:             if ($this->_cascadeCallbacks) {
520:                 $conditions = new QueryExpression($conditions);
521:                 $conditions->traverse(function ($entry) use ($target) {
522:                     if ($entry instanceof FieldInterface) {
523:                         $entry->setField($target->aliasField($entry->getField()));
524:                     }
525:                 });
526:                 $query = $this->find('all')->where($conditions);
527:                 $ok = true;
528:                 foreach ($query as $assoc) {
529:                     $ok = $ok && $target->delete($assoc, $options);
530:                 }
531: 
532:                 return $ok;
533:             }
534: 
535:             $conditions = array_merge($conditions, $this->getConditions());
536:             $target->deleteAll($conditions);
537: 
538:             return true;
539:         }
540: 
541:         $updateFields = array_fill_keys($foreignKey, null);
542:         $conditions = array_merge($conditions, $this->getConditions());
543:         $target->updateAll($updateFields, $conditions);
544: 
545:         return true;
546:     }
547: 
548:     /**
549:      * Checks the nullable flag of the foreign key
550:      *
551:      * @param \Cake\ORM\Table $table the table containing the foreign key
552:      * @param array $properties the list of fields that compose the foreign key
553:      * @return bool
554:      */
555:     protected function _foreignKeyAcceptsNull(Table $table, array $properties)
556:     {
557:         return !in_array(
558:             false,
559:             array_map(
560:                 function ($prop) use ($table) {
561:                     return $table->getSchema()->isNullable($prop);
562:                 },
563:                 $properties
564:             )
565:         );
566:     }
567: 
568:     /**
569:      * Get the relationship type.
570:      *
571:      * @return string
572:      */
573:     public function type()
574:     {
575:         return self::ONE_TO_MANY;
576:     }
577: 
578:     /**
579:      * Whether this association can be expressed directly in a query join
580:      *
581:      * @param array $options custom options key that could alter the return value
582:      * @return bool if the 'matching' key in $option is true then this function
583:      * will return true, false otherwise
584:      */
585:     public function canBeJoined(array $options = [])
586:     {
587:         return !empty($options['matching']);
588:     }
589: 
590:     /**
591:      * Gets the name of the field representing the foreign key to the source table.
592:      *
593:      * @return string
594:      */
595:     public function getForeignKey()
596:     {
597:         if ($this->_foreignKey === null) {
598:             $this->_foreignKey = $this->_modelKey($this->getSource()->getTable());
599:         }
600: 
601:         return $this->_foreignKey;
602:     }
603: 
604:     /**
605:      * Sets the sort order in which target records should be returned.
606:      *
607:      * @param mixed $sort A find() compatible order clause
608:      * @return $this
609:      */
610:     public function setSort($sort)
611:     {
612:         $this->_sort = $sort;
613: 
614:         return $this;
615:     }
616: 
617:     /**
618:      * Gets the sort order in which target records should be returned.
619:      *
620:      * @return mixed
621:      */
622:     public function getSort()
623:     {
624:         return $this->_sort;
625:     }
626: 
627:     /**
628:      * Sets the sort order in which target records should be returned.
629:      * If no arguments are passed the currently configured value is returned
630:      *
631:      * @deprecated 3.4.0 Use setSort()/getSort() instead.
632:      * @param mixed $sort A find() compatible order clause
633:      * @return mixed
634:      */
635:     public function sort($sort = null)
636:     {
637:         deprecationWarning(
638:             'HasMany::sort() is deprecated. ' .
639:             'Use setSort()/getSort() instead.'
640:         );
641:         if ($sort !== null) {
642:             $this->setSort($sort);
643:         }
644: 
645:         return $this->getSort();
646:     }
647: 
648:     /**
649:      * {@inheritDoc}
650:      */
651:     public function defaultRowValue($row, $joined)
652:     {
653:         $sourceAlias = $this->getSource()->getAlias();
654:         if (isset($row[$sourceAlias])) {
655:             $row[$sourceAlias][$this->getProperty()] = $joined ? null : [];
656:         }
657: 
658:         return $row;
659:     }
660: 
661:     /**
662:      * Parse extra options passed in the constructor.
663:      *
664:      * @param array $opts original list of options passed in constructor
665:      * @return void
666:      */
667:     protected function _options(array $opts)
668:     {
669:         if (!empty($opts['saveStrategy'])) {
670:             $this->setSaveStrategy($opts['saveStrategy']);
671:         }
672:         if (isset($opts['sort'])) {
673:             $this->setSort($opts['sort']);
674:         }
675:     }
676: 
677:     /**
678:      * {@inheritDoc}
679:      *
680:      * @return \Closure
681:      */
682:     public function eagerLoader(array $options)
683:     {
684:         $loader = new SelectLoader([
685:             'alias' => $this->getAlias(),
686:             'sourceAlias' => $this->getSource()->getAlias(),
687:             'targetAlias' => $this->getTarget()->getAlias(),
688:             'foreignKey' => $this->getForeignKey(),
689:             'bindingKey' => $this->getBindingKey(),
690:             'strategy' => $this->getStrategy(),
691:             'associationType' => $this->type(),
692:             'sort' => $this->getSort(),
693:             'finder' => [$this, 'find']
694:         ]);
695: 
696:         return $loader->buildEagerLoader($options);
697:     }
698: 
699:     /**
700:      * {@inheritDoc}
701:      */
702:     public function cascadeDelete(EntityInterface $entity, array $options = [])
703:     {
704:         $helper = new DependentDeleteHelper();
705: 
706:         return $helper->cascadeDelete($this, $entity, $options);
707:     }
708: }
709: 
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