Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Delegates the "magic call strategy" on model instance to `data\model\Model`. #744

Merged
merged 1 commit into from

2 participants

Simon JAILLET Nate Abele
Simon JAILLET
Collaborator

This PR allows data\model\Model to manage it's own ::__call() strategy. This way it's possible to override how models should manage ::__call on its model instance.

Use case:

  • Delegate calls to some kind of "Behavior" class.
  • Use other kind of closures than the one in data\model\Model::_instanceMethods
Nate Abele nateabele merged commit f96a3ca into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
18 data/Entity.php
View
@@ -182,25 +182,17 @@ public function __isset($name) {
* $record->validates();
* }}}
*
- * @see lithium\data\Model::instanceMethods
- * @param string $method
- * @param array $params
+ * @param string $method Method name caught by `__call()`.
+ * @param array $params Arguments given to the above `$method` call.
* @return mixed
*/
public function __call($method, $params) {
if ($model = $this->_model) {
- $methods = $model::instanceMethods();
array_unshift($params, $this);
-
- if (method_exists($model, $method)) {
- $class = $model::invokeMethod('_object');
- return call_user_func_array(array(&$class, $method), $params);
- }
- if (isset($methods[$method]) && is_callable($methods[$method])) {
- return call_user_func_array($methods[$method], $params);
- }
+ $class = $model::invokeMethod('_object');
+ return call_user_func_array(array(&$class, $method), $params);
}
- $message = "No model bound or unhandled method call `{$method}`.";
+ $message = "No model bound to call `{$method}`.";
throw new BadMethodCallException($message);
}
18 data/Model.php
View
@@ -488,6 +488,24 @@ public static function __callStatic($method, $params) {
}
/**
+ * Magic method that allows calling `Model::_instanceMethods`'s closure like normal methods
+ * on the model instance.
+ *
+ * @see lithium\data\Model::instanceMethods
+ * @param string $method Method name caught by `__call()`.
+ * @param array $params Arguments given to the above `$method` call.
+ * @return mixed
+ */
+ public function __call($method, $params) {
+ $methods = static::instanceMethods();
+ if (isset($methods[$method]) && is_callable($methods[$method])) {
+ return call_user_func_array($methods[$method], $params);
+ }
+ $message = "Unhandled method call `{$method}`.";
+ throw new BadMethodCallException($message);
+ }
+
+ /**
* The `find` method allows you to retrieve data from the connected data source.
*
* Examples:
9 tests/cases/data/EntityTest.php
View
@@ -91,7 +91,14 @@ public function testMethodDispatch() {
}));
$this->assertEqual('testInstanceMethod', $entity->testInstanceMethod($entity));
- $this->expectException("/^No model bound or unhandled method call `foo`.$/");
+ $this->expectException("/^Unhandled method call `foo`.$/");
+ $entity->foo();
+ }
+
+ public function testMethodDispatchWithNoModel() {
+ $data = array('foo' => true);
+ $entity = new Entity(compact('data'));
+ $this->expectException("/^No model bound to call `foo`.$/");
$entity->foo();
}
2  tests/cases/data/entity/DocumentTest.php
View
@@ -445,7 +445,7 @@ public function testArrayValueSet() {
public function testInvalidCall() {
$doc = new Document();
- $this->expectException("No model bound or unhandled method call `medicin`.");
+ $this->expectException("No model bound to call `medicin`.");
$result = $doc->medicin();
$this->assertNull($result);
}
2  tests/cases/data/entity/RecordTest.php
View
@@ -120,7 +120,7 @@ public function testMethodDispatch() {
$this->assertEqual('create', $result['query']->type());
$this->assertEqual(array('title' => 'foo'), $result['query']->data());
- $this->expectException("No model bound or unhandled method call `invalid`.");
+ $this->expectException("Unhandled method call `invalid`.");
$this->assertNull($this->record->invalid());
}
}
Something went wrong with that request. Please try again.