hasMany() public method

Target table can be inferred by its name, which is provided in the first argument, or you can either pass the class name to be instantiated or an instance of it directly. The options array accept the following keys: - className: The class name of the target table object - targetTable: An instance of a table object to be used as the target table - foreignKey: The name of the field to use as foreign key, if false none will be used - dependent: Set to true if you want CakePHP to cascade deletes to the associated table when an entity is removed on this table. The delete operation on the associated table will not cascade further. To get recursive cascades enable cascadeCallbacks as well. Set to false if you don't want CakePHP to remove associated data, or when you are using database constraints. - cascadeCallbacks: Set to true if you want CakePHP to fire callbacks on cascaded deletes. If false the ORM will use deleteAll() to remove data. When true records will be loaded and then deleted. - conditions: array with a list of conditions to filter the join with - sort: The order in which results for this association should be returned - saveStrategy: Either 'append' or 'replace'. When 'append' the current records are appended to any records in the database. When 'replace' associated records not in the current set will be removed. If the foreign key is a null able column or if dependent is true records will be orphaned. - strategy: The strategy to be used for selecting results Either 'select' or 'subquery'. If subquery is selected the query used to return results in the source table will be used as conditions for getting rows in the target table. - finder: The finder method to use when loading records from this association. Defaults to 'all'. This method will return the association object that was built.
public hasMany ( string $associated, array $options = [] ) : Cake\ORM\Association\HasMany
$associated string the alias for the target table. This is used to uniquely identify the association
$options array list of options to configure the association definition
return Cake\ORM\Association\HasMany
 /**
  * Creates the associations between the bound table and every field passed to
  * this method.
  *
  * Additionally it creates a `i18n` HasMany association that will be
  * used for fetching all versions for each record in the bound table
  *
  * @param string $table the table name to use for storing each field version
  * @return void
  */
 public function setupFieldAssociations($table)
 {
     $alias = $this->_table->alias();
     foreach ($this->_fields() as $field) {
         $name = $this->_table->alias() . '_' . $field . '_version';
         $target = TableRegistry::get($name);
         $target->table($table);
         $this->_table->hasOne($name, ['targetTable' => $target, 'foreignKey' => 'foreign_key', 'joinType' => 'LEFT', 'conditions' => [$name . '.model' => $alias, $name . '.field' => $field], 'propertyName' => $field . '_version']);
     }
     $this->_table->hasMany($table, ['foreignKey' => 'foreign_key', 'strategy' => 'subquery', 'conditions' => ["{$table}.model" => $alias], 'propertyName' => '__version', 'dependent' => true]);
 }
 /**
  * Creates the associations between the bound table and every field passed to
  * this method.
  *
  * Additionally it creates a `i18n` HasMany association that will be
  * used for fetching all translations for each record in the bound table
  *
  * @param array $fields list of fields to create associations for
  * @param string $table the table name to use for storing each field translation
  * @param string $model the model field value
  * @param string $strategy the strategy used in the _i18n association
  *
  * @return void
  */
 public function setupFieldAssociations($fields, $table, $model, $strategy)
 {
     $targetAlias = $this->_translationTable->alias();
     $alias = $this->_table->alias();
     $filter = $this->_config['onlyTranslated'];
     $tableLocator = $this->tableLocator();
     foreach ($fields as $field) {
         $name = $alias . '_' . $field . '_translation';
         if (!$tableLocator->exists($name)) {
             $fieldTable = $tableLocator->get($name, ['className' => $table, 'alias' => $name, 'table' => $this->_translationTable->table()]);
         } else {
             $fieldTable = $tableLocator->get($name);
         }
         $conditions = [$name . '.model' => $model, $name . '.field' => $field];
         if (!$this->_config['allowEmptyTranslations']) {
             $conditions[$name . '.content !='] = '';
         }
         $this->_table->hasOne($name, ['targetTable' => $fieldTable, 'foreignKey' => 'foreign_key', 'joinType' => $filter ? 'INNER' : 'LEFT', 'conditions' => $conditions, 'propertyName' => $field . '_translation']);
     }
     $conditions = ["{$targetAlias}.model" => $model];
     if (!$this->_config['allowEmptyTranslations']) {
         $conditions["{$targetAlias}.content !="] = '';
     }
     $this->_table->hasMany($targetAlias, ['className' => $table, 'foreignKey' => 'foreign_key', 'strategy' => $strategy, 'conditions' => $conditions, 'propertyName' => '_i18n', 'dependent' => true]);
 }
 /**
  * Returns association object for all versions or single field version.
  *
  * @param string|null $field Field name for per-field association.
  * @param array $options Association options.
  * @return \Cake\ORM\Association
  */
 public function versionAssociation($field = null, $options = [])
 {
     $name = $this->_associationName($field);
     if (!$this->_table->associations()->has($name)) {
         $model = $this->_config['referenceName'];
         if ($field) {
             $this->_table->hasOne($name, $options + ['className' => $this->_config['versionTable'], 'foreignKey' => $this->_config['foreignKey'], 'joinType' => 'LEFT', 'conditions' => [$name . '.model' => $model, $name . '.field' => $field], 'propertyName' => $field . '_version']);
         } else {
             $this->_table->hasMany($name, $options + ['className' => $this->_config['versionTable'], 'foreignKey' => $this->_config['foreignKey'], 'strategy' => 'subquery', 'conditions' => ["{$name}.model" => $model], 'propertyName' => '__version', 'dependent' => true]);
         }
     }
     return $this->_table->association($name);
 }
 /**
  * Test that the associated entities are unlinked and deleted when they have a not nullable foreign key
  *
  * @return void
  */
 public function testSaveReplaceSaveStrategyAdding()
 {
     $articles = new Table(['table' => 'articles', 'alias' => 'Articles', 'connection' => $this->connection, 'entityClass' => 'Cake\\ORM\\Entity']);
     $articles->hasMany('Comments', ['saveStrategy' => 'replace']);
     $article = $articles->newEntity(['title' => 'Bakeries are sky rocketing', 'body' => 'All because of cake', 'comments' => [['user_id' => 1, 'comment' => 'That is true!'], ['user_id' => 2, 'comment' => 'Of course']]], ['associated' => ['Comments']]);
     $article = $articles->save($article, ['associated' => ['Comments']]);
     $commentId = $article->comments[0]->id;
     $sizeComments = count($article->comments);
     $articleId = $article->id;
     $this->assertEquals($sizeComments, $articles->Comments->find('all')->where(['article_id' => $article->id])->count());
     $this->assertTrue($articles->Comments->exists(['id' => $commentId]));
     unset($article->comments[0]);
     $article->comments[] = $articles->Comments->newEntity(['user_id' => 1, 'comment' => 'new comment']);
     $article->dirty('comments', true);
     $article = $articles->save($article, ['associated' => ['Comments']]);
     $this->assertEquals($sizeComments, $articles->Comments->find('all')->where(['article_id' => $article->id])->count());
     $this->assertFalse($articles->Comments->exists(['id' => $commentId]));
     $this->assertTrue($articles->Comments->exists(['to_char(comment)' => 'new comment', 'article_id' => $articleId]));
 }
 /**
  * Creates the associations between the bound table and every field passed to
  * this method.
  *
  * Additionally it creates a `i18n` HasMany association that will be
  * used for fetching all translations for each record in the bound table
  *
  * @param array $fields list of fields to create associations for
  * @param string $table the table name to use for storing each field translation
  * @param array $fieldConditions conditions for finding fields
  * @param string $strategy the strategy used in the _i18n association
  *
  * @return void
  */
 public function setupFieldAssociations($fields, $table, $fieldConditions, $strategy)
 {
     $targetAlias = $this->_translationTable->alias();
     $alias = $this->_table->alias();
     $filter = $this->_config['onlyTranslated'];
     foreach ($fields as $field) {
         $name = $alias . '_' . $field . '_translation';
         $conditions = [$name . '.model' => $fieldConditions['model'], $name . '.field' => $field];
         foreach ($fieldConditions as $fieldName => $fieldValue) {
             $conditions[$name . '.' . $fieldName] = $fieldValue;
         }
         if (!TableRegistry::exists($name)) {
             $fieldTable = TableRegistry::get($name, ['className' => $table, 'alias' => $name, 'table' => $this->_translationTable->table()]);
         } else {
             $fieldTable = TableRegistry::get($name);
         }
         $this->_table->hasOne($name, ['targetTable' => $fieldTable, 'foreignKey' => 'foreign_key', 'joinType' => $filter ? 'INNER' : 'LEFT', 'conditions' => $conditions, 'propertyName' => $field . '_translation']);
     }
     $this->_table->hasMany($targetAlias, ['className' => $table, 'foreignKey' => 'foreign_key', 'strategy' => $strategy, 'conditions' => ["{$targetAlias}.model" => $fieldConditions['model']], 'propertyName' => '_i18n', 'dependent' => true]);
 }
Example #6
0
 /**
  * Generate additional source table associations as necessary.
  *
  * Generates the following associations:
  *
  * - source hasMany junction e.g. Tags hasMany ArticlesTags
  *
  * You can override these generated associations by defining associations
  * with the correct aliases.
  *
  * @param \Cake\ORM\Table $junction The junction table.
  * @param \Cake\ORM\Table $source The source table.
  * @return void
  */
 protected function _generateSourceAssociations($junction, $source)
 {
     $junctionAlias = $junction->alias();
     if (!$source->association($junctionAlias)) {
         $source->hasMany($junctionAlias, ['targetTable' => $junction, 'foreignKey' => $this->foreignKey()]);
     }
 }
Example #7
0
 /**
  * Integration test for replacing entities with HasMany and no already persisted entities. The transaction must be successfull.
  * Replace operation should prevent considering 0 changed records an error when they are not found in the table
  *
  * @return void
  */
 public function testReplaceHasManyNoPersistedEntities()
 {
     $authors = new Table(['connection' => $this->connection, 'alias' => 'Authors', 'table' => 'authors']);
     $authors->hasMany('Articles');
     $author = $authors->newEntity(['name' => 'mylux']);
     $author = $authors->save($author);
     $newArticles = $authors->Articles->newEntities([['title' => 'New bakery next corner', 'body' => 'They sell tastefull cakes'], ['title' => 'Spicy cake recipe', 'body' => 'chocolate and peppers']]);
     $authors->Articles->deleteAll(['1=1']);
     $sizeArticles = count($newArticles);
     $this->assertTrue($authors->Articles->link($author, $newArticles));
     $this->assertEquals($authors->Articles->findAllByAuthorId($author->id)->count(), $sizeArticles);
     $this->assertEquals(count($author->articles), $sizeArticles);
     $this->assertTrue($authors->Articles->replace($author, $newArticles));
     $this->assertCount($sizeArticles, $authors->Articles->findAllByAuthorId($author->id));
 }
 /**
  * Ensure associations use the plugin-prefixed model
  * even if specified with config
  *
  * @return void
  */
 public function testHasManyPluginOverlapConfig()
 {
     TableRegistry::get('Comments');
     Plugin::load('TestPlugin');
     $table = new Table(['table' => 'authors']);
     $table->hasMany('Comments', ['className' => 'TestPlugin.Comments']);
     $comments = $table->Comments->target();
     $this->assertInstanceOf('TestPlugin\\Model\\Table\\CommentsTable', $comments);
 }
Example #9
0
 /**
  * Tests that hasMany() creates and configures correctly the association
  *
  * @return void
  */
 public function testHasMany()
 {
     $options = ['foreignKey' => 'author_id', 'conditions' => ['b' => 'c'], 'sort' => ['foo' => 'asc']];
     $table = new Table(['table' => 'authors']);
     $hasMany = $table->hasMany('article', $options);
     $this->assertInstanceOf('Cake\\ORM\\Association\\HasMany', $hasMany);
     $this->assertSame($hasMany, $table->association('article'));
     $this->assertEquals('article', $hasMany->name());
     $this->assertEquals('author_id', $hasMany->foreignKey());
     $this->assertEquals(['b' => 'c'], $hasMany->conditions());
     $this->assertEquals(['foo' => 'asc'], $hasMany->sort());
     $this->assertSame($table, $hasMany->source());
 }
 /**
  * Constructor.
  *
  * Here we associate `Comments` table with the table this behavior is attached to.
  *
  * @param \Cake\ORM\Table $table The table this behavior is attached to.
  * @param array $config The config for this behavior.
  */
 public function __construct(Table $table, array $config = [])
 {
     $this->_table = $table;
     $this->_table->hasMany('Comments', ['className' => 'Comment.Comments', 'foreignKey' => 'entity_id', 'conditions' => ['table_alias' => Inflector::underscore($this->_table->alias()), 'status' => 'approved'], 'joinType' => 'LEFT', 'dependent' => true]);
     parent::__construct($table, $config);
 }