/** * Filter data on inner relation or relation chain. Method automatically called by Selector, * see with() method. Logic is identical to loader() method. * * @see Selector::load() * @param string $relation Relation name, or chain of relations separated by. * @param array $options Loader options (will be applied to last chain element only). * @return Loader * @throws LoaderException */ public function joiner($relation, array $options = []) { if (empty($options['method'])) { //We have to force joining method for full chain $options['method'] = self::JOIN; } if (($position = strpos($relation, '.')) !== false) { //Chain of relations provided $nested = $this->joiner(substr($relation, 0, $position), []); if (empty($nested) || !$nested instanceof self) { //todo: DRY throw new LoaderException("Only ORM loaders can be used to generate/configure chain of relation joiners."); } //Recursively (will work only with ORM loaders). return $nested->joiner(substr($relation, $position + 1), $options); } if (!isset($this->schema[ORM::M_RELATIONS][$relation])) { $container = $this->container ?: $this->schema[ORM::M_ROLE_NAME]; throw new LoaderException("Undefined relation '{$relation}' under '{$container}'."); } if (isset($this->joiners[$relation])) { //Updating existed joiner options return $this->joiners[$relation]->setOptions($options); } $relationOptions = $this->schema[ORM::M_RELATIONS][$relation]; $joiner = $this->orm->loader($relationOptions[ORM::R_TYPE], $relation, $relationOptions[ORM::R_DEFINITION], $this); if (!$joiner instanceof self) { //todo: DRY throw new LoaderException("Only ORM loaders can be used to generate/configure chain of relation joiners."); } return $this->joiners[$relation] = $joiner->setOptions($options); }