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

Is a view service a must in a module?

One of my modules will be a worker used e.g to send e-mails.

Is it possible not to define a view service in such module? When I try not to define a view a get an Exception.

I know that view is one of three parts of MVC but still, is it possible?

edited Aug '14

In any module you can define custome services, and views too.

But if you want to post email from HTML template just do something like this:

First variant:

class EmailSender extends \Phalcon\Mvc\User\Component {
        public function sendNotificationEmail($user){
                $this->view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_ACTION_VIEW);
                $this->view->setVar('login', $user->email);
                $this->view->start();
                $this->view->render('email','activation-info');
                $this->view->finish();

                $template = $this->view->getContent(); //here u will be have a full prepared and compiled HTML template
                //process send email here
                $this->view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_LAYOUT); // back to the normal rendering

        }
}

Second variant:

class EmailSender extends \Phalcon\Mvc\User\Component {
        public function sendNotificationEmail($user){
                $this->view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_ACTION_VIEW);
                $this->view->setVar('login', $user->email);
                $this->view->start();
                $this->view->pick('email/activation-info');
                $this->view->finish();

                $template = $this->view->getContent(); //here u will be have a full prepared and compiled HTML template

                //process send email here
                $this->view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_LAYOUT); // back to the normal rendering
        }
}

In Controller

 public function signUpAction(){
     //some stuff here validation, post data and save user
     $email = new \EmailSender();
     $email->sendNotificationEmail($user); //this it will set render level for ACTION and send your email after send email don't forget to set renderLevel back to \Phalcon\Mvc\View::LEVEL_LAYOUT
 }

I hope this help!!

And how about set custom views for any module just look at my AutoRoute plugin how i set views and where. https://github.com/softdream/Phalcon-autorouter



26.3k

Thanks a lot for your reply @softdream ! Fortunately have similiar code but have some questions.

(A) As I understand, your code is for such situation: you both render an e-mail and send it within the same request? Let's say registering a user will be this request.

(B) Setting rendering levels for \Phalcon\Mvc\View::LEVEL_ACTION_VIEW and then back for \Phalcon\Mvc\View::LEVEL_LAYOUT is done not to have any collision with a HTML that should be shown to the user?

My situation is a bit different.

In user's request I only save in the database an information that an e-mail should be sent (with some its parameters). Actual e-mail sending is not performed in this request (user experience). I have a worker in another module under cron which is sending e-mails, SMSes etc. I want it working via some queue like beanstalkd but I have not learned how to do it yet.

So my worker is not showing any output to the user (in fact there is no user). It only need to produce html/text for e-mails/SMS.

For now my code to produce HTML is similiar to yours:


$view = new \Phalcon\Mvc\View();

$view->setViewsDir('somedir');
$view->setVar("parameters", $someparameters);

$view->start();
$view->render('subdirectory','file');
$view->finish();

$html = $view->getContent();

The difference is that I don't change render levels.

My questions:

(C) Let's say my worker in one request sends 100 e-mails and each has different HTML. Is there any risk with my code that there will be some mess in produced HTMLs?

Still, my first question. Must I define any view in service container? For now I don't know how to achive NOT defining any.

edited Aug '14

A Yes in one request, look at my controller action part:


            $user->save();
            $email = new \Manager\Library\Components\Email();
            $email->sendVerifyEmail($user);

            $this->flash->success('Vše proběhlo v pořádku, neradi to děláme ale snažíme se chránit jak nás tak Vaše soukromí<br />
            a právě proto potřebujeme ověřit Váš email, jenom klikněte na odkaz uvedený v emailu a hned budeme pokračovat.');

            $this->flash->warning('Pozor! Platnost ověřovacího emailu je 24 hodin.');

It will continue render your controller view.

B No it will not have any collision look above.

C Just do some global template which u can store into variable and replace the vars inside for example i'm using something like this:

<div>
##myCustomVar##
{{ phalconVar }}
<div>##myNextCustomVar##</div>
</div>

Then pick or render the template and get it into variable

and in loop you can do something like this


foreach($items as $item){
    $findVars = array('##myCustomVar##','##myNexCustomVar##');
    $replaceVars = array($item['myvalue'],$item['mynextValue']);
    $emailHtml = str_replace($findVars,$replaceVars,$template);
    //send email
}

This will save you many unneccessary rendering template.



26.3k
edited Aug '14

Thanks, now I understand everything - I think so :)

Thanks for the idea from C but this would be too difficult in my case. My e-mail rendering is too complex so I stay with Phalcon's views.



26.3k
Accepted
answer
edited Aug '14

I have found answer for my question in another topic here https://forum.phalcon.io/discussion/2819/how-to-disable-views-in-restful-api-app.

So the answer is: Yes, defining a view is a must.

Sorry for starting an old issue again!