phalcon

Using views in Phalcon Task


for one of my developments, I would like to run a Phalcon task that can retrieve the HTML code of a .volt view. The purpose of using a .volt view is to pass parameters to my .volt view before retrieving the HTML code. However, I have not found any discussion about this way of doing things, hence the reason why I am coming to you. And I wanted to know if it is possible to use .volt views in a Phalcon task.

PS:I am currently using version 3.4.5 of Phalcon

I tried this :

public class TestTask {
    public function mainAction() {
        $diViews = $this->getDI()->get("view");
        $diViewsBackend->start();
        $diViewsBackend->setRenderLevel(\Phalcon\Mvc\View::LEVEL_ACTION_VIEW);
        $diViewsBackend->render("test", 'test', $dataForReport);
        $diViewsBackend->finish();
        echo $diViewsBackend->getContent();
    }
}

But in my view .volt, I use stylesheet_link which generated this error : PHP Fatal error: Uncaught Error: Call to a member function stylesheetLink() on null

Thanking you in advance for the help you could give me

Update of 20/03 to answer Arthur : Register service :

$di->set(
            'viewGvReport',
            function () {
                $viewGvReport = new \Phalcon\Mvc\View\Simple();
                $viewGvReport->setViewsDir(__DIR__ . '/views/');

                $viewGvReport->registerEngines(
                    array(
                        ".volt" => function ($view, $di) {
                            $volt = new Volt($view, $di);

                            $compiler = $volt->getCompiler();
                            $compiler->addFunction('ucfirst', function($params) {
                                return "mb_strtoupper( mb_substr( $params, 0, 1 )) . mb_substr( $params, 1 )";
                            });
                            $compiler->addFunction('stylesheetLink', function($parameters, $local) {
                                return null;
                               return \Phalcon\Tag::stylesheetLink($parameters, $local);
                            });
                            return $volt;
                        }
                    )
                );

                return $viewGvReport;
            },
            true
        );

In Task :

$html = $this->view->render(
      "controller", "view", []
);

In my view .volt :

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    {{ stylesheet_link('https://fonts.googleapis.com/css?family=Barlow+Semi+Condensed:200,200i,400,500&amp;subset=latin-ext') }}
    {{ stylesheet_link('assets2/css/report.min.css?version=2.9.4') }}
    <title>Report</title>
</head>

<body>
<!-- content body with some with some expected parameters -->
</body>
</html>

Solution

  • You can register the Simple View service:

    use Phalcon\Mvc\View\Simple as SimpleView;
    use Phalcon\Mvc\View\Engine\Volt;
    
    $di->set(
    'view',
    function () {
        $view = new View();
    
        $view->setViewsDir('../app/views/');
    
        $view->registerEngines(
            [
                '.volt' => Phalcon\Mvc\View\Engine\Volt::class
            ]
        );
    
        return $view;
      }
    );
    
    //In CLI, you must register as well the Tag service:
    $di['tag'] = function () {
       return new Phalcon\Tag();
    };
    
    //and probably you will need the Url service too:
    
    $di->set(
    'url',
    function () {
        $url = new Phalcon\Mvc\Url();
    
        $url->setBaseUri('/');
    
        return $url;
     }
    

    );

    And in the Action of your Task, you can pick up the view and return the code as string:

     public class TestTask {
      public function mainAction() {
          $html = $this->getView('Main/test', $dataForReport);
          //generate PDF
      }
    
      private getView($view, $dataForReport)
      {
           return $this->view->render(
            $view, ['data' => $dataForReport]
           );
      }
    }
    

    It is split in a private function in case you need to generate more views. Otherwise, leave it in one line in your mainAction.