How to pass values to helper / Helper Loader 30/01/2012

If you need to pass a helper already defined values or database results, you can do it through anonymous function. Static list $genderTypes = array( 'ma' => 'Male', 'f' => 'Female', ); $this->template->registerHelper('gender', function($gender) use($genderTypes) { if (isset($genderTypes[$gender])) { return $genderTypes[$gender]; } return 'gender unknown'; }); Items list from database $categoryList = $this->models->categories->fetchAll(); $this->template->registerHelper('category', function($categoryId) use($categoryList) { if (isset($categoryList[$categoryId])) { return $categoryList[$categoryId]; } return 'unknown'; }); Helper Loader Another and easily extensible solution is to use your own helper loader.

If you need to pass a helper already defined values or database results, you can do it through anonymous function.

Static list

$genderTypes = array(
        'ma' => 'Male',
        'f' => 'Female',
);

$this->template->registerHelper('gender', function($gender) use($genderTypes) {
        if (isset($genderTypes[$gender])) {
                return $genderTypes[$gender];
        }
        return 'gender unknown';
});

Items list from database

$categoryList = $this->models->categories->fetchAll();

$this->template->registerHelper('category', function($categoryId) use($categoryList) {
        if (isset($categoryList[$categoryId])) {
                return $categoryList[$categoryId];
        }
        return 'unknown';
});

Helper Loader

Another and easily extensible solution is to use your own helper loader. You can extend the class and simply test them and move to other projects.

Following example respects Dependency Injection, so it’s passing only required services, you can use to access database, predefined parameters, path to dirs temp, app etc. Our loader contains helper profilePicture, which based on file name return route to profile photo, resp. to default “no profile photo” file.

namespace App;

class Helpers extends Nette\Object
{
        /** @var string */
        private $wwwDir;

        /** @var Nette\Http\IRequest */
        private $httpRequest;

        public function __construct($wwwDir, Nette\Http\IRequest $httpRequest)
        {
                $this->wwwDir = $wwwDir;
                $this->httpRequest = $httpRequest;
        }

        /**
         * Method we will register as callback
         * in method $template->registerHelperLoader().
         */
        public function loader($helper)
        {
                if (method_exists($this, $helper)) {
                        return callback($this, $helper);
                }
        }

/* === Following particular helpers === */

        /**
         * Display profile photos
         *
         * <code>
         * <img src="{'JohnDoe.jpg'|profilePicture}">
         * </code>
         *
         * @param  string name of file with photo
         * @return string route to profile photo of default picture
         */
        public function profilePicture($fileName)
        {
                $basePath = $this->httpRequest->url->scriptPath;
                if (is_file($this->wwwDir . '/photos/' . $fileName)) { // profile photo exits
                        return $basePath . '/photos/' . $fileName;
                } else { // profile photo doesn't exist
                        return $basePath . '/photos/noPhoto.jpg';
                }
        }
}

If you need use presenter functions in helper (redirect(), link() etc.), zou have to pass service @application through the __construct. Presenter will be accessible through $application->getPresenter() during template rendering.

How to register helper loader?

Set it as a service first in application config.

common:
    services:
        myTemplateHelpers:
            factory: App\Helpers( %wwwDir%, @httpRequest )

Than we can register Helper loader in BasePresenter.php by callback to our method loader() into Template::registerHelperLoader().

abstract class BasePresenter extends Nette\Application\UI\Presenter
{

    public function createTemplate($class = NULL)
    {
        $template = parent::createTemplate($class);
        $template->registerHelperLoader(callback(
            $this->context->myTemplateHelpers,
            'loader'
        ));
        return $template;
    }
}