Browse Source

Merge pull request #4816 from sukihub/3.0-cacheable-get-v1

3.0 - Query caching for \Cake\ORM\Table::get (updated)
Mark Story 11 years ago
parent
commit
b2f9bbf43e
2 changed files with 93 additions and 4 deletions
  1. 18 1
      src/ORM/Table.php
  2. 75 3
      tests/TestCase/ORM/TableTest.php

+ 18 - 1
src/ORM/Table.php

@@ -924,7 +924,24 @@ class Table implements RepositoryInterface, EventListener {
 			));
 		}
 		$conditions = array_combine($key, $primaryKey);
-		$entity = $this->find('all', $options)->where($conditions)->first();
+
+		$cacheConfig = isset($options['cache']) ? $options['cache'] : false;
+		$cacheKey = isset($options['key']) ? $options['key'] : false;
+		unset($options['key'], $options['cache']);
+
+		$query = $this->find('all', $options)->where($conditions);
+
+		if ($cacheConfig) {
+			if (!$cacheKey) {
+				$cacheKey = sprintf(
+					"get:%s.%s%s",
+					$this->connection()->configName(), $this->table(), json_encode($primaryKey)
+				);
+			}
+			$query->cache($cacheKey, $cacheConfig);
+		}
+
+		$entity = $query->first();
 
 		if ($entity) {
 			return $entity;

+ 75 - 3
tests/TestCase/ORM/TableTest.php

@@ -3301,13 +3301,81 @@ class TableTest extends \Cake\TestSuite\TestCase {
 		$table->find();
 	}
 
+	public function providerForTestGet() {
+		return [
+			[ ['fields' => ['id']] ],
+			[ ['fields' => ['id'], 'cache' => false] ]
+		];
+	}
+
 /**
  * Test that get() will use the primary key for searching and return the first
  * entity found
  *
+ * @dataProvider providerForTestGet
+ * @param array $options
+ * @return void
+ */
+	public function testGet($options) {
+		$table = $this->getMock(
+			'\Cake\ORM\Table',
+			['callFinder', 'query'],
+			[[
+				'connection' => $this->connection,
+				'schema' => [
+					'id' => ['type' => 'integer'],
+					'bar' => ['type' => 'integer'],
+					'_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['bar']]]
+				]
+			]]
+		);
+
+		$query = $this->getMock(
+			'\Cake\ORM\Query',
+			['addDefaultTypes', 'first', 'where', 'cache'],
+			[$this->connection, $table]
+		);
+
+		$entity = new \Cake\ORM\Entity;
+		$table->expects($this->once())->method('query')
+			->will($this->returnValue($query));
+		$table->expects($this->once())->method('callFinder')
+			->with('all', $query, ['fields' => ['id']])
+			->will($this->returnValue($query));
+
+		$query->expects($this->once())->method('where')
+			->with([$table->alias() . '.bar' => 10])
+			->will($this->returnSelf());
+		$query->expects($this->never())->method('cache');
+		$query->expects($this->once())->method('first')
+			->will($this->returnValue($entity));
+		$result = $table->get(10, $options);
+		$this->assertSame($entity, $result);
+	}
+
+	public function providerForTestGetWithCache() {
+		return [
+			[
+				['fields' => ['id'], 'cache' => 'default'],
+				'get:test.table_name[10]', 'default'
+			],
+			[
+				['fields' => ['id'], 'cache' => 'default', 'key' => 'custom_key'],
+				'custom_key', 'default'
+			]
+		];
+	}
+
+/**
+ * Test that get() will use the cache.
+ *
+ * @dataProvider providerForTestGetWithCache
+ * @param array $options
+ * @param string $cacheKey
+ * @param string $cacheConfig
  * @return void
  */
-	public function testGet() {
+	public function testGetWithCache($options, $cacheKey, $cacheConfig) {
 		$table = $this->getMock(
 			'\Cake\ORM\Table',
 			['callFinder', 'query'],
@@ -3320,10 +3388,11 @@ class TableTest extends \Cake\TestSuite\TestCase {
 				]
 			]]
 		);
+		$table->table('table_name');
 
 		$query = $this->getMock(
 			'\Cake\ORM\Query',
-			['addDefaultTypes', 'first', 'where'],
+			['addDefaultTypes', 'first', 'where', 'cache'],
 			[$this->connection, $table]
 		);
 
@@ -3337,9 +3406,12 @@ class TableTest extends \Cake\TestSuite\TestCase {
 		$query->expects($this->once())->method('where')
 			->with([$table->alias() . '.bar' => 10])
 			->will($this->returnSelf());
+		$query->expects($this->once())->method('cache')
+			->with($cacheKey, $cacheConfig)
+			->will($this->returnSelf());
 		$query->expects($this->once())->method('first')
 			->will($this->returnValue($entity));
-		$result = $table->get(10, ['fields' => ['id']]);
+		$result = $table->get(10, $options);
 		$this->assertSame($entity, $result);
 	}