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

Phalcon\Di\Exception: Service 'view' wasn't found in the dependency injection container

I'm following the book "Learning Phalcon PHP" and making a project with modules. I've got the "Phalcon\Di\Exception: Service 'view' wasn't found in the dependency injection container" error.

The most important files are:

public/index.php

<?php

header('Content-Type: text/html; charset=utf-8');
mb_internal_encoding("UTF-8");

require_once __DIR__.'/../modules/Bootstrap.php';
require_once __DIR__.'/../vendor/autoload.php'; // composer autoload

$app = new Bootstrap('frontend');
$app->init();

config/config.php

<?php

return new \Phalcon\Config(array(
    'application' => array(
        'name' => 'Learning Phalcon'
    ),
    'root_dir' => __DIR__.'/../',
    /*'redis' => array(
        'host' => '127.0.0.1',
        'port' => 6379,
    ),*/
    'session' => array(
        'unique_id' => 'learning_phalcon',
        'name' => 'learning_phalcon',
        'path' => 'tcp://127.0.0.1:6379?weight=1'
    ),
    'view' => array(
        'cache' => array(
            'dir' => __DIR__.'/../cache/volt/'
        )
    ),
));

config/loader.php:

<?php

$loader = new \Phalcon\Loader();
$loader->registerNamespaces(array(
    'App\Core'       => __DIR__ . '/../modules/Core/',
    'App\Frontend'   => __DIR__ . '/../modules/Frontend/',
    'App\Api'        => __DIR__ . '/../modules/Api/',
    'App\Backoffice' => __DIR__ . '/../modules/Backoffice/',
));

$loader->register();

config/routing.php

<?php

$di['router'] = function() use ($default_module, $modules, $di, $config) {
    $router = new \Phalcon\Mvc\Router(false);
    $router->clear();
    $moduleRouting = __DIR__.'/../apps/'.ucfirst($default_module).'/Config/routing.php';

    if (file_exists($moduleRouting) && is_file($moduleRouting)) {
        $router = include $moduleRouting;
    } else {
        $router->add('#^/(|/)$#', array(
            'module' => $default_module,
            'controller' => 'index',
            'action' => 'index',
        ));

        $router->add('#^/([a-zA-Z0-9\_]+)[/]{0,1}$#', array(
            'module' => $default_module,
            'controller' => 1,
       ));
        $router->add('#^/{0,1}([a-zA-Z0-9\_]+)/([a-zA-Z0-9\_]+)(/.*)*$#', array(
            'module' => $default_module,
            'controller' => 1,
            'action' => 2,
        'params' => 3,
    ));
}
return $router;

};

config/services.php

<?php

use \Phalcon\Logger\Adapter\File as Logger;

$di['session'] = function () use ($config) {
    $session = new \Phalcon\Session\Adapter\Redis(array(
        'uniqueId' => $config->session->unique_id,
        'path' => $config->session->path,
        'name' => $config->session->name
    ));
    $session->start();
    return $session;
};

$di['security'] = function () {
    $security = new \Phalcon\Security();
    $security->setWorkFactor(10);
    return $security;
};

$di['redis'] = function () use ($config) {
    $redis = new \Redis();
    $redis->connect(
        $config->redis->host,
        $config->redis->port
    );
    return $redis;
};

$di['url'] = function () use ($config, $di) {
    $url = new \Phalcon\Mvc\Url();
    return $url;
};

$di['voltService'] = function($view, $di) use ($config) {
    $volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di);
    if (!is_dir($config->view->cache->dir)) {
        mkdir($config->view->cache->dir);
    }

    $volt->setOptions(array(
        "compiledPath" => $config->view->cache->dir,
        "compiledExtension" => ".compiled",
        "compileAlways" => true
    ));
    return $volt;
};

$di['logger'] = function () {
    $file = __DIR__."/../logs/".date("Y-m-d").".log";
    $logger = new Logger($file, array('mode' => 'w+'));
    return $logger;
};

$di['cache'] = function () use ($di, $config) {
    $frontend = new \Phalcon\Cache\Frontend\Igbinary(array(
        'lifetime' => 3600 * 24
    ));

    $cache = new \Phalcon\Cache\Backend\Redis($frontend, array(
        'redis' => $di['redis'],
        'prefix' => $config->application->name.':'
    ));

    return $cache;
};

modules/Frontend/Bootstrap.php

<?php

class Bootstrap extends \Phalcon\Mvc\Application
{
    private $modules;
    private $default_module = 'frontend';

    public function __construct($default_module)
    {
        $this->modules = array(
            'core' => array(
                'className' => 'App\Core\Module',
                'path' => __DIR__ . '/Core/Module.php'
            ),
            'api' => array(
                'className' => 'App\Api\Module',
                'path' => __DIR__ . '/Api/Module.php'
            ),
            'frontend' => array(
                'className' => 'App\Frontend\Module',
                'path' => __DIR__ . '/Frontend/Module.php'
            ),
            'backoffice' => array(
                'className' => 'App\Backoffice\Module',
                'path' => __DIR__ . '/Backoffice/Module.php'
            ),
        );

       $this->default_module = $default_module;
    }

    private function _registerServices()
    {
        $default_module = $this->default_module;
        $di = new \Phalcon\DI\FactoryDefault();
        $config = require __DIR__.'/../config/config.php';
        $modules = $this->modules;

        include_once __DIR__.'/../config/loader.php';
        include_once __DIR__.'/../config/routing.php';
        include_once __DIR__.'/../config/services.php';

        $this->setDI($di);
    }

    public function init()
    {
        $debug = new \Phalcon\Debug();
        $debug->listen();

        $this->_registerServices();
        $this->registerModules($this->modules);

        echo $this->handle()->getContent();
    }
}

modules/Frontend/Module.php

<?php

namespace App\Frontend;

use Phalcon\Mvc\ModuleDefinitionInterface;

class Module implements ModuleDefinitionInterface
{
    /**
    * Registers the module auto-loader
    */
    public function registerAutoloaders(\Phalcon\DiInterface $di = null)
    {
    }

    /**
    * Registers the module-only services
    *
    * @param Phalcon\DI $di
    */
    public function registerServices(\Phalcon\DiInterface $di)
    {
        $config = include __DIR__ . "Config/config.php"; // Fallo del libro, en el libro sobra la primera slash
        $di['config'] = $config;
        include __DIR__ . "Config/services.php";
    }
}

modules/Frontend/Config/config.php

<?php

$config = require __DIR__.'/../../../config/config.php';

$module_config = array(
    'application' => array(
        'controllersDir' => __DIR__ . '/../Controllers/',
        'modelsDir' => __DIR__ . '/../Models/',
        'viewsDir' => __DIR__ . '/../Views/',
        'baseUri' => '/',
        'cryptSalt' => '[email protected]',
        'publicUrl' => 'https://proyecto-libro.localhost'
    )
);

$config->merge($module_config);
return $config;

modules/Frontend/Config/routing.php

<?php

$router = new \Phalcon\Mvc\Router(false);
$router->clear();

$router->add('/', array(
    'module' => 'frontend',
    'controller' => 'index',
    'action' => 'index'
));

return $router;

modules/Frontend/Config/services.php

<?php

$di['dispatcher'] = function () use ($di) {
    $eventsManager = $di->getShared('eventsManager');
    $dispatcher = new \Phalcon\Mvc\Dispatcher();
    $dispatcher->setEventsManager($eventsManager);
    $dispatcher->setDefaultNamespace('App\Frontend\Controllers');
    return $dispatcher;
};

$di['url']->setBaseUri(''.$config->application->baseUri.'');
$di['view'] = function () {
    $view = new \Phalcon\Mvc\View();
    $view->setViewsDir(__DIR__ . '/../Views/Default/');
    $view->registerEngines(array(
        ".volt" => 'voltService'
    ));
    return $view;
};

modules/Frontend/Views/Default/index/index.volt:

{% extends 'layout.volt' %}
{% block body %}
I did it !
{% endblock %}


4.5k
Accepted
answer

I've found this very useful github repo and now I'm extending the behavior of that base.