diff --git a/src/ORM/Table.php b/src/ORM/Table.php index 2ed26d1842d..92fdf60ed30 100644 --- a/src/ORM/Table.php +++ b/src/ORM/Table.php @@ -1213,7 +1213,7 @@ public function get($primaryKey, $options = []) * called allowing you to define additional default values. The new * entity will be saved and returned. * - * @param array $search The criteria to find existing records by. + * @param array|\Cake\ORM\Query|string $search The criteria to find existing records by. * @param callable|null $callback A callback that will be invoked for newly * created entities. This callback will be called *before* the entity * is persisted. @@ -1221,7 +1221,7 @@ public function get($primaryKey, $options = []) */ public function findOrCreate($search, callable $callback = null) { - $query = $this->find()->where($search); + $query = $this->_getFindOrCreateQuery($search); $row = $query->first(); if ($row) { return $row; @@ -1234,6 +1234,25 @@ public function findOrCreate($search, callable $callback = null) return $this->save($entity) ?: $entity; } + /** + * Gets the query object for findOrCreate(). + * + * @param array|\Cake\ORM\Query|string $search The criteria to find existing records by. + * @return \Cake\ORM\Query + */ + protected function _getFindOrCreateQuery($search) { + if ($search instanceof Query) { + return $search; + } elseif (is_string($search)) { + if (method_exists($this, $search)) { + return $this->{$search}(); + } else { + throw new InvalidArgumentException('Method `' . $search . '` does not exist!'); + } + } + return $this->find()->where($search); + } + /** * {@inheritDoc} */ diff --git a/tests/TestCase/ORM/TableTest.php b/tests/TestCase/ORM/TableTest.php index 81bd675c6ac..1be756960bd 100644 --- a/tests/TestCase/ORM/TableTest.php +++ b/tests/TestCase/ORM/TableTest.php @@ -5383,6 +5383,22 @@ function ($article) { $this->assertEquals('New body', $article->body); $this->assertEquals('N', $article->published); $this->assertEquals(2, $article->author_id); + + $query = $articles->find()->where(['author_id' => 2, 'title' => 'First Article']); + $article = $articles->findOrCreate($query); + $this->assertEquals('First Article', $article->title); + $this->assertEquals(2, $article->author_id); + } + + /** + * Test that exceptions from the findOrCreate are thrown. + * + * @expectedException \InvalidArgumentException + */ + public function testFindOrCreateException() + { + $articles = TableRegistry::get('Articles'); + $articles->findOrCreate('doesNotExist'); } /**