Best practice: Zend View: Load content from database and render PHP-code included in content - zend-framework

Let's say I load a value from a database which return something like:
<?php
//Zend_Controller_Action
public function indexAction()
{
$dbContent = "<p>Hello <?php echo $user?>!</p>";
$this->view->paragraph = $dbContent;
}
?>
How is it possible, that
<?php echo $user?>
will be rendered?
What precaution need to be taken (safety issuses, XXS)?
Thanks so much indeed!
== Edit: ==
Sorry, I obviously formulated my question misunderstandingly. What I actually ment:
I would like to avoid implementing a template engine like smarty.
In my project, there will be content that has PHP-Code within a string and that needs to be parsed.
Example:
<?php
//Zend_Controller_Action
public function indexAction()
{
$dbContent = "<p>Hello <?php echo $user?>!</p>";
$this->view->paragraph = $dbContent;
}
<?php
//viewscript.phtml
$user = 'John Doe';
echo $this->paragraph;
?>
is supposed to output:
Hello John Doe!
Is there any safe solution to do this without an external template engine?
Thanks once more... :-)

If found a solution here, which seems to perfectly fill my needs.
Thanks to all who answered here,
==UPDATE==
Unfortunately the posted link is dead. However, the solution was pretty simple. As far as i Remember, it went through the following steps:
Fetch content from database and save it in a file
Use Zend_Cache to check, whether this file exists
If file exists, simply render it. If not, go to step 1.
==UPDATE II ==
Found a copy of the page:
archive.org

In zend framework you will be always be able to print string (or whatever you want) from a controller but it's a very bad practice.
You should give the $user value from the controller to the view in this way:
$this->view->paragraph = $user;
and then, in the view, have:
<p>Hello <?php echo $this->paragraph; ?>!</p>
To ensure this code from XSS you should do some check before (before you print the value) like this:
$user = strip_tags($user);

Zend Framework doesn't support automatic output escaping , but you can prevent XSS in many ways.
First of all push all values into view layer and then print them with a View Helper like Zend\View\Escape , by default it returns string under htmlspecialchars() but you can set a callback function simple with :
//view.phtml
$this->setEscape('yourClass','methodName');
$this->setEscape('functionName');
echo $this->escape($this->myGreatDbValue);
Sure you can create your custom View Helper for all your need.
Another way is to create a custom View class extending Zend\View\Abstract , override __get() magic method and filtering output .
Read documentations for Zend View Helper and Zend Filter: http://framework.zend.com/manual/en/zend.filter.html
http://framework.zend.com/manual/en/zend.view.helpers.html

Related

Cakephp Controller isn´t processing form data

Hi I´m new with cakephp (v.1.3). I´m trying to do something simple.
I have two tables: fichas[id,... etc] and labos[id,laboratorio,ficha_id] so "labos" belongs to "fichas". (labos.laboratorio is ENUM field).
I would like to view a "ficha" given labos.id and labos.laboratorio so I´ve included the following code in "home.ctp"
<h3>Mostrar Ficha</h3>
<?php echo $this->Form->create('ficha',array('action'=>'localiza'));?>
<?php echo $this->Form->radio('laboratorio',array('A','B','C'),array('A','B','C')); ?>
<?php echo $this->Form->input('id',array('label'=>'Numero','type'=>'text')); ?>
<?php echo $this->Form->end("Mostrar");?>
Then in "fichas_controller.php" added the following:
function localiza(){
$laboratorio=$this->data['Ficha']['laboratorio'];
$id=$this->data['Ficha']['id'];
if(!$id){
$this->Session->setFlash('Por favor introduzca un valor valido');
$this->redirect(array('action'=>'index'));
}
$this->set('fichas',$this->Ficha->findID($id,$laboratorio));
}
Finally in the model "ficha.php" the following:
function findID($id=null,$laboratorio=null){
return $this->find('all',array('conditions'=>array('Labo.laboratorio'=>$laboratorio,'Labo.id'=>$id)));
}
Obviously the file views/fichas/localiza.ctp exists
The thing is when I press the submit button in the form it just reloads the home.ctp page. Looks like the controller´s code is not being executed because i´ve tried to force the error message that should load the index action changing the if condition to true but the same result. I´ve changed the name of the function in the model expecting an error to ocurr but I get the same result.
I have another two forms in the home.ctp page but calling another actions and models.
One of them its almost identical and it works fine.
I can´t figure out the error.
Thanks in advance for any help.
Marcelo.
The array key $this->data['Ficha'] likely doesn't exist. You've created the lowercase "ficha" form, this name should be capitalized, otherwise the data is available in $this->data['ficha']. So the form creation call would look like this:
<?php echo $this->Form->create('Ficha',array('action'=>'localiza'));?>
You can debug in two ways on Cake
Configure::write('debug', 2);
debug($this->data);
OR
The other PHP ways
print_r($this->data);
This way, you will know if you are passing the data->params properly.
Why is your model has first charcter in lower-case? It should be
Fichas
Labos
Then you can issue a direct find on the controller, if you only want.
$d = $this->Fichas->find('all', array();
You might have added the home.ctp file into another controller. Try adding the controller in the following line:
<?php echo $this->Form->create('ficha',array('controller' => 'fichas', 'action'=>'localiza'));?>
Hope it helps.

Zend framework - access controller or model from the view

I need to give the front-end designer the ability to choose whether or not to display a single xml feed or an mash-up, from the view.phtml file
This means I need to be able to call a method from the controller or model which then returns a variable to the view containing the requested feed(s).
So how do I access methods of the controller or model from the view?
you don't call controller methods in view , but you can create an instance of model (for read only purposes) inside view and then call its public methods .eg
Foo.phtml
<?php $feedsTb = new Default_Model_Feeds() ?>
<?php $allFeeds = $feedsTb->fetchAll(); ?>
I don't know if i got your problem right, but this is something i'd probably do in a way like
Controller:
if($this->_getParam('single')) {
$this->view->data = $model->getFeedSingleData();
$this->render('single_feed.phtml');
} else { //mashup
$this->view->data = $model->getMashUpData();
$this-render('mashup_feed.phtml');
}
Though admittedly an example like this is better off with two different actions (singleAction() and mashupAction())
But i really don't know if i got your problem figured out at all :S You may explain it further

Zend Form Element with Javascript - Decorator, View Helper or View Script?

I want to add some javacsript to a Zend_Form_Element_Text .
At first I thought a decorator would be the best way to do it, but since it is just a script (the markup doesn't change) then maybe a view helper is better? or a view script?
It seems like they are all for the same purpose (regarding a form element).
The javascript I want to add is not an event (e.g. change, click, etc.). I can add it easily with headScript() but I want to make it re-usable , that's why I thought about a decorator/view helper. I'm just not clear about the difference between them.
What is the best practice in this case? advantages?
UPDATE: Seems like the best practice is to use view helpers from view scripts , so decorators would be a better fit?
Thanks.
You could create your own decorator by extending Zend_From_Decorator_Abstract and generate your snippet in it's render() method :
class My_Decorator_FieldInitializer extends Zend_Form_Decorator_Abstract {
public function render($content){
$separator = $this->getSeparator();
$element = $this->getElement();
$output = '<script>'.
//you write your js snippet here, using
//the data you have in $element if you need
.'</script>';
return $content . $separator . $output;
}
}
If you need more details, ask for it in a comment, i'll edit this answer. And I didn't test this code.
Use setAttrib function.
eg:-
$element = new Zend_Form_Element_Text('test');
$element->setAttrib('onclick', 'alert("Test")');
I'm not actually seeing where this needs to be a decorator or a view-helper or a view-script.
If I wanted to attach some client-side behavior to a form element, I'd probably set an attribute with $elt->setAttrib('class', 'someClass') or $elt->setAttrib('id', 'someId'), some hook onto which my script can attach. Then I'd add listeners/handlers to those targeted elements.
For example, for a click handler using jQuery , it would be something like:
(function($){
$(document).ready(function(){
$('.someClass').click(function(e){
// handle the event here
});
});
})(jQuery);
The benefit is that it is unobtrusive, so the markup remains clean. Hopefully, the javascript is an enhancement- not a critical part of the functionality - so it degrades gracefully.
Perhaps you mean that this javascript segment itself needs to be reusable across different element identifiers - someClass, in this example. In this case, you could simply write a view-helper that accepts the CSS class name as the parameter.
"the markup doesn't change", Yap,
but I like to add some javascript function throw ZendForm Element:
$text_f = new Zend_Form_Element_Text("text_id");
$text_f->setAttrib('OnChange', 'someFunction($(this));');
The best way is if you are working with a team, where all of you should use same code standard. For me and my team this is the code above.

Zend Framework multiplay forms

I want get the follow thing working.
I've a page with a couple of text articles, each article has his own 'id' in the database. Below every article I want to make it possible to discuss about it. So I setup a discuss form witch I print with my article trough a 'foreach'.
In the form I added a Zend_Form_Element_Hidden. In the view I want to set the value of the hidden field with 'article_id', this likes me the best way to put it in the database?
In the foreach I try the follow thing but when I do this, the form is gone and I only get the element where I add the value.
My code in the view:
foreach ($this->paginator as $article):
echo $this->form->getElement('article')->setValue($article['id']);
endforeach;
I hope some one can make this a bit more clear for me :)
With kind regards,
Nicky
I am guessing you want to print the form inside the loop but only the element is being printed.
If that is your problem, the reason is because setValue() returns the element and not the form.
// Your Code
// This will only print the element and not the entire form
echo $this->form->getElement('article')->setValue($article['id']);
You will have to change your code to:
// Set the element value first
$this->form->getElement('article')->setValue($article['id']);
// Then render the form
echo $this->form;

Categorising FlashMessenger messages in Zend Framework

What is the easiest way to categorise (warning, success, error) flash messages in Zend Framework using the FlashMessenger helper? I also want a single method to check for messages where the controller may not necessarily have forward the request on. At the moment, I believe this is done via FlashMessenger::getCurrentMessage()?
In you're controller you can do this :
$this->_helper->FlashMessenger(
array('error' => 'There was a problem with your form submission.')
);
$this->_helper->FlashMessenger(
array('notice' => 'Notice you forgot to input smth.')
);
In you're view you can echo the notice like this :
<?php echo $this->flashMessenger('notice'); ?>
And the error like this :
<?php echo $this->flashMessenger('error'); ?>
Edit:
Check this link :
... Calling the regular getMessages() method here won't work. This only returns messages which were stored in the appropriate ZendSession namespace when the FlashMessenger was instantiated. Since any messages added this request were not in the ZendSession namespace at that time (because the FlashMessenger was instantiated in order to add the messages) they won't be returned by getMessages().
For just this use-case, the FlashMessenger also provides a getCurrentMessages() method (and a related family of current methods) which returns those messages set on the current request.
Okay, thanks for everyone's input I have however implemented a different approach.
I already had a parent controller that extends Zend_Controller_Action where I've placed common logic across the application, so in the postDispatch() method I merged the getCurrentMessages and getMessages into a view variable.
public function postDispatch()
{
$messages = array_merge(
$this->_helper->flashMessenger->getCurrentMessages(),
$this->_helper->flashMessenger->getMessages()
);
$this->view->messages = count($messages) > 0 ? $messages[0] : array();
}
I set the message via a controller action like;
$this->_helper->flashMessenger(array('error'=>'This is an error'));
And in my layout file, I use a conditional on the $messages variable;
<?php if(count($this->messages) > 0) : ?>
//.. my HTML e.g. key($this->messages) returns 'error'
// current($this->messages) returns 'This is an error'
<?php endif; ?>
This works for me as the messages is categorised and can be obtained from the current request in addition to the next redirect.
Two ideas.
1. PHPPlaneta
Check out the source code of PHPlaneta by Robert Basic:
https://github.com/robertbasic/phpplaneta
He uses the standard FlashMessenger action helper:
$this->_helper->flashMessenger()->addMessage(array('fm-bad' => 'Error occurred')
Then defines a view helper called FlashMessenger so that he can access the messages. In his layout or view script, he simply calls:
<?php echo $this->flashMessenger(); ?>
The view helper uses the key (ex: 'fm-bad') to set up CSS styling for the output message.
2. PriorityMessenger
Check out the Priority Messenger view helper from Sean P. O. MacCath-Moran:
http://emanaton.com/code/php/zendprioritymessenger
The thing I like about this is that this whole business of saving messages for display on the next page load strikes me as something that should be completely within the view. So in your action, before your redirect, you populate the view helper with your messages and your priorities. Then, in your layout or view script, you output those messages with their priorities via the same view helper.