Calling functions outside of controllers

I have a controller called GiftController.

And I call the method getModel(); inside of it like this:

$model = $this->getModel();
giftFactory->getGiftFactory();
$array = $model->get('giff-data');
$array = giftFactory->getValidator($array[0]['validator']);

The code above is inside GiftController.

I would like to call these 4 lines outside of the controller. I think I need to do:

$model = GiftController::getModel();

I am not sure if this is enough though. Do I need to import the Controller? How do you do that?

You might want to think about refactoring this feature out of the controller and into its own class.

Scott

Do I need to do a require? I am using Yii.

I am no expert with Yii, but theoretically, you can and probably should use the Yii autoloader.

Scott

Can you use namespaces?

namespace Gift;

public class GiftController {
...
}

and

use Gift;

public class someOtherPlace {
...
}

Yes, but a namespace is usually constructed a bit differently.

With that, you’d also use “use” and the namespace something like this…

namespace YourName\YourApplication;

public class GiftAsSomeOtherClass {
...
}

Then you can “use” the new class like this…

namespace YourName\YourApplication;

use YourName\YourApplication\GiftAsSomeOtherClass as Gift;

$gift = new Gift();

If your application is bigger, you might want to break the namespace down even further. Something like…

namespace YourName\YourApplication\YourComponent;

That is optional though.

You might also want to register the class in the DI container, which theoretically should give your controller access to the container (and the object), if your controller extends the base controller class from Yii, which is actually called the base “Object” class. Not sure though. I am not familiar with Yii and am just flying over their docs.

Scott

Certainly not import the controller. The best way is usually dependency injection. If you have an object outside the controller that needs the model then that object should require it in its constructor:

class MyOtherClass {
  private $model;

  public function __construct(Model $model) {
    $this->model = $model;
  }
}

Then when you construct an instance of MyOtherClass you do this:

$myOtherObj = new MyOtherClass($model);

You might do it in the controller but ideally the new keyword should be avoided outside the bootstrapping code or factories because it is global. A solution is again to use dependency injection and pass the already constructed $myOtherObj to the controller. In the same way, $model should also be passed to the controller via DI in the constructor and then use it like this in its methods:

$array = $this->model->get('diff-data');
// ...
$this->myOtherObj->doSomething();

In this way you end up with what is called controllers as services meaning they don’t have any hidden dependencies on your framework but explicitly require them via the constructor. In short - if you need to access an object both in a controller and in some other class then pass the object to both of them.

However, not all frameworks go as far as to decouple controllers so much from them and they allow the service locator pattern where the controller has access to a framework-specific factory or dependency injection container and pull the necessary objects from it:

$model = $this->factory->getModel();
$array = $model->get('diff-data');
// ...
$myOtherObj = $this->factory->getMyOtherObj();
$myOtherObj->doSomething();

This is only a general picture as each framework will have its own implementation details.

However, I would not use the service locator pattern for any classes outside the controllers and would stick to dependency injection only. So, for example if your model class needs $myOtherObj then simply pass $myOtherObj to the model class via the constructor. Usually, your factory (or DIC) will be responsible for constructing your model with the required MyOtherClass instance.

Edit: Regarding namespaces - they are used to organize the code in a sort of separate paths or directories and are a different concept. Meaning - yes you can use them and probably should, but this has nothing to do with this topic.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.