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

Implement Implicit Model Binding like Laravel 5.2

I like the Implicit model binding provided by laravel 5.2, after some work , found could implement this way: route file:

$router->add('/tags/{tag:[0-9]+}/item/{file:[0-9]+}','tags::showItem')->setName('tags.showItem');

for TagsController.php:

public function showItemAction(Tags $tag,Files $file)
    {
        $this->view->mytag = $tag;
        $this->view->page = $tag->getShowItemPage($file);
        $this->view->file = $file;
        $this->view->form = myForm::buildCommentForm($file->getTaggable($tag)->getFirst());
    }

In order to get this, I found the way like this : in dispatch.php


$eventsManager = new \Phalcon\Events\Manager();
$eventsManager->attach("dispatch:beforeDispatchLoop", function($event, \Phalcon\Mvc\Dispatcher $dispatcher){
    try{
        $reflection = new ReflectionMethod($dispatcher->getControllerClass(), $dispatcher->getActiveMethod());
        $actionParams = [];
        foreach($reflection->getParameters() as $parameter){

            $objectId = $dispatcher->getParam($parameter->name);
            if(null == $objectId && $parameter->isDefaultValueAvailable()) $objectId = $parameter->getDefaultValue();

            if($parameter->getClass()){
               // $className = RouterFacade::getProvider($parameter->getClass()->name);
                $className = $parameter->getClass()->name;

                if($objectId){
                    if(is_subclass_of($className,\Phalcon\Mvc\Model::class)){
                        /** @var \Phalcon\Mvc\Model $className */
                        $actionParams[$parameter->name] = $className::findFirst($objectId);
                    }else{
                        $actionParams[$parameter->name] = new $className($objectId);
                    }

                }else{
                    $actionParams[$parameter->name] = new $className;
                }
            }else{
                $actionParams[$parameter->name] = $objectId;
            }
        }

        if(count($actionParams)){
            $dispatcher->setParams($actionParams);
        }

    } catch(\Phalcon\Exception $e) {
        var_dump($e);
        die();
    }

});

$dispatcher = new \Phalcon\Mvc\Dispatcher();
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;

It just works like in laravel, if you want to bind interface to some class, you could substitue " $className = $parameter->getClass()->name;" by some function you defined.

What do you think of this method? If you have a better idea, pls comment!

There was a Pull Request about this recently which will be available in Phalcon 2.1: https://github.com/phalcon/cphalcon/pull/11288

I've also made an alternative implementation here which is available as a Composer package and works with Phalcon 2.0: https://github.com/SidRoberts/phalcon-boundmodels