PHP Mustache combine alias loader with regular partials - mustache.php

I'm using the Mustache alias loader from this post to dynamically load partials (based on URL variables) into my default template.
This works like a charm, however, in some cases I would also like to load "regular" partials. Is there a way to combine both the dynamic alias loader and the regular partial loading?

Yep! You can use the Cascading Loader to load both alias and regular partials. Something like this should do the trick:
$partials = [
'sidebar' => 'themes/custom/sidebar',
];
$loader = new Mustache_Loader_CascadingLoader([
new FilesystemAliasLoader('path/to/partials', $partials),
new Mustache_Loader_FilesystemLoader('path/to/partials'),
]);

Related

zend 2 view rendering template with same name from a different module

I'm working with reusable modules in Zend2 and I have a little problem which concerns code duplication.
I have an User module, which has i.e an HTML template register (template path: user/user/register).
It contains some basic HTML but in one of my projects, I need to embed this template with a < div > for CSS stylization (the rest of the HTML page doesn't change).
After the User module, I load my Application module where I can overwrite the user/user/register template and put new code but I'm unable to render the original user/user/register template through it.
Example of code in Application module -> user/user/register:
<div><?=$this->render('user/user/register')?></div>
This causes an endless loop and I don't want to copy/paste all the HTML from my user/user/register template in User module.
Anyone can help me ?
Thank you !
What you're trying to achieve won't work. You can not have two templates with identical names. The Module that loads the key the latest will always have priority.
You have to understand that templates are just a key inside a big array.
'view_manager' => array(
'template_map' => array(
'layout/layout' => 'my\layout.phtml'
)
)
So if you have two modules providing this configuration, it doesn't change the fact that both use the key layout/layout. Therefore whatever Module loads later, wins.
TL/DR You can only overwrite templates, not extend them. In your case you have to create a separate template.

Laravel: How to find the right blade master template?

To extend a blade template you have to write
#extends('folder.template_name')
This works for standard installation.
I've created a module for the backend and now I can't use my module template because Laravel catches the first record and that is the standard view folder.
My structure looks like this:
app
-- modules
-- modules\backend
-- modules\backend\views
-- modules\backend\views\layouts\master.blade.php
-- views
-- views\layouts\master.blade.php
So when I'm in the backend and try to display my template:
// app\modules\backend\views\page\index.blade.php
#extends('layouts.master')
Laravel renders the app\views\layouts\master.blade.php instead of
app\modules\backend\views\layouts\master.blade.php
I've tried many names inside that #extends e.g.
#extends('app\modules\backend\views\layouts\master')
#extends('app.modules.backend.views.layouts.master')
#extends(base_path(). '\app\modules\backend\views\\' . 'layouts.master')
Nothing works.
While using a package or autoloaded module, referring to it's resources is done using the double colon notation. In your case, to access the module's master template you need to use
#extends('backend::layouts.master')
These conventions are described in the docs, for further info please refer to
Laravel 4 package conventions
Make sure /app/config/view.php has a path entry for where those views are located.
I.E.
'paths' => array(__DIR__.'/../views'),
To
'paths' => array(
__DIR__.'/../views',
__DIR__.'/../modules/backend/views'
),
or whatever represents your actual path.
From here you might want to look into doing the view folder loading via another mechanism if your views are in dynamically generated folders. Maybe a module::boot event that adds the module path to the view paths array? Just an idea.

Best Practices for Laravel 4 Helpers and Basic Functions?

I'm trying to understand the best place to put a global function in Laravel 4. For example, date formatting. I don't think making a facade is worth it as facades are too modular. I've read articles about creating a library folder and storing classes there but that also seems like a lot for a simple function. Shouldn't a 'tool' like this be available in Blade templates?
What are the best practices for something like this and how do I make it available to Blade templates?
The ugly, lazy and awful way: At the end of bootstrap/start.php , add an include('tools.php') and place your function in that new file.
The clean way: Create a library. That way it'll be autoloaded ONLY when you actually use it.
Create a libraries folder inside your app folder
Create your library file, create a class in it, and add static functions to it
Option 1: Edit start/global.php to add app_path().'/libraries' to the ClassLoader::addDirectories( array.
Option 2: Edit composer.json to add "app/libraries" to the autoload array. Run composer dump-autoload
Call your class and static functions from your views.
About your options, quoted from the global.php file
In addition to using Composer, you may use the Laravel class loader to
load your controllers and models. This is useful for keeping all of
your classes in the "global" namespace without Composer updating.
You can combine both options, where the Laravel class loader will automatically search for classes in the registered directories (Option 1, easier) and Composer will keep record of all the classes but only after you update it (Option 2, might improve performance).
My way of doing this is to create a new folder in the /app directory in the root of your Laravel 4 project. Then add this folder to the first array of the /app/start/global.php file like so:
<?php
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/classes', // This line is the one I've added.
));
As long as the folder structure within the new /app/classes folder follows your namespacing convention. Laravel 4 will autoload all the classes/files within this folder. This way there's no need to dig into any composer files or run composer command.
Not sure if this is best practice but it certainly works.
If you created a simple file called /app/classes/Helpers/Helper.php such as this:
<?php namespace Helpers;
class Helper {
public static function helloWorld()
{
return 'Hello World';
}
}
All you would need to do is call Helpers\Helper::helloWorld();
You could also alias this helper class in your /app/config/app.php file. Just add something like this to the end of the aliases array:
'Helper' => 'Helpers\Helper'
Laravel's helpers.php method is to add it to your "files" in composer.json (https://github.com/laravel/framework/blob/master/composer.json):
"autoload": {
"classmap": [
...
],
"files": [
"app/libraries/helpers.php"
],
},
What I do is to create small classes (a few methods per class, one line per method, everything extended from something and DRY, that's my goal),
class ExtendedCarbon extends Carbon\Carbon {
public function formatDDMMAAAA($date)
{
/// format and return
}
}
save them to them in app/libraries and add to composer.json:
"autoload": {
"classmap": [
...
"app/libraries",
...
],
},
Execute
composer dump
And then just use them wherever you need
$formatted = (new ExtendedCarbon)->formatDDMMAAAA($date);
Watch this video about refactoring: http://www.youtube.com/watch?v=DC-pQPq0acs
By the way, I'm kind of sure it was just an example, but you might not need a helper to format dates, since all dates in Laravel are instances of Carbon (https://github.com/briannesbitt/Carbon) and it has loads of methods to format date and time.
You can also use View::share() together with closures to achieve this - I just posted about this: http://www.develophp.org/2014/07/laravel-4-blade-helper-functions/
Added benefit: You don't need to create an extra class and also keep the global namespace clean.

Organize views and controllers with the new EmberJS router

I want to organize my views in packages / folders to avoid a long list. With the (great) new router, a view is provided by default that we can change by creating a new one with a convention name. For example:
match('/').to('home');
uses:
"home" handlebars template
App.HomeView
App.HomeController
Now I want to use:
"my_package/home" handlebars template (works)
App.MyPackage.HomeView
App.MyPackage.HomeController
When I use the gem "ember-rails" (the GIT version) and the generator:
rails g ember:view my_package/home
I get:
DemoEmberRails.MyPackage::HomeView = Ember.View.extend({
});
that is not a correct javascript code (seems to be an extract for ruby code).
I tried:
DemoEmberRails.MyPackage = {};
DemoEmberRails.MyPackage.HomeView = Ember.View.extend({
});
But it's not used by the router.
How to do that?
I think you should Namespace them using Ember.Namespace. I'm still not sure if the router will automatically search namespaces but it may?
http://emberjs.com/api/classes/Ember.Namespace.html
As you've said
match('/').to('home');
expects AppName.HomeRoute, AppName.HomeView and AppName.HomeController. So if you have a template with data-template-name="home" and a view similar to
AppName.HomeView = Ember.View.extend({
teplateName: 'home'
});
then ember will automatically connect the / route with this view.
The new ember routing guides are quite helpful here.
It looks like this is currently unsupported, however, a pull request exists to add this feature.
See:
https://github.com/emberjs/ember.js/pull/1679

Resolve view helper location from within the controller or form

I have a few view helpers that add JavaScript files when they're needed (for instance, so that only forms use CKEditor and such). My directory structure (simplified to include only the relevant files) is this:
application
--forms
--Project
AddIssue.php
--modules
--default
--views
--helpers
JQueryUI.php
Wysiwyg.php
--project
--controllers
ProjectController.php
--views
--scripts
--project
version.phtml
issueadd.phtml
What I want to do:
include CKEditor in the view project/project/issueadd
include jQuery UI in project/project/version
When I'm inside the view script, calling <?php $this->jQueryUI(); ?> works like a charm, even though the helper is in the default module's helpers directory. However, the same is not true for the controller and the form.
In the controller ProjectController.php, versionAction(), I tried to call:
$this->view->jQueryUI();
and the effect was an exception:
Message: Plugin by name 'JQueryUI' was not found in the registry; used paths: Project_View_Helper_: C:/xampp/htdocs/bugraid/application/modules/project/views\helpers/ Zend_View_Helper_: Zend/View/Helper/
Similarly, in the AddIssue.php form, I tried this:
$this->getView()->wysiwyg();
and there was an exception again:
Message: Plugin by name 'Wysiwyg' was not found in the registry; used paths: Project_View_Helper_: C:/xampp/htdocs/bugraid/application/modules/project/views\helpers/ Zend_View_Helper_: Zend/View/Helper/
Obviously, both would work if my view helpers were in the helper directories of the modules/controllers they're being called from, but since they're used across many modules, I'd like to have them in the default module's view helpers directory.
So, my questions are:
How do I access those view helpers from within the controller and the form?
Is there a simpler way to get around this (apart from simply including all javascript files in the layout)? Like creating a plugin or an action helper? (I haven't done these things before, so I really don't know, I'm only starting my adventure with ZF).
Regarding Q1 (based on the comments). You should be able to access the helpers in a usual way. However since it does not work, I think there is a problem with the way you bootstrap your view resource and/or the way how you perform concrete registration of the helpers or how you add helper path to it. I paste an example of adding helper path in Bootsrap.php:
<?php
#file: APPLICATION_PATH/Bootstrapt.php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
public function _initViewHelperPath() {
$this->bootstrap('view');
$view = $this->getResource('view');
$view->addHelperPath(
APPLICATION_PATH . '/modules/default/views/helpers',
'My_View_Helper' // <- this should be your helper class prefix.
);
}
}
?>
This off course should normally work for modular setup of ZF.
Regarding Q2:
You can use headScript view helper to manage what scripts do you load in the head tag of your layout. Using this helper you can do it from your actions.
For example. If in a layout.php you have:
<head>
<?php echo $this->headScript(); ?>
</head>
then in, e.g. indexAction you can append some JS file as follows:
$this->view->headScript()->appendFile($this->view->baseUrl('/js/someJS.js'));
As much as I hate answering my own questions, there's one more solution I came up with, based on what Marcin has suggested in his answer. It can also be done in application.ini:
resources.view[] =
resources.view.helperPath.My_View_Helper = APPLICATION_PATH "/modules/default/views/helpers"
The caveat is that the lines need to appear in this order. Should it be reversed, anything before resources.view[] = will be ignored.
I'd rather get rid of your JQueryUI.php and would use ZendX. Something like that:
In controller:
ZendX_JQuery::enableView ($this->view);
$this->view->jQuery ()->enable ()->setRenderMode (ZendX_JQuery::RENDER_ALL);
In layout:
<?php echo $this->jQuery () ?>

Resources