Skip to content

Commit

Permalink
Update/remove Controller::$uses & Controller::loadModel()
Browse files Browse the repository at this point in the history
Remove Controller::$uses. It doesn't serve much purpose now other than
to waste resources by eagerly loading models. If people need to load
multiple models in a single controller they can use repository() to
fetch them. This new method will respect any set properties making
testing simple.

Update and remove tests that are no longer relevant.
  • Loading branch information
markstory committed Dec 6, 2013
1 parent a6ca876 commit fc37279
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 212 deletions.
110 changes: 24 additions & 86 deletions Cake/Controller/Controller.php
Expand Up @@ -90,26 +90,6 @@ class Controller extends Object implements EventListener {
*/
public $name = null;

/**
* An array containing the class names of models this controller uses.
*
* Example: `public $uses = array('Product', 'Post', 'Comment');`
*
* Can be set to several values to express different options:
*
* - `true` Use the default inflected model name.
* - `array()` Use only models defined in the parent class.
* - `false` Use no models at all, do not merge with parent class either.
* - `array('Post', 'Comment')` Use only the Post and Comment models. Models
* Will also be merged with the parent class.
*
* The default value is `true`.
*
* @var mixed A single name as a string or a list of names as an array.
* @link http://book.cakephp.org/2.0/en/controllers.html#components-helpers-and-uses
*/
public $uses = true;

/**
* An array containing the names of helpers this controller uses. The array elements should
* not contain the "Helper" part of the class name.
Expand Down Expand Up @@ -377,27 +357,17 @@ public function __construct($request = null, $response = null) {

/**
* Provides backwards compatibility to avoid problems with empty and isset to alias properties.
* Lazy loads models using the loadModel() method if declared in $uses
*
* @param string $name
* @return boolean
*/
public function __isset($name) {
if (is_array($this->uses)) {
foreach ($this->uses as $modelClass) {
list($plugin, $class) = pluginSplit($modelClass, true);
if ($name === $class) {
return $this->loadModel($modelClass);
}
}
}

if ($name === $this->modelClass) {
list($plugin, $class) = pluginSplit($name, true);
if (!$plugin) {
$plugin = $this->plugin ? $this->plugin . '.' : null;
}
return $this->loadModel($plugin . $this->modelClass);
return $this->repository($plugin . $this->modelClass);
}

return false;
Expand Down Expand Up @@ -506,7 +476,7 @@ protected function _getScaffold(Request $request) {
}

/**
* Merge components, helpers, and uses vars from
* Merge components, helpers vars from
* parent classes.
*
* @return void
Expand All @@ -516,28 +486,10 @@ protected function _mergeControllerVars() {
if (!empty($this->plugin)) {
$pluginDot = $this->plugin . '.';
}
if ($this->uses === null) {
$this->uses = false;
}
if ($this->uses === false) {
$this->uses = [];
$this->modelClass = '';
}
if ($this->uses === true) {
$this->uses = [$pluginDot . $this->modelClass];
}
$this->_mergeVars(
['components', 'helpers', 'uses'],
[
'associative' => ['components', 'helpers'],
'reverse' => ['uses']
]
['components', 'helpers'],
['associative' => ['components', 'helpers']]
);
$usesProperty = new \ReflectionProperty($this, 'uses');
if ($this->uses && $usesProperty->getDeclaringClass()->getName() !== get_class($this)) {
array_unshift($this->uses, $pluginDot . $this->modelClass);
}
$this->uses = array_unique($this->uses);
}

/**
Expand All @@ -558,24 +510,19 @@ public function implementedEvents() {
/**
* Loads Model and Component classes.
*
* Using the $uses and $components properties, classes are loaded
* Using the $components properties, classes are loaded
* and components have their callbacks attached to the EventManager.
* It is also at this time that Controller callbacks are bound.
*
* See Controller::loadModel(); for more information on how models are loaded.
* See Controller::repository(); for more information on how models are loaded.
*
* @return mixed true if models found and instance created.
* @see Controller::loadModel()
* @see Controller::repository()
* @link http://book.cakephp.org/2.0/en/controllers.html#Controller::constructClasses
* @throws MissingModelException
*/
public function constructClasses() {
$this->_mergeControllerVars();
if ($this->uses) {
$this->uses = (array)$this->uses;
list(, $this->modelClass) = pluginSplit(reset($this->uses));
}

$this->_loadComponents();
$this->getEventManager()->attach($this);
return true;
Expand Down Expand Up @@ -653,30 +600,32 @@ public function shutdownProcess() {
}

/**
* Loads and instantiates models required by this controller.
* If the model is non existent, it will throw a missing database table error, as CakePHP generates
* dynamic models for the time being.
* Loads and constructs repository objects required by this controller.
*
* Typically used to load ORM Table objects as required. Can
* also be used to load other types of repository objects your application uses.
*
* If a repository provider does not return an object a MissingModelException will
* be thrown.
*
* @param string $modelClass Name of model class to load.
* @param integer|string $id Initial ID the instanced model class should have.
* @return boolean True when single model found and instance created.
* @param string $modelClass Name of model class to load. Defaults to $this->modelClass
* @param string $type The type of repository to load. Defaults to 'Table' which
* delegates to Cake\ORM\TableRegistry.
* @return boolean True when single repository found and instance created.
* @throws Cake\Error\MissingModelException if the model class cannot be found.
*/
public function loadModel($modelClass = null, $id = null) {
public function repository($modelClass = null, $type = 'Table') {
if ($modelClass === null) {
$modelClass = $this->modelClass;
}

$this->uses = ($this->uses) ? (array)$this->uses : array();
if (!in_array($modelClass, $this->uses, true)) {
$this->uses[] = $modelClass;
}

list($plugin, $modelClass) = pluginSplit($modelClass, true);

$this->{$modelClass} = ClassRegistry::init(array(
'class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id
));
if ($type === 'Table') {
$this->{$modelClass} = TableRegistry::get($plugin . $modelClass);
} else {
$this->{$modelClass} = $this->_loadRepository($plugin . $modelClass, $type);
}
if (!$this->{$modelClass}) {
throw new Error\MissingModelException($modelClass);
}
Expand Down Expand Up @@ -756,14 +705,6 @@ public function render($view = null, $layout = null) {
return $this->response;
}

if (!empty($this->uses) && is_array($this->uses)) {
foreach ($this->uses as $model) {
list(, $name) = pluginSplit($model);
$className = App::classname($model, 'Model');
$this->request->params['models'][$name] = compact('className');
}
}

$this->View = $this->_getViewObject();

$models = ClassRegistry::keys();
Expand Down Expand Up @@ -820,9 +761,6 @@ public function paginate($object = null) {

if (is_string($object) || $object === null) {
$try = [$object, $this->modelClass];
if (isset($this->uses[0])) {
$try[] = $this->uses[0];
}
foreach ($try as $tableName) {
if (empty($tableName)) {
continue;
Expand Down

0 comments on commit fc37279

Please sign in to comment.