We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Inject Model into Controller

Hi All,

I'm trying to figure out how to make my Controllers more testable in my Micro application.
To that end, I figured I'd auto inject a related model into each controller.

I'm using this project as a starting point for my REST API. https://github.com/cmoore4/phalcon-rest

I read that you can do something like this in the Full Stack application. https://docs.phalcon.io/en/latest/reference/dispatching.html#inject-model-instances

Since Micro doesn't have $dispatcher, I looked into

$app = new \Phalcon\Mvc\Micro();
$app->before(function() user($app, $di) {
    $className = "MyModel";
    $modelName = "\\PhalconRest\\Models\\$className";
    $alt = new $modelName()
    //Model loaded, what now?  How to inject into controller?
}

I can load a model but don't know how to perserve it for the controller to inject.

My app uses Collections to build routes.
My setup seems to require a string in setHandler so how to pass in a parameter?

Example: https://github.com/cmoore4/phalcon-rest/blob/develop/routes/collections/example.php

// VERSION NUMBER SHOULD BE FIRST URL PARAMETER, ALWAYS
// setHandler MUST be a string in order to support lazy loading
    $userCollection->setPrefix('/v1/user')
        ->setHandler('\PhalconRest\Controllers\MyController')
        ->setLazy(true);

I'm open to ideas, help!



98.9k
edited Aug '14

First of all, to create a model instance you don't have to do:

$className = "MyModel";
$modelName = "\\PhalconRest\\Models\\$className";
$alt = new $modelName()

Just this would be ok:

$alt = new \PhalconRest\\Models\MyModel();

Not sure why you need to inject the model from the middelware, but you can just use it right there in the controller:

<?php

namespace PhalconRest\Controllers;

use PhalconRest\\Models\MyModel;
use PhalconRest\Exceptions\HTTPException;

class ExampleController extends RESTController
{
    public function get($id)
    {
        $model = MyModel::findFirstById($id);
        if ($model) {
            //...
        }
    }
}


25.1k
edited Aug '14

Thanks Phalcon!

I was trying to make the Controller more testable by supplying any dependant objects into the controller rather than having the Controller created the object.

For example, in Laravel, they suggest injecting a dependancy, like a model, in the controller constructor to aid Unit Testing.

Here is a Laravel based tutorial that explains the concept I'm trying to create. https://culttt.com/2013/07/15/how-to-structure-testable-controllers-in-laravel-4/

Or some pseudo code in an example controller:

public function __construct(User $user)
{
    $this->user = $user;
}

/**
 * Display a listing of the resource.
 *
 * @return Response
 */
public function index()
{
    return $this->user->all();
}


300
Accepted
answer

Afaik, unfortunatly, theres no such functionality in PhalconPHP.

My recommendation for you is to instantiate models you are using in actions with \Phalcon\DI, and then you could setup mocks for those models in your tests and register them with DI.



25.1k

@digitronac I think I understand what you are suggesting. You are saying to create models in the Controller Action methods using \Phalcon\DI. I'm guessing \Phalcon\DI provides a layer where I can later insert mock objects to fill in for the REAL models when I run tests.