helman
helman

Reputation: 56

Phalcon: HMVC view not working

I got a problem rendering nested view, here is what I'm trying to do I changed your 'request' of HMVC (HMVC-GitHub or/and HMVC-Pattern) function into an Elements module

namespace Modules\Main\Libraries;

/**
 * Elements
 *
 * Helps to build UI elements for the application
 */
class Elements extends \Phalcon\Mvc\User\Component
{

    public function loadModule($path = '', $data = array()) {
        $di = clone $this->getDI();
        $dispatcher = $di->get('dispatcher');

        $paths = explode('/', $path);
        $data = is_array($data) ? $data : array($data);

        // get controller name
        if (isset($paths[0])) {
            $controller = $paths[0];
        }

        // get action name
        if (isset($paths[1])) {
            $action = $paths[1];
        }

        // get params
        if (isset($paths[2])) {
            array_splice($paths, 0, 2);
            $params = array_merge($paths, $data);
        } else {
            $params = $data;
        }

        if (!empty($controller)) {
            $dispatcher->setControllerName($controller);
        } else {
            $dispatcher->setControllerName('index');
        }

        if (!empty($action)) {
            $dispatcher->setActionName($action);
        } else {
            $dispatcher->setActionName('index');
        }

        if (!empty($params)) {
            if(is_array($params)) {
                $dispatcher->setParams($params);
            } else {
                $dispatcher->setParams((array) $params);
            }
        } else {
            $dispatcher->setParams(array());
        }

        $dispatcher->dispatch();

        $response = $dispatcher->getReturnedValue();
        if ($response instanceof ResponseInterface) {
            return $response->getContent();
        }

        return $response;
    }
}

and I have 2 controllers:

namespace Modules\Main\Controllers;

class IndexController extends ControllerBase
{

    public function indexAction()
    {
        $secondContent = $this->elements->loadModule('test/hello/json');

        $this->view->setVar('secondContent', $secondContent);
    }

}

and

namespace Modules\Main\Controllers;

use \Phalcon\Http\Response;

class TestController extends ControllerBase
{

    public function indexAction()
    {

    }

    public function helloAction($format='html', $param = 'empty')
    {
        $this->view->setVar('content', 'Hello this is test value "'.$param.'"');

        $content = $this->view->getContent();

        return (string)$content;

        // return 'Hello this is test value "'.$param.'"';
    }

}

my DI

        $di['elements'] = function() {
            return new \Modules\Main\Libraries\Elements();
        };

Views files IndexController::Index

<h1>Congratulations!</h1>

<p>You're now flying with Phalcon. Great things are about to happen!</p>
<p>Second content: {{ secondContent}}</p>
<p>HMVC: {{ elements.loadModule('test/hello/json', 'test') }}</p>

and HelloController::test

This is :: {{ content }}

expecting to get

Congratulations!
You're now flying with Phalcon. Great things are about to happen!
Second content: This is :: Hello this is test value "empty"
HMVC: This is :: Hello this is test value "test"

but it only rendering the HelloController (First call from IndexController::indexAction):

This is :: Hello this is test value "empty"

if I change IndexController::indexAction to

public function indexAction()
{
    $secondContent = '';

    $this->view->setVar('secondContent', $secondContent);
}

and TestController::helloAction to

public function helloAction($format='html', $param = 'empty')
{
    $this->view->setVar('content', 'Hello this is test value "'.$param.'"');

    $content = $this->view->getContent();

    //return (string) $content;

    return 'Hello this is test value "'.$param.'"';
}

the result that i get is (Second content is empty):

Congratulations!
You're now flying with Phalcon. Great things are about to happen!
Second content: 
HMVC: Hello this is test value "test"

Any solution to solve this ?

Thanks, Helman

Upvotes: 2

Views: 1054

Answers (1)

Jowy Atreides
Jowy Atreides

Reputation: 31

Phalcon have built-it modules feature, you dont have to built your own module loader, you just need create module bootstrap that extend ModuleDefinitionInterface.

Just take a look this sample from phalcon multi module

https://github.com/phalcon/mvc/tree/master/multiple

this example below is taken from link above, This contain module bootstrap code.

<?php

namespace Multiple\Frontend;

class Module
{

    public function registerAutoloaders()
    {

        $loader = new \Phalcon\Loader();

        $loader->registerNamespaces(array(
            'Multiple\Frontend\Controllers' => '../apps/frontend/controllers/',
            'Multiple\Frontend\Models' => '../apps/frontend/models/',
        ));

        $loader->register();
    }

    /**
     * Register the services here to make them general or register in the ModuleDefinition to make them module-specific
     */
    public function registerServices($di)
    {

        //Registering a dispatcher
        $di->set('dispatcher', function () {
            $dispatcher = new \Phalcon\Mvc\Dispatcher();

            //Attach a event listener to the dispatcher
            $eventManager = new \Phalcon\Events\Manager();
            $eventManager->attach('dispatch', new \Acl('frontend'));

            $dispatcher->setEventsManager($eventManager);
            $dispatcher->setDefaultNamespace("Multiple\Frontend\Controllers\\");
            return $dispatcher;
        });

        //Registering the view component
        $di->set('view', function () {
            $view = new \Phalcon\Mvc\View();
            $view->setViewsDir('../apps/frontend/views/');
            return $view;
        });

        $di->set('db', function () {
            return new \Phalcon\Db\Adapter\Pdo\Mysql(array(
                "host" => "localhost",
                "username" => "root",
                "password" => "secret",
                "dbname" => "invo"
            ));
        });

    }

}

you can load module using this code below

$app = new \Phalcon\Mvc\Application();
$app->registerModules(array(
            'frontend' => array(
                'className' => 'Multiple\Frontend\Module',
                'path' => '../apps/frontend/Module.php'
            ),
            'backend' => array(
                'className' => 'Multiple\Backend\Module',
                'path' => '../apps/backend/Module.php'
            )
        ));

Upvotes: 2

Related Questions