Zend Form Custom Validation Path issues - zend-framework

The issue:
Plugin by name 'Spam' was not found in
the registry; used paths:
Zend_Validate_: Zend/Validate/
I have this on my bootstrap.php file (it's NOT a class):
include_once 'config_root.php';
set_include_path ( $PATH );
require_once 'Initializer.php';
require_once "Zend/Loader.php";
require_once 'Zend/Loader/Autoloader.php';
// Set up autoload.
$loader = Zend_Loader_Autoloader::getInstance ();
$loader->setFallbackAutoloader ( true );
$loader->suppressNotFoundWarnings ( false );
//resource Loader
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH,
'namespace' => '',
));
$resourceLoader->addResourceType('validate', 'validators/', 'My_Validate_');
$loader->pushAutoloader($resourceLoader);
I've named a file called Spam.php like this:
application/validators/Spam.php
class My_Validate_Spam extends Zend_Validate_Abstract {
On the form class I have:
//HONEY POT
$this->addElement(
'text', 'honeypot', array(
'label' => 'Honeypot',
'required' => false,
'class' => 'honeypot',
'decorators' => array('ViewHelper'),
'validators' => array(
array(
'validate' => 'Spam'
)
)
)
);
With all this, I'm getting:
Plugin by name 'Spam' was not found in
the registry; used paths:
Zend_Validate_: Zend/Validate/
Why ?
Thanks a lot.

You have to add the directory where you have your custom validators to your form elements prefix path. For example:
$elementPrefixPaths =
array(
array(
array(
'prefix' => 'My_Validate_',
'path' => 'My/Validate', // 'application/validators' in your case
'type' => 'validate',
)
)
);
$form->addElementPrefixPaths($elementPrefixPaths);
// or, if your're inside the form,
// $this->addElementPrefixPaths($elementPrefixPaths)
// before any elements make use of the validator.
The 'path' should be in your include path. You have to do the same with your custom filters. Also there is a similar approach for custom decorators and elements (which use the method setPrefixPaths() instead).
Read more here.
Your path is 'application/validators', but it would be better to follow ZF convention on class naming and path mirroring; as such you should put your validator in a directory such as 'My/Validate' You should follow this convention on all custom ZF extensions you develop (filters, helpers, plugins, etc). It will make your life easier in the long run. Also, as a final suggestion, don't use "My_" as your classes prefix, use something more personal, such as "Mem_" (considering your nickname).

Related

CodeIgniter autoloading form validation rules set not working with parameters

Following CI user_guide, I have created a configuration file named "form_validation.php" with in it the following sets:
$config = array(
'user/create' => array(
array(
'field' => 'id',
'label' => '',
'rules' => ''
),
array(
'field' => 'first_name',
'label' => 'lang:First name',
'rules' => 'required|max_length[30]'
),...
),
'user/update' => array(
array(
'field' => 'id',
'label' => '',
'rules' => ''
),
array(
'field' => 'first_name',
'label' => 'lang:First name',
'rules' => 'required|max_length[30]'
),...
)
);
In my 'user' controller, when I call the 'create' method, hence with the URL http://localhost/my_ci_application/user/create, the statement $this->form_validation->run() automatically runs the first set of rules defined in my configuration file. This is the expected behaviour from what I read in the user guide.
But when I run the following URL http://localhost/my_ci_application/user/update/1 to update the user whose ID is 1, it does not automatically load the 'user/update' rules set. It seems like because of the parameter, CI expects to find a 'user/update/1' rules set, which of course I cannot create because the ID of my users will vary all the time when calling this method.
Am I understanding this right? If yes, then that's a pity as I thought standard CI URL were formed like: controller/method/parameters... so I would expect the form validation class to only consider the first two URI segments?!
FYI, if I write in my user.update method the following, my validation rules work fine:
$this->form_validation->run('user/update')
So my question is really if I understood the autoloading of rules properly or not, and if there is anything we can do to autoload those rules even with methods having some parameters.
thank you very much in advance.
In your form_validation.php file:
$CI =& get_instance();
$config = array(
'user/update/' . $CI->uri->segment(3) => array(
....
)
);
if i understant this question u will need call validation, for example:
$this->lang->load('form_validation', 'portuguese'); //if u have order language
if($this->form_validation->run('user/update') == FALSE)
{
//msg error
}
else{
//save
}
To get the value for the url dowel u need:
$this->uri->segment(3);
i hope this has helped
You can extend the library to achieve this
application/libraries/MY_Form_validation.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation {
function run($group = '')
{
if($group == '')
{
$group = '/' . implode('/', array_slice($this->CI->uri->rsegment_array(), 0, 2));
}
return parent::run($group);
}
}

Where and How to Locate this Zend Controller Plugin

I have a Zend front controller plugin. It depends on the request object, and on the service layer, but it is not reusable across applications. Therefore, I think it belongs in a Plugins directory within the application's controller directory. Does this sound right?
Secondly, how can I get Zend to autoload the plugins in this directory?
Thanks!
I would agree that plugins should go in the plugins folder. I normally setup an instance of the resource autoloader during bootstrap using my app's custom namespace. E.g. say your app's namespace was 'Bob':
protected function _initAutoloader()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$resourceAutoloader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH,
'namespace' => 'Bob',
'resourceTypes' => array(
'model' => array(
'path' => 'models/',
'namespace' => 'Model'
),
'form' => array(
'path' => 'forms/',
'namespace' => 'Form'
),
'plugin' => array(
'path' => 'plugins/',
'namespace' => 'Plugin'
),
'service' => array(
'path' => 'services/',
'namespace' => 'Service'
)
)
));
$autoloader->pushAutoloader($resourceAutoloader);
return $autoloader;
}
Add or remove resource types as required. You can then put your plugin in application/plugins/Whatever.php and it will be autoloaded as normal.

Using Zend translate in Bootstrap.php

I have several routes defined in Zend's Bootstrap.php that I want to translate with Zend's translate function:
$trans = new Zend_View_Helper_Translate();
$router->addRoute(
'myroute',
new Zend_Controller_Router_Route(':lang/'.$trans->translate('mytitle').'/',
array(
'module' => 'default',
'controller' => 'index',
'action' => 'statistics'
)
)
);
The helper itself seems to work (doesn't throw an exception or error) but always returns mytitle instead of the actual translation which is defined in the language file (I checked - the language files work in the view).
How can I get the translate function to work in the Bootstrap.php file?
Remember that you needs to load translations before you use it.
Load routing translations like:
$router->setDefaultTranslator($yourTranslator);
Best how to use routing translations is adding '#' before a word you want to translate f.e.:
$router->addRoute(
'myroute',
new Zend_Controller_Router_Route(':lang/#mytitle/',
array(
'module' => 'default',
'controller' => 'index',
'action' => 'statistics'
)
)
);

Zend: Using forms in modules

I'm trying to use forms with modules, they should be stored inside the module. So at first my filestructure:
application/
(...other directories)
modules/
group/
controllers/
IndexController.php
(...controllers)
forms/
Create.php
views/
scripts/
(...view scripts)
Bootstrap.php
Within the IndexController, I'm trying to set the Form by
new Group_Form_Create()
and the class in Create.php is of course Group_Form_Create. I get the following error message:
Fatal error: Class 'Group_Form_Create' not found in (...)\application\modules\group\controllers\IndexController.php on line 380
The Bootstrap.php with the class Group_Bootstrap is just an empty class.
Actually, I'm using the default Zend structure, but it woun't work anyway. Any ideas wheres the problems or what could be a possible solution?
In my module bootstrap (APPLICATION_PATH/modules/group/Bootstrap.php), if use the following code:
//Loads the autoloader resources
$this->_moduleName = 'group';
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH ."/modules/".$this->_moduleName."/",
'namespace' => '',
'resourceTypes' => array(
//Tells the application where to find the forms
'form' => array(
'path' => 'forms/',
'namespace' => ucfirst($this->_moduleName).'_Form_'
),
//Tells the application where to find the models
'model' => array(
'path' => 'models/',
'namespace' => ucfirst($this->_moduleName).'_Model_'
)
)
));
I then call the forms or models like this:
$frm = new Group_Form_Create();
I use the same snippet in all my modules and I only change the value of the $this->_moduleName; each time.
Hope this helps !
It sounds like your module bootstraps are not being run. These are triggered by the module resource, which is loaded if you have:
resources.modules[] = ""
in your application.ini. So add this if it is not present.
Ideally, it should work out of box.
Add this in your bootstrap:
protected function _initAutoload() {
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Group_',
'basePath' => dirname(__FILE__),
));
Zend_Loader_Autoloader::getInstance()->setFallbackAutoloader(true);
return $autoloader;
}

How to autoload extra module classess automatically like of default namespace "Application_"?

All the classes under a default namespace Application_ is autoloaded by default. When you are creating more modules, the classes under that module is not autoloaded.
I tried setting the extra module's namespace on the application.ini like
autoloaderNamespaces[] = "EXTRA_"
but since the folder structure of the extra modules lies inside the Application it cannot find it.
How to set this correctly?
You can use application resource modules
Module bootstrap(if subclass of Zend_Application_Module_Bootstrap) register autoloader on instantiation.
Following is array of resources registered with autoloader by default:
array(
'dbtable' => array(
'namespace' => 'Model_DbTable',
'path' => 'models/DbTable',
),
'mappers' => array(
'namespace' => 'Model_Mapper',
'path' => 'models/mappers',
),
'form' => array(
'namespace' => 'Form',
'path' => 'forms',
),
'model' => array(
'namespace' => 'Model',
'path' => 'models',
),
'plugin' => array(
'namespace' => 'Plugin',
'path' => 'plugins',
),
'service' => array(
'namespace' => 'Service',
'path' => 'services',
),
'viewhelper' => array(
'namespace' => 'View_Helper',
'path' => 'views/helpers',
),
'viewfilter' => array(
'namespace' => 'View_Filter',
'path' => 'views/filters',
),
)
You can add your own module resource type to autoloader from module bootstrap:
//module bootstrap for module foo
class Foo_Bootstrap extends Zend_Application_Module_Bootstrap
{
function _initMyRes()
{
$autoloader = $this->getResourceLoader();
$autoloader->addResourceType('myres', 'myres/custom/path', 'My_Res');
}
}
first parameter is a key for resource type, second is a path relative to module name, third is a resource prefix.
For example class Foo_My_Res_Bar will be autoloaded from modules/foo/myres/custom/path/Bar.php
Namespaces is for your own library classes (like the Zend_) classes. Modules are different thing and don't have namespace in that sense.
In the application.ini configuration you will have something like this
autoloaderNamespaces.My = "My_"
// these are you library classes
resources.frontController.moduleDirectory = APPLICATION_LIBRARY "/modules"
// this is your module directory
UPDATE If you need support for more than one module directory you need ZF 1.11.1 or this bugfix
In the Bootstrap class for each module, create a new module resource autloloader:
protected function _initResourceAutoloader()
{
$resourceAutoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Mymodule',
'basePath' => dirname(__FILE__),
));
}
Then, you can use the "standard" folder structure for module-specific classes. For example, a form named Mymodule_Form_Edit would reside in the file modules/mymodule/forms/Edit.php
UPDATE
As noted by #Xerkus and others, a module Bootstrap extending Zend_Application_Module_Bootstrap will automatically register some standard namespace/path mappings, so no need to manually instantiate a Zend_Application_Module_Autoloader.