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

How Component generates render view and passes it to Backend which generates render view and send to display?

Hello,
I have an advanced file hierarchy.

  • Application
    • Backend
      • Controller
      • View
      • Module.php
    • Frontend
      • ...
  • Component
    • ...
    • Geoloc
      • City
        • Controller
        • Model
        • View
        • Module.php
  • View
    • layout
    • partial

All my routes redirect only on Backend or on Frontend.
I have build a City Component Service add to DI. I call it from a VilleController from Backend.

The Component should generates render of its own view and passes it to Backend Controller which generates rendering of its view with page layout and send to display. (Because there might be several Services called within same ControllerAction on Backend or Frontend)

I tried several versions of rendering but I can not connect the two parts.

PHP Fatal error: Call to undefined method AdCms\Component\Geoloc\Ville\Controller\IndexController::getId() in /.../AdCms/www/cache/volt/%%users%%elroliv%%sites%%adcms%%www%%app%%component%%geoloc%%ville%%view%%index%%villes.volt.php on line 8

getId() is a public function from my model and not from City Component IndexController.

Perhaps it's not the good way to render Component/Controller in its own view and pass html code at Interface/BackendController to render it's own view too.

Can someone advise me? Thank a lot

Component/Geoloc/City

File : Component/Geoloc/City/Module.php

$di->set('moduleView', function () {
    $view = new Simple();
    $view->setDI($this);
    $view->setViewsDir(__DIR__ . '/View/');

    $view->registerEngines([
        '.volt'  => 'volt',
        '.phtml' => 'phpTemplating',
    ]);

    return $view;
});

$di->setShared('ville', function () {
    return new IndexController();
});

File : Component/Geoloc/City/Controller/IndexController.php

public function villesAction()
{

    $template = $this->moduleView->render(
        "index/villes",
        [
            "villes" => Ville::find(
                [
                    "limit" => 100,
                ]
            ),
        ]
    );

    return $template;
}

File : Component/Geoloc/City/Model/Ville.php

class Ville extends Model
{
    protected $id;
    protected $name;
    public function getId()
    {
        return $this->id;
    }
    public function setId($id)
    {
        $this->id = $id;
    }
    public function getCommune()
    {
        return $this->name;
    }
    public function setCommune($commune)
    {
        $this->name = $commune;
    }
}

File : Component/Geoloc/City/View/index/villes.volt

<div class="page-header">
    <h1>Module Geoloc / Ville</h1>
</div>

{% if not villes is empty %}
    <h2>villes : </h2>
    {% for ville in villes %}
        {{ ville.getId() }} {{ ville.getName() }}{% if not loop.last %}<br>{% endif %}
    {% endfor %}
{% else %}
    <p><i>aucune ville récupérée</i></p>
{% endif %}

Application/Backend

File : Application/Backend/Module.php

$di->set('view', function () {
    $view = new View();
    $view->setDI($this);
    $view->setViewsDir(array(__DIR__ . '/View/'));

    $view->setLayoutsDir(APP_PATH . '/View/layout/');
    $view->setTemplateAfter('bootstrap4-fixed-nav-dev');

    $view->registerEngines([
        '.volt'  => 'volt',
        '.phtml' => 'phpTemplating'
    ]);

    return $view;
});

File : Application/Backend/Controller/VilleController.php

public function villeAction()
{
    $villes = $this->getDI()->getShared('ville');

    $this->view->villes = $villes->villesAction();

}

File : Application/Backend/View/ville/ville.volt

<div class="page-header">
    <h1>Interface Backend / Ville</h1>
</div>

{{ villes }}

And what exactly problem you have? You can register this service just anywhere you want, like in some genric file like services.php



3.4k
edited May '17

And what exactly problem you have? You can register this service just anywhere you want, like in some genric file like services.php

Sorry, i'd forgot to write error ;o)

Services look like good but rendering don't work :o((

PHP Fatal error: Call to undefined method AdCms\Component\Geoloc\Ville\Controller\IndexController::getId() in /.../AdCms/www/cache/volt/%%users%%elroliv%%sites%%adcms%%www%%app%%component%%geoloc%%ville%%view%%index%%villes.volt.php on line 8

getId() is a public function from my model and not from City Component IndexController.

I don't understand how generate render from my component and passed it to Backend Controller who should render its own view.



145.0k
Accepted
answer
edited May '17

Why you just dont use partials for example and do this find in villeAction? Tbh this is really bad app design currently, it's bad idea to call action in other action and get template. There are better ways of doing it.



3.4k

Why you just dont use partials for example and do this find in villeAction? Tbh this is really bad app design currently, it's bad idea to call action in other action and get template. There are better ways of doing it.

As Phalcon is loosely coupled, allowing to use its objects as glue components, I would like building an app easy maintainable that's why I'd think adding bundle components encapsulating models, views, ...

I understand I'm not on the good way. ;o)) I'll following your advice about action calling action. Indeed that was a bad idea. All calls will be only from Frontend and Backend.

I'm asking to me if I can keep my app tree or something like this.

I think, I can call Component/Geoloc/City/Model/Ville.php directly in Application/Backend/Controller/VilleController.php.

Do you think there is a way to call or render a volt template (like Component/Geoloc/City/View/index/villes.volt) directly in Application/Backend/Controller/VilleController.php?

Thanks for your time and your advice, regards

Yes, just partial most likely or include with proper path.



3.4k

thanks a lot ;o)