Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Flash service is not defined in multi-module app

Hi, i generated a project with single module and a new one with multi-module enabled, both with webtools active.

Using this configuration:

Phalcon DevTools Version    4.0.3
Phalcon Version     4.0.6
AdminLTE Version    2.3.6
OS  Linux BW 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2+deb10u1 (2020-06-07) x86_64
PHP Version     7.3.19-1~deb10u1
PHP SAPI    fpm-fcgi
PHP Bin     /usr/sbin/php-fpm7.3
PHP Extension Dir   /usr/lib/php/20180731
PHP Bin Dir     /usr/bin
Loaded PHP config   /etc/php/7.3/fpm/php.ini

I successfully generated the MVC components for some entities with webtools and after some tweaking in the single module application but on the multi-module version I can't figure out why the non shared service 'flash', defined in services_web.php (as generated by devtools), is not defined.

Going to the index of a generated entity controller i get this output, Fatal error: Uncaught Error: Call to a member function output() on null in

out of this line:

            $this->flash->notice("The search did not find any activation_token");

But can make it work with this:

            $this->flashSession->notice("The search did not find any activation_token");

Why is flash service not defined in the controller of the module? From the controller methods $this->flash is NULL.

The only difference i can see is that flash is declared not shared by devtools in both the application versions (overriding i guess the FactoryDefault predefined service since flash is reported as shared in the docs) but it seems it has nothing to do with the real problem, see services_web.php (identical to services.php (single module)):

/**
 * Register the session flash service with the Twitter Bootstrap classes
 */
$di->set('flash', function () {
    $escaper = new Escaper();
    $flash = new Flash($escaper);
    $flash->setImplicitFlush(false);
    $flash->setCssClasses([
        'error'   => 'alert alert-danger',
        'success' => 'alert alert-success',
        'notice'  => 'alert alert-info',
        'warning' => 'alert alert-warning'
    ]);
});

I tried changing this to setShared but the result is the same.

The same thing applies to the PHTML templates too, so this (generated) does not work:

<?php echo $this->flash->output() ?>

this does:

<?php echo $this->flashSession->output() ?>

Any hint?

EDIT: I tried the following in the frontend module:

class IndexController extends ControllerBase
{

    public function indexAction()
    {

       var_dump($this->flash);
       var_dump($this->flashSession);
       $this->view->disable();
    }

}

And this is the output:

NULL
object(Phalcon\Flash\Session)#56 (9) {
  ["container":protected]=>
  object(Phalcon\Di\FactoryDefault)#1 (3) {
    ["services":protected]=>
    array(24) {
      ["annotations"]=>
      object(Phalcon\Di\Service)#3 (4) {
        ["definition":protected]=>
        string(34) "Phalcon\Annotations\Adapter\Memory"
        ["resolved":protected]=>
        bool(false)
        ["shared":protected]=>
        bool(true)
        ["sharedInstance":protected]=>
        NULL
      }
...
      ["flash"]=>
      object(Phalcon\Di\Service)#34 (4) {
        ["definition":protected]=>
        object(Closure)#33 (0) {
        }
        ["resolved":protected]=>
        bool(true)
        ["shared":protected]=>
        bool(false)
        ["sharedInstance":protected]=>
        NULL
      }
      ["flashSession"]=>
      object(Phalcon\Di\Service)#11 (4) {
        ["definition":protected]=>
        string(21) "Phalcon\Flash\Session"
        ["resolved":protected]=>
        bool(true)
        ["shared":protected]=>
        bool(true)
        ["sharedInstance":protected]=>
        *RECURSION*
      }
...

You can see NULL at line 1 o_O

The same thing on single module app gives this intead, as expected

object(Phalcon\Flash\Direct)#47 (9) {
  ["container":protected]=>
  object(Phalcon\Di\FactoryDefault)#1 (3) {
    ["services":protected]=>
    array(23) {
      ["annotations"]=>
      object(Phalcon\Di\Service)#3 (4) {
        ["definition":protected]=>
        string(34) "Phalcon\Annotations\Adapter\Memory"
        ["resolved":protected]=>
        bool(false)
        ["shared":protected]=>
        bool(true)
        ["sharedInstance":protected]=>
        NULL
      }
...

One thing: are you sure that you have 2 declarations for flash messages? I mean - one for flash with session and one with direct? Please, look at: https://docs.phalcon.io/4.0/en/flash#dependency-injection .



19.7k

Hi, i did not add any service to the defaults generated by devtools :) I can't find a duplicate anywhere but in any event i don't understand why the service is not appearing at all defined with it's name. A double definition would overwrite the first one but one should exists!

Any other idea?



19.7k
Accepted
answer
edited Jul '20

Bug found!

    return $flash;

This is missing in services_web.php as generated by phalcon devtools. Generated code:

/**
 * Register the session flash service with the Twitter Bootstrap classes
 */
$di->set('flash', function () {
    $escaper = new Escaper();
    $flash = new Flash($escaper);
    $flash->setImplicitFlush(false);
    $flash->setCssClasses([
        'error'   => 'alert alert-danger',
        'success' => 'alert alert-success',
        'notice'  => 'alert alert-info',
        'warning' => 'alert alert-warning'
    ]);
});