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

Components into modules and general components

Hi!

I've followed the hmvc architecture and designed a simple web application but now I have a problem:

I want to use a module in apps/frontend/components/User.php, the file is:

<?php

namespace Component;

class User extends \Phalcon\Mvc\User\Component
{

    public function createSession(\Users $user)
    {
        $this->session->set('id', $user->id);
        $this->session->set('role', $user->role);
        $this->redirectDependingOnRole();
    }

    public function redirectDependingOnRole()
    {
        switch ($this->session->get('role')) {
            case 'admin':
                $this->response->redirect('admin/');
            break;
            case 'user':
                $this->response->redirect('dashboard/');
            break;
            case 'guest':
                $this->response->redirect('/'); 
            break;
        }
    }

    public function isOnline()
    {
        return $this->session->get('id') != null;
    }

    public function isAdmin()
    {
        return $this->session->get('role') == 'admin';
    }

    public function helloWorld()
    {
        echo "hello world!";
    }
}

The apps/frontend/Module.php is:

<?php

namespace Frontend;

use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\DiInterface;
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
use Phalcon\Mvc\ModuleDefinitionInterface;

class Module implements ModuleDefinitionInterface
{

    /**
     * Registers the module auto-loader
     */
    public function registerAutoloaders(DiInterface $di = null)
    {

        $loader = new Loader();

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

        // Registro de componentes propios
        $loader->registerClasses([
            'Component\User' => __DIR__ . '/components/User.php',
            'Component\Helper' => __DIR__ . '/components/Helper.php'
        ]);

        $loader->register();
    }

    // more content...

Then in my frontend/controllers/IndexController.php:

   <?php

   namespace Frontend\Controllers;

   use \Phalcon\Tag;

   class IndexController extends ControllerBase
   {
       public function onConstruct()
       {
           parent::initialize();
       }

       public function indexAction()
       {
           Tag::setTitle('Home');
       }

       public function testAction()
       {
           $this->component->user->helloWorld();
       }
   }

The function testAction() is failing always, I don't know why.

Also I want to know a way to have a "global" components directory for be used by all the modules. Thanks.



47.7k

I can't see that you have registered your component as a service in your Module.php in

    public function registerServices(DiInterface $di)
    {
    }


4.5k
edited Jan '16
public function registerServices(DiInterface $di)
{

    /**
     * Read configuration
     */
    $config = include __DIR__ . "/config/config.php";

    /**
     * Setting up the view component
     */
    $di['view'] = function() {
        $view = new View();
        $view->setViewsDir(__DIR__ . '/views/');
        $view->registerEngines(array(
            ".volt" => 'Phalcon\Mvc\View\Engine\Volt'
        ));

        return $view;
    };

    /**
     * Database connection is created based in the parameters defined in the configuration file
     * for this module!!
     */
    $di['db'] = function() use ($config) {
        return new DbAdapter(array(
            "host"     => $config->database->host,
            "username" => $config->database->username,
            "password" => $config->database->password,
            "dbname"   => $config->database->name
        ));
    };
}

Nope, I didn't, how can I do it?



47.7k
edited Jan '16

Ok so in my public/index.php I have

/**
 * Registering user components
 */
$di->set('elements', function() {
    return new Common\Library\Elements(); //This extends \Phalcon\Mvc\User\Component
});

or

$di['elements'] = function() {
    return new Common\Library\Elements(); //This extends \Phalcon\Mvc\User\Component
});

in my apps/frontend/Module.php I make sure to:

$loader->registerNamespaces(
                array(
                    'Common\Library' => SITE_ROOT . 'apps/common/library/',
                )
        );

It probably shouldn't really be done this way as it would be better to explicitly register that service in both frontend and whateverend Module.php.

If you want components used in all modules, just register it after modules registrating for example in services.



4.5k
edited Jan '16

If you want components used in all modules, just register it after modules registrating for example in services.

I did, now it is working:

$di->setShared('component', function() {
    $obj = new stdClass();
    $obj->helper = new \Component\Helper();
    $obj->user = new \Component\User();

    return $obj;
});

And then in the Module.php file:

$loader->registerNamespaces(array(
            'Frontend\Controllers' => __DIR__ . '/controllers/',
            'Frontend\Models' => __DIR__ . '/models/',
            'Component' => '../components/' // de este modo buscará el namespace Component en la carpeta "global" components
));

Thanks.