/** * Changes the association fetching strategy if required because of duplicate * under the same direct associations chain * * @param \Cake\ORM\EagerLoadable $loadable The association config * @return void */ protected function _correctStrategy($loadable) { $config = $loadable->config(); $currentStrategy = isset($config['strategy']) ? $config['strategy'] : 'join'; if (!$loadable->canBeJoined() || $currentStrategy !== 'join') { return; } $config['strategy'] = Association::STRATEGY_SELECT; $loadable->config($config); $loadable->canBeJoined(false); }
/** * Auxiliary function responsible for fully normalizing deep associations defined * using `contain()` * * @param Table $parent owning side of the association * @param string $alias name of the association to be loaded * @param array $options list of extra options to use for this association * @param array $paths An array with two values, the first one is a list of dot * separated strings representing associations that lead to this `$alias` in the * chain of associations to be loaded. The second value is the path to follow in * entities' properties to fetch a record of the corresponding association. * @return array normalized associations * @throws \InvalidArgumentException When containments refer to associations that do not exist. */ protected function _normalizeContain(Table $parent, $alias, $options, $paths) { $defaults = $this->_containOptions; $instance = $parent->association($alias); if (!$instance) { throw new InvalidArgumentException(sprintf('%s is not associated with %s', $parent->alias(), $alias)); } if ($instance->alias() !== $alias) { throw new InvalidArgumentException(sprintf("You have contained '%s' but that association was bound as '%s'.", $alias, $instance->alias())); } $paths += ['aliasPath' => '', 'propertyPath' => '', 'root' => $alias]; $paths['aliasPath'] .= '.' . $alias; $paths['propertyPath'] .= '.' . $instance->property(); $table = $instance->target(); $extra = array_diff_key($options, $defaults); $config = ['associations' => [], 'instance' => $instance, 'config' => array_diff_key($options, $extra), 'aliasPath' => trim($paths['aliasPath'], '.'), 'propertyPath' => trim($paths['propertyPath'], '.')]; $config['canBeJoined'] = $instance->canBeJoined($config['config']); $eagerLoadable = new EagerLoadable($alias, $config); if ($config['canBeJoined']) { $this->_aliasList[$paths['root']][$alias][] = $eagerLoadable; } else { $paths['root'] = $config['aliasPath']; } foreach ($extra as $t => $assoc) { $eagerLoadable->addAssociation($t, $this->_normalizeContain($table, $t, $assoc, $paths)); } return $eagerLoadable; }