Browse Source

Add Query::firstOrFail()

This method lets you use get() like behavior on any finder. This is
intended to replace #5157.
Mark Story 11 years ago
parent
commit
90a9ef29dd
3 changed files with 28 additions and 17 deletions
  1. 22 0
      src/ORM/Query.php
  2. 1 12
      src/ORM/Table.php
  3. 5 5
      tests/TestCase/ORM/TableTest.php

+ 22 - 0
src/ORM/Query.php

@@ -20,6 +20,7 @@ use Cake\Datasource\QueryTrait;
 use Cake\ORM\EagerLoader;
 use Cake\ORM\ResultSet;
 use Cake\ORM\Table;
+use Cake\ORM\Exception\RecordNotFoundException;
 use JsonSerializable;
 
 /**
@@ -836,6 +837,27 @@ class Query extends DatabaseQuery implements JsonSerializable {
 	}
 
 /**
+ * Get the first result from the executing query or raist an exception.
+ *
+ * @throws \Cake\ORM\RecordNotFoundException When there is no first record.
+ * @return mixed The first result from the ResultSet.
+ */
+	public function firstOrFail() {
+		$entity = $this->first();
+		if ($entity) {
+			return $entity;
+		}
+		$binder = new ValueBinder();
+		$conditions = $this->clause('where');
+
+		throw new RecordNotFoundException(sprintf(
+			'Record not found in table "%s" for conditions "%s"',
+			$this->repository()->table(),
+			$conditions->sql($binder)
+		));
+	}
+
+/**
  * Decorates the results iterator with MapReduce routines and formatters
  *
  * @param \Traversable $result Original results

+ 1 - 12
src/ORM/Table.php

@@ -30,7 +30,6 @@ use Cake\ORM\Association\HasMany;
 use Cake\ORM\Association\HasOne;
 use Cake\ORM\BehaviorRegistry;
 use Cake\ORM\Exception\MissingEntityException;
-use Cake\ORM\Exception\RecordNotFoundException;
 use Cake\ORM\Marshaller;
 use Cake\Utility\Inflector;
 use Cake\Validation\Validator;
@@ -941,17 +940,7 @@ class Table implements RepositoryInterface, EventListenerInterface {
 			}
 			$query->cache($cacheKey, $cacheConfig);
 		}
-
-		$entity = $query->first();
-
-		if ($entity) {
-			return $entity;
-		}
-		throw new RecordNotFoundException(sprintf(
-			'Record "%s" not found in table "%s"',
-			implode(',', (array)$primaryKey),
-			$this->table()
-		));
+		return $query->firstOrFail();
 	}
 
 /**

+ 5 - 5
tests/TestCase/ORM/TableTest.php

@@ -3389,7 +3389,7 @@ class TableTest extends TestCase {
 
 		$query = $this->getMock(
 			'\Cake\ORM\Query',
-			['addDefaultTypes', 'first', 'where', 'cache'],
+			['addDefaultTypes', 'firstOrFail', 'where', 'cache'],
 			[$this->connection, $table]
 		);
 
@@ -3404,7 +3404,7 @@ class TableTest extends TestCase {
 			->with([$table->alias() . '.bar' => 10])
 			->will($this->returnSelf());
 		$query->expects($this->never())->method('cache');
-		$query->expects($this->once())->method('first')
+		$query->expects($this->once())->method('firstOrFail')
 			->will($this->returnValue($entity));
 		$result = $table->get(10, $options);
 		$this->assertSame($entity, $result);
@@ -3449,7 +3449,7 @@ class TableTest extends TestCase {
 
 		$query = $this->getMock(
 			'\Cake\ORM\Query',
-			['addDefaultTypes', 'first', 'where', 'cache'],
+			['addDefaultTypes', 'firstOrFail', 'where', 'cache'],
 			[$this->connection, $table]
 		);
 
@@ -3466,7 +3466,7 @@ class TableTest extends TestCase {
 		$query->expects($this->once())->method('cache')
 			->with($cacheKey, $cacheConfig)
 			->will($this->returnSelf());
-		$query->expects($this->once())->method('first')
+		$query->expects($this->once())->method('firstOrFail')
 			->will($this->returnValue($entity));
 		$result = $table->get(10, $options);
 		$this->assertSame($entity, $result);
@@ -3476,7 +3476,7 @@ class TableTest extends TestCase {
  * Tests that get() will throw an exception if the record was not found
  *
  * @expectedException \Cake\ORM\Exception\RecordNotFoundException
- * @expectedExceptionMessage Record "10" not found in table "articles"
+ * @expectedExceptionMessage Record not found in table "articles" for conditions "articles.id = :c0"
  * @return void
  */
 	public function testGetNotFoundException() {