Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inspired by @reinink plates and @symfony template slot #46

Closed
wants to merge 1 commit into from
Closed

Inspired by @reinink plates and @symfony template slot #46

wants to merge 1 commit into from

Conversation

harikt
Copy link
Member

@harikt harikt commented Nov 14, 2013

This is adding sections in a view. The section must be rendered before the used variable.

@pmjones
Copy link
Member

pmjones commented Nov 14, 2013

I like the idea, but I think we can modify the implementation to use a closure. Instead of start() and end(), we might do something like this:

public function section($name, $callable)
{
    ob_start();
    call_user_func($callable);
    $this->section[$name] = ob_get_clean();
}

And then in the template:

$this->section('sidebar', function () { ?>
    <h2>Sidebar</h2>
    <p>This is the sidebar.</p>
?> });

But I still want to think about it a little.

@harikt
Copy link
Member Author

harikt commented Nov 14, 2013

I am not sure why you prefer callable. Is there anything we get via callable ? may be we need to pass the data also here in that case.

After a sleep what I have in mind is place the value in $this->section['name'] , and we use $this->section['name'] where ever we use $this->{sectionname} . That helps to check internally return isset($this->section['name']) ? $this->section['name'] : ''

@harikt harikt modified the milestone: Beta3 Apr 18, 2014
@pmjones
Copy link
Member

pmjones commented May 15, 2014

After reviewing again, it looks like Plates does sections by buffering input to a variable ...

<?php $this->start('section_name') ?>

    <h1>Welcome!</h1>
    <p>Hello <?=$this->e($this->name)?></p>

<?php $this->end() ?>

... and then echoing the variable:

<?= $this->section_name ?>

We can do the same thing using render(), although it does mean putting the section code into its own template:

<?php
// first ...
$this->section_name = $this->render('section_name');

// later...
echo $this->section_name;
?>

Does that seem sufficient?

@harikt
Copy link
Member Author

harikt commented May 16, 2014

@pmjones I am not sure of the outcome though.

The idea is in layout you don't need to use a test for whether the variable is initialized or not. And if it is called to render in the template add the contents in the layout.

Can we make something like this ? Only render if the_section_name is in the wrapper, else not if the view is nosection. And yes we may be having more sections in layout.

$view_registry = $view->getViewRegistry();
$view_registry->set('layout', function () {
    echo "This is the main content." . PHP_EOL;
    echo $this->section('the_section_name');
});

$layout_registry = $view->getLayoutRegistry();
$layout_registry->set('wrapper', function () {
    echo "Before the main content." . PHP_EOL;
    echo $this->content;
    echo "After the main content." . PHP_EOL;
    $this->section()->the_section_name = $this->render('the_section_name');
})

$layout_registry->set('nosection', function () {
    echo "No section content." . PHP_EOL;
})

$view->setView('main_content');
$view->setLayout('wrapper');
$output = $view();

@pmjones
Copy link
Member

pmjones commented May 16, 2014

The idea is in layout you don't need to use a test for whether the variable is initialized or not. And if it is called to render in the template add the contents in the layout.

In Plates, it looks like you do need to test if the variable is initialized. If you never start a section named "foo", and try to echo $this->foo, it won't work because the property won't exist.

@pmjones
Copy link
Member

pmjones commented May 16, 2014

Tell you what -- how does this look as an addition to Aura.Html?

<?php
namespace Aura\Html\Helper;

class Section extends AbstractHelper
{
    protected $section = array();

    protected $capture = array();

    public function __invoke()
    {
        return $this;
    }

    public function __set($name, $spec)
    {
        $this->section[$name] = $spec;
    }

    public function __get($name)
    {
        return $this->section[$name];
    }

    public function __isset($name)
    {
        return isset($this->section[$name]);
    }

    public function __unset($name)
    {
        unset($this->section[$name]);
    }

    public function begin($name)
    {
        $this->capture[] = $name;
        ob_start();
    }

    public function end()
    {
        $spec = ob_get_clean();
        $name = array_pop($this->capture);
        $this->__set($name, $spec);
    }
}
// usage:

// set directly into section helper:
$this->section()->foo = $this->render('_foo'); 

// capture into section helper:
$this->section()->start('bar');
echo "bar bar bar";
$this->section()->end();

// either way, echo directly:
echo $this->section()->foo;
echo $this->section()->bar;
?>

@pmjones
Copy link
Member

pmjones commented May 16, 2014

Hm. On further consideration I see that sections are not necessarily HTML specific, and might belong in the view after all. What about this in AbstractView?

<?php
    protected function beginSection($name)
    {
        $this->capture[] = $name;
        ob_start();
    }

    protected function endSection()
    {
        $body = ob_get_clean();
        $name = array_pop($this->capture);
        $this->setSection($name, $body);
    }

    protected function setSection($name, $body)
    {
        $this->section[$name] = $body;
    }

    protected function getSection($name)
    {
        return $this->section[$name];
    }

    protected function hasSection($name)
    {
        return isset($this->section[$name]);
    }
?>

Usage:

<?php
// usage:

// set directly:
$this->setSection('foo', $this->render('_foo')); 

// capture into buffer
$this->beginSection('bar');
echo "bar bar bar";
$this->endSection();

// either way, echo directly:
echo $this->getSection('foo');
echo $this->getSection('bar');
?>

@harikt
Copy link
Member Author

harikt commented May 17, 2014

@pmjones I like the last one. beginSection and endSection . Also can we make a return empty string on calling getSection .

protected function getSection($name)
{
    if ($this->hasSection($name)) {
        return $this->section[$name];
    }
    return '';
}

@pmjones
Copy link
Member

pmjones commented May 17, 2014

Why do we think it's important to return an empty string instead of checking with hasSection()? Avoiding an if() statement does not strike me as a benefit here.

@harikt
Copy link
Member Author

harikt commented May 17, 2014

I don't need to write an if () in template :) .

@pmjones pmjones closed this in 9120f5f May 19, 2014
@harikt harikt deleted the section branch May 19, 2014 17:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants