The default zend framework 2 configuration relies on phtml files for view rendering. However, for security reasons I want to change that to php.
From this link I understand that I need to create a custom view helper in order to do that or is there a setting I can change to change the suffix from phtml to php and how is this done exactly?
Update: I got it working, but not the way I want. If possible I would like to get the answer from guessimtoolate working. So I prefer something like this in my module.config.php:
'view_manager' => array(
'default_suffix' => 'php',
//etc...
)
If my memory serves my well, you can define that in default_suffix key in your module's configuration file under view_manager, e.g.:
return array(
// ...
'view_manager' => array(
'default_template_suffix' => 'php',
// ...
),
// ...
);
This should make template file resolvers to look for .php files instead of .phtml.
Not entirely sure how's that an improvement, but it can be done.
UPDATE:
Sorry, I've wrote the wrong configuration key name -- it should be default_template_suffix and not default_suffix. It is used, e.g.: in Zend\Mvc\Service\ViewTemplatePathStackFactory where path stack resolvers are born :).
Try this in your module.php:
//module.php
public function onBootstrap(MvcEvent $e)
{
$application = $e->getApplication();
$sm = $application->getServiceManager();
$sm->get('ViewTemplatePathStack')->setDefaultSuffix('php');
}
Then change all .phtml files to .php in your project.
In your Application module, the Module.php file:
public function onBootstrap($e)
{
$app = $e->getApplication();
$sl = $app->getServiceManager();
$resolver = $sl->get('ViewTemplatePathStack');
$resolver->setDefaultSuffix('php');
}
What happens here, is during bootstrap you grab the path stack and sets the suffix on the resolver.
Related
I'm trying to load a template in PhalconPHP (v 2.0.13), but even the simplest example doesn't seem to work. I'm trying to access http://www.mysite.dev.fb/forms/ in this example. Here is my router:
$router->add(
'/forms/',
[
"namespace" => "Render\\Controller",
"controller" => "index",
"action" => "forms",
],
['GET']
);
The routing works, or at least the code in the action is reached (vardumps, etc).
Here's my Controller action variants.
Variant 1
public function formsAction()
{
}
In this case, the template located at app/views/index/forms.volt (I have a copy of the file with an .phtml extension, for debugging purposes) should be loaded, right? Wrong, an empty screen is displayed, no errors in errorlog.
Variant 2
Then, I tried picking the view, like that:
$this->view->setViewsDir(__DIR__ . '/../views/');
$this->view->pick('forms/contact');
The file, app/views/forms/contact.volt, also exists, with full permissions. Vardumping $this->view->getContent() returns null and the result is again an empty white screen without any errors.
Variant 3
Desperately, I tried directly rendering the template (for this example I'm using the default Phalcon index/index template) like this:
$this->view->start();
$this->view->render('index', 'index'); //Pass a controller/action as parameters if required
$this->view->finish();
The only difference is that now vardumping $this->view->getContent() returns an empty string, instead of null.
It's like automatic rendering is disabled, but the following line returns false (as it should):
var_dump($this->view->isDisabled());
I'm out of ideas, can anyone help? If I forgot to include something, respond and I'll include it.
You should definitely check your PHP logs for PHP errors. Also I suspect that your volt declaration might be wrong. Here is a working example of declaring a dependency injectable view component in services that I use:
$di->setShared('view', function () use ($di,$config) {
$view = new View();
$view->setViewsDir($config->application->viewsDir); // path to directory with views, loaded from config in this case
$view->registerEngines(array(
'.volt' => function ($view, $di) use ($di, $config) {
$volt = new VoltEngine($view, $di);
$volt->setOptions(array(
'compiledPath' => $config->application->cacheDir, // path to cache dir, loaded from config in this case
'compiledSeparator' => '_'
));
return $volt;
},
'.phtml' => 'Phalcon\Mvc\View\Engine\Php'
));
return $view;
});
Ensure that your webserver has rights to read views and R/W rights for cache directory. Hope it will help you
I have a controller with two actions what uses the exact same view file (the index.phtml)
If the URL says for example : localhost/public/map
Then the URL for the image file is localhost/public/style/img.jpg
But if I use a different action in the same controller then the URL will change to localhost/public/map/style/img.jpg what doesn't exist.
Also if I am not using the same template so I have a separate one for choose action, it is doing the exact same thing so it will have the extra "map" word in the URL.
Any idea how could I get this solved?
Example code:
Controller
public function indexAction(){
$view = new ViewModel();
return $view;
public function chooseAction(){
$view = new ViewModel();
$view->setTemplate("map/index"); //will not work with just "index"
return $view;
}
index.phtml
<?php
// module/Map/view/index.phtml:
$title = 'Map';
$this->headTitle($title);
?>
<img src="style/img.jpg"/>
You can simply point to the absolute path of the image:
<?php
// module/Map/view/index.phtml:
$title = 'Map';
$this->headTitle($title);
?>
<img src="/public/style/img.jpg"/>
If you want the template to be named index instead of map/index you have to change the template name in your template_map in the module.config.php file in the config folder:
Now probably it looks probably like this:
'view_manager' => array(
//...other things
'template_map' => array(
'map/index' => __DIR__ . '/../view/layout/index.phtml',
//...more view templates
)
)
Simply change to 'map/index' to 'index'. Then you can do:
$view->setTemplate("index");
Update:
From your comment I understand that part of the problem is that you don't want to hardcode your folder names. In that case you can always use the php __NAMESPACE__ constant. This might solve your issue regarding hardcoding paths inside your modules.
If you would later put your site in a folder and you configure everything correctly then using an absolute path to your images should not be a problem.
I'm trying to send a variable to a twig file which is not in the typical location, Usually I'm loading views by specifying their path through the Bundle but the file I want to send a variable to is not, hierarchically, on the same level as the other twig templates.
I've a controller which looks like the following:
public function fooAction(Request $request)
{
*//Query*
return $this->render('Bundle:file.html.twig', array('varToSend' => $queryResult));
}
I'm pretty sure the Bundle:file.html.twig is wrong but I don't know how else to specify the relevant path in twig.
Twig you would get from container would not work with arbitrary paths, but you can initialize your own twig:
$twig = new \Twig_Environment(new \Twig_Loader_String());
$rendered = $twig->render(
file_get_contents('/path/to/your/file.html.twig'),
array('varToSend' => $queryResult)
);
If you need this in more than one place, consider making it a Symfony service in order to not initialize Twig Environment every time.
Note that renderer in this case won't have any of Symfony's Twig Extensions, you'll have to add them manually.
If possible, try to avoid this, and put templates into app/Resources/views or src/AppBundle/Resources/views directories.
You have to use a path like that :
return $this->render('Bundle:Something:file.html.twig', array(
'varToSend' => $queryResult
));
And put your file in this folder :
src/Bundle/Resources/views/Something/file.html.twig
With any regular page I set up a Zend\Cache\Pattern\CaptureCache, catch the onFinish event, and send the rendered version to a message queue for later processing. So far, so good...
Problem: sometimes I need to render two versions of the same action in the same request; one for mobile and one for desktop and I'm not sure how to do that.
If it helps, the actions that I need to "double render" actually create two discrete ViewModel objects so that I can have full control over that.
Ended up creating a service that given these two view models would figure out which one is mobile and which one is desktop. Then it would grab the layout and render each view model separately. Finally it would bypass any caching and generate both files manually.
With the setTemplate method :)
First you create your phtml view file (already done I suppose).
then you declare it in your view manager config / template_map :
In the Module.config.php file (you create the alias to call it later in your controller) :
return array(
//[...],
'view_manager' => array(
'template_map' => array(
// [...],
'index/test' => __DIR__ . '/../view/mymodule/index/test.phtml',
),
//here your template_path_stack as usual
),
// [...],
);
(of course, put your own path ;) )
Then in your controller :
public function indexAction(){
$view = new ViewModel();
if (/*here your tests*/) {
$view->setTemplate('index/test'); //here the name declared in the template_map
}
return $view;
}
you can learn a lot here about views (and layouts): http://framework.zend.com/manual/2.2/en/modules/zend.view.quick-start.html
Reading the section Zend_Application_Resource_Modules in the docs here:
http://framework.zend.com/manual/1.10/en/zend.application.available-resources.html
I noticed this:
You can specify module-specific configuration using the module name as a prefix or sub-section in your configuration file.
using this:
[production]
news.resources.db.adapter = "pdo_mysql"
news.resources.db.params.host = "localhost"
news.resources.db.params.username = "webuser"
news.resources.db.params.password = "XXXXXXX"
news.resources.db.params.dbname = "news"
To me this is a good idea. But, when I simply add these prefixes to certain things I want to be specific to my modules, nothing changes.
So my question is: How do I tell Zend Framework to actually use these module specific prefixes?
I use the following implementation of modules in Zend. It allows you to use "module-specific" configuration.
application/config/config.ini
-----------------------------
[production]
resources.modules[] =
By doing this, you're telling Zend_Application that you want to use the Modules Bootstrap Resource plugin. The Modules plugin will load a separate bootsrap class for each of your modules, excluding the default module. Therefore, you need to create a new bootstrap class for your second module.
application/modules/news/Bootstrap.php
-----------------------------
class News_Bootstrap extends Zend_Application_Module_Bootstrap {
//---------------------------------------
// Automatically load our resources
//
// NOTE: You don't have to add this, its
// just and example to show that you
// can customize the bootstrap
// process just for this module.
public function _initModuleResourceAutoloader(){
$this->getResourceLoader()->addResourceTypes(array(
'modelResource' => array(
'path' => 'models/resources',
'namespace' => 'Resource'
)
));
}
}
This "News_Bootstrap" class will now be loaded and executed during the bootstrap process.
The naming convention for this file is important as the Modules Resource plugin needs to be able to find the class. Note that you must name the file Bootstrap.php.
Finally, you'll notice that you're subclassing the Zend_Application_Module_Bootstrap rather than Zend_Application_Bootstrap_Bootstrap like you do in the main bootstrap.
Now, your module-specific configuration should work:
[production]
news.resources.db.adapter = "pdo_mysql"
news.resources.db.params.host = "localhost"
news.resources.db.params.username = "webuser"
news.resources.db.params.password = "XXXXXXX"
news.resources.db.params.dbname = "news"