Zend Framework: How to pass variables to a custom form element's view helper - zend-framework

So I've created myself a custom form element which has a custom view helper. Now I want to be able to set certain parameters/variables on this form element and be able to access them in my element's view helper. How can I do that?
Here's an example of what I am talking about:
adding the element to the form:
$element = new My_Form_Element_Picker('elementname');
$element->setFoobar('hello');
// or
$form->addElement('Picker', 'elementname', array('foobar' => 'hello'));
form element:
class My_Form_Element_Picker extends Zend_Form_Element_Xhtml
{
public $helper = 'pickerElement';
}
view helper:
class My_View_Helper_PickerElement extends Zend_View_Helper_FormElement
{
public function pickerElement($name, $value = null, $attribs = null)
{
//now I want to check if the 'foobar' option was set, otherwise use a default value
$foobar = 'default';
}
}

There is a fourth optional argument to the view helper that might do the trick for you.
if you define your view helper like this:
public function pickerElement( $name, $value=null, $attribs=null, $options=null ) { }
And then inside your actual form element you define it like this:
class My_Form_Element_Picker extends Zend_Form_Element_Xhtml {
public $helper = 'pickerElement';
public $options = array();
public function setFoobar( $foobar ) {
$this->options['foobar'] = $foobar;
}
}
You will find that the options are passed into the view helper and can be used.
This code is from memory so please forgive any mistakes, this method definitely works for me though.

Related

How to require javascript after construction but before template render in a SilveStripe form field

I currently have a custom form field with a bunch of optional parameters in the constructor. I want to change this and have the field use setter functions but I can't find any way to include my templated JavaScript except during construction
class CustomField extends FormField {
protected $myField;
public function __construct($name, $title = null, $myField = null)
{
parent::__construct($name, $title);
$this->setMyField($myField);
Requirements::javascriptTemplate('path/to/script.js', ['Field' => $this->myField]);
}
/**
* I can update the value of myField but the value is already baked into the JavaScript and wont be updated
*/
public function setMyField($value) {
$this->myField = $value;
return $this;
}
I found a solution but it does feel a little hacky. I added a RequireJs() function to the form field as such:
<?php
function RequireJs() {
Requirements::javascriptTemplate('path/to/script.js', ['Field' => $this->myField]);
}
The added $RequireJs to the top of my template file so it would be called when the template is being rendered.

ZF2 passing arguments to factories at runtime

In ZF2, I have a factory for a multicheckbox (simplified)
class MultiCheckboxFactory
{
public function __invoke(FormElementManager $formElementManager)
{
$multiCheck = new MultiCheckbox();
$serviceManager = $formElementManager->getServiceLocator();
$mapper = $serviceManager->get('Path\To\The\Mapper\SomeMapper');
$resultFromQuery = $mapper->findText('text');
// further setting up of the multicheckbox based on $resultFromQuery
return $multiCheck;
}
}
I want the multicheckbox to render different content depending on $resultFromQuery that comes from the mapper's findText() method.
I thought of passing a variable to the __invoke(FormElementManager $formElementManager, $someText). But the problem is that when I call the multicheckbox from the service manager like this:
$element = $formElementManager->get('Path\To\Factory\Alias\Multicheckbox');
I don't see how to pass an additional variable. Any help?
Have a look at MutableCreationOptionsInterface, this allows your factory to receive runtime options which you pass through the serviceManager get() method.
use Zend\ServiceManager\MutableCreationOptionsInterface;
use Zend\ServiceManager\MutableCreationOptionsTrait;
class MultiCheckboxFactory implements MutableCreationOptionsInterface
{
use MutableCreationOptionsTrait;
public function __invoke(FormElementManager $formElementManager)
{
$options = $this->getCreationOptions();
var_dump($options);
$multiCheck = new MultiCheckbox();
....
}
}
Now you can pass options:
$element = $formElementManager->get('Path\To\Factory\Alias\Multicheckbox', ['foo' => 'bar']);
Update: MutableCreationOptionsTrait is no longer available in ZF3: https://docs.zendframework.com/zend-servicemanager/migration/#miscellaneous-interfaces-traits-and-classes
The simplest way to do this now appears to be
$element = $formElementManager->build('Path\To\Factory\Alias\Multicheckbox', ['foo' => 'bar']);
though this will give you a discrete (not shared) instance every time.

How to disable some Zend View Helpers

I'm trying to make a way to disable some view helpers that are inside "application/views/helpers"...
What I really want is to put some options on the application.ini to enable or disable some Helpers.
Example on application.ini:
helpers.Helper1=on
helpers.Helper2=off
Now the problem is that when a Helper is off, I want to rewrite some functions of this helper in order to return a different result on the view. In this way, I don't need to change anything in the view script.
I thought in having 2 different php files for each helper, in different locations. One with the real helper and another with the changed helper (to work when it is off on the application.ini).
The problem is that I don't know how to tell the view which one it shoul load...
Does anyone know how it could be done?
FINAL CODE
Ok, after many tries, I put it to work with the following code:
Bootstrap
protected function _initConfigureHelpers(){
$this->bootstrap('view');
$view = $this->getResource('view');
$view->addHelperPath("./../library/ConfigHelpers","Configurable_Helper");
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
'ViewRenderer'
);
$viewRenderer->setView($view);
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Application_Plugin_ViewPlugins());
return $view;
}
Application_Plugin_ViewPlugins
class Application_Plugin_ViewPlugins extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request){
$front=Zend_Controller_Front::getInstance();
$bootstrap=$front->getParam('bootstrap');
$options=$bootstrap->getOption("helpers");
if (is_array($options)){
$view = $bootstrap->getResource('view');
foreach($options as $option => $value){
$helper=$view->getHelper($option);
if ($helper){
if ($value=="off")
$helper->__disable();
else if ($value!="on")
throw new Exception('The value of helpers.'.$option.' must be "on" or "off" on application.ini.');
} else {
throw new Exception("Inexistent Helper");
}
}
}
}
}
Modified helper example
require_once APPLICATION_HELPERS."CssCrush.php";
class Configurable_Helper_CssCrush extends Zend_View_Helper_CssCrush {
protected $__config_enabled = true;
public function __disable(){
$this->__config_enabled = false;
return $this;
}
public function __enable(){
$this->__config_enabled = true;
return $this;
}
public function cssCrush(){
if ($this->__config_enabled){
return parent::cssCrush();
} else{
return new Modified_CssCrush();
}
}
}
class Modified_CssCrush {
public static function file ( $file, $options = null ) {
return $file;
}
}
APPLICATION_HELPERS is defined on /public/index.php as "../application/views/helpers/".
Now, when I want to add a configurable helper, I put the original helper on "/application/views/helpers/" and then, create a modified version of it on "/library/ConfigHelpers" with the structure of the example above.
What I think you want is Dependency Injection which is coming in zf2, but not available in zf1.
With some tinkering though you can get what you need.
Configuring helpers in the bootstrap
(assumes default project structure)
View helpers paths config : application/configs/application.ini:
resources.view.helperPath.Zf_View_Helper_ = "Zf/View/Helper"
A simple configurable helper, (allows disable/enable but you can obviously add any methods you need (use this as base class for helpers that need the behaviour)
class Zf_View_Helper_Configurable extends Zend_View_Helper_Abstract
{
protected $isEnabled = true;
public function configurable()
{
return $this;
}
public function disable()
{
$this->isEnabled = false;
return $this;
}
public function enable()
{
$this->isEnabled = true;
return $this;
}
public function __toString()
{
if ($this->isEnabled) {
return 'Configurable is enabled';
} else {
return 'Configurable is disabled';
}
}
}
And configure the helpers in the bootstrap:
public function _initConfigureHelpers()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$configurableHelper = $view->configurable();
$configurableHelper->disable();
}
You can add options in the .ini file and grab them in the bootstrap initConfigureHelpers() method.
If you want this behaviour from any default zf helper, do what #Ratzo said and extend those helpers and add the required behaviour and then configure them in your bootstrap.
Please take a look at the following link Zend_View link
Below is an important points you should consider from the Zend docs.
Note: Default Helper Path
The default helper path always points to the Zend Framework view
helpers, i.e., 'Zend/View/Helper/'. Even if you call setHelperPath()
to overwrite the existing paths, this path will be set to ensure the
default helpers work.
This means that you can't really turn off the helpers, unless you want to go about extending the Zend_View object and overwrite the setHelperPath method. This is not the way to go though.
Here is probably what you want to do. First though, here is my assumption.
Assumption : You want to write your own view helper that slightly alters what the current view helpers do by changing a few methods here or there.
Here is what you should do to accomplish that.
First, write your view helper. Make sure the last part of the class name is the same as the view helper you want to 'overwrite'. You don't have to, but this makes sure the original helper can't be used anymore.
class My_View_Helper_BaseUrl extends Zend_View_Helper_BaseUrl
{
private $_enabled = true;
public function setEnabled( $bool ){ $this->_enabled = (boolean) $bool; }
public function baseUrl(){
if( $this->_enabled ){
return 'testUrl'; //other code
}
else return parent::baseUrl();
}
Now that you have that, do the following
$view->setHelperPath('/path/to/my/helpers', 'My_View_Helper'); //1
echo $view->baseUrl(); //2
Excellent. Now you've effectively shadowed the original BaseUrl helper.
The above code will make it so that the view scans your directory
for any helpers before scanning the default zend directory. When it gets to line
2 the view will find YOUR baseUrl helper first and use THAT instead of the
original baseUrl helper. In the above example it should echo
'testurl' instead of the normal baseUrl behavior.
You can make a custom helper that extends the original helper, for example
class My_Helper_Url extends Zend_View_Helper_Url
{}
and rewrite the methods as you need.

ZendFramework Noob: Adding text on top of a form

I've just (as in today) started working on some ZF stuff.
I have a Form that needs to have some text in a div appear at the top of the form, but I have no idea how to include it.
The structure of the form is:
class MyForm extends \app\forms\FormType {
public function init() {
// gets all the form elements of the parent
parent::init();
// A few additional form elements for MyForm created here
}
}
Any help would be apprecaited!
In your controller where you instantiate the form object just set it with the view object like this:
public function actionNameAction()
{
// ...
if (/* some condition to check form page */) {
$this->view->divText = 'your text';
}
}
Then put the div in the action-name.phtml script:
views/scripts/controller/action-name.phtml
Contents:
<?php if (!empty($this->divText)): ?>
<div><?php echo $this->divText; ?></div>
<?php endif; ?>
Additionally, you could pass the view object by reference to your form class. Just overload the construct function like so:
public function __construct($options = null, &$view)
{
parent::__construct($options);
$this->view = $view;
}
Then in your controller when you instantiate your form object do this:
$form = new MyForm(null, $this->view);
Let's go back to your form class once again and modify the init() method:
public function init()
{
// ...
$this->view->divText = 'Text set from within ' . __CLASS__;
}
Using this way, you won't have to put any conditional if statements checking anything in the controller. You're already checking if $this->divText is not empty in the view, so by passing the view object to your form class you can ensure that that text will only be set when the form is being used.

zend-framework, call an action helper from within another action helper

i am writing an action helper and i need to call another action helper from within that helper. but i dont know how. here in the sample code:
class Common_Controller_Action_Helper_SAMPLE extends Zend_Controller_Action_Helper_Abstract
{
protected $_view;
public function __construct(Zend_View_Interface $view = null, array $options = array())
{
$this->_view = $view;
}
public function preDispatch()
{
$flashMessenger = $this->_helper->FlashMessenger; // IT IS NULL
}
}
Use the action helper broker:
$flashMessenger =
Zend_Controller_Action_HelperBroker::getStaticHelper('FlashMessenger');
You can also use getActionController to get a reference back to the actioncontroller you were using for any methods you'd normally use there.
In addition to mercator's answer, add your method after, see example below:
Zend_Controller_Action_HelperBroker::getStaticHelper('FlashMessenger')->myMethod();
You can call it in this way:
$this->_actionController->OtherActionHelper();
The _actionController property references the actual action controller.