8.5.4: Why doesn't ElementController work in package?

Permalink
I have a package called Reviews. It's got a block Reviews where you write and submit reviews. This package is working on its own - no problem.

I'm also developing a package called Listing with a block where for each listing I want to be able to leave reviews. I could simply copy the whole view.php content from Reviews block and paste them into the Listing block. This will make my Listing's view.php "kilometer" long. What I want is to be able to insert a piece of view code into another view. That is, as was suggested, this can be done with elements. Ok then. Here's what I've done:

- I copied and renamed Reviews block's view.php into listing/elements/reviews.php
- I made a new controller file in listing/controllers/element/reviews.php with these contents:
<?php 
namespace Concrete\Package\Listing\Controller\Element;
use Concrete\Core\Controller\ElementController;
class Reviews extends ElementController
{
    public function getElement()
    {
        return 'reviews';
    }
    public function on_start()
    {
        $this->set('app', $this->app);
    }
    public function view()
    {

- In my Listing block view.php I'm trying to insert the reviews.php element:
echo 'View goes here:';
View::element('reviews', null, 'listing');

- My reviews.php element starts with:
<?php defined('C5_EXECUTE') or die("Access Denied.");
use Concrete\Core\Support\Facade\Url;
use Concrete\Core\Page\Page;
echo 'Test value: '.$test; // <- NO VALUE SET
$dh = $app->make('helper/date'); // <- EXCEPTION HERE
$page = Page::getCurrentPage();
$form_action = $view->action('submit', $app->make('token')->generate('reviews_form'));
?>
<div class="reviews">

and there on line 5 it throws the exception "Call to a member function make() on null" and it does NOT set the $test value.

And even if I explicitly set the $app myself, the exception goes away, but the controller doesn't work, it doesn't set any values (see attached).

Yes I could set everything myself in the reviews.php element view, pass some stuff to it through an array in View::element() etc. These will make it sort of work but it's not the way it should do work in MVC. Why doesn't the element controller work - this is the question!

1 Attachment

linuxoid
 
linuxoid replied on at Permalink Reply
linuxoid
I've finally found a way to get it all to work but... it turns out the process is such a pain in one place that I'd rather keep my code in one place rather than to have it logically separated. The process is not as nice as in Laravel. It works but IMO it's only worth for simple HTML. If you want controllers, css, js it's not worth the effort.

Anyway, here's what you do. Say, I have a block called Listing as part of my package called Listing and I want to insert another view element called Reviews into the Listing:

1. Make a new element listing/elements/reviews.php
2. Make a new controller listing/controllers/element/reviews.php with these contents:
<?php 
namespace Concrete\Package\Listing\Controller\Element;
use Concrete\Core\Controller\ElementController;
class Reviews extends ElementController
{
    protected $app;
    protected $form;
    protected $bID;
    protected $listing;
    public function __construct($app, $form, $bID = 0, Listing $listing)
    {
        parent::__construct();
        $this->app = $app;
        $this->form = $form;
        $this->bID = $bID;

3. Listing block view.php:
$currentPage = $app->make(\Concrete\Core\Http\Request::class)->getCurrentPage();
$argumentsForElementControllerConstructor = ['app'=>$app, 'form'=>$form, 'bID'=>$bID, 'listing'=>$listing];
$elementManager = $app->make(\Concrete\Core\Filesystem\ElementManager::class);
$element = $elementManager->get('reviews', 'listing', $currentPage, $argumentsForElementControllerConstructor);
$element->render();
Tuzpik replied on at Permalink Reply
Tuzpik
The bet.