Please See Correct Answer for solution to the requested question.
Hi,
Recently I have been searching for telephone validation in zend framework which I think is a missing component of their Validator framework. Therefore I created custom telephone validator which I would like to share with you.
Put code below in a file accessible by require_once php statement. Here we suppose that this code is pasted in file telephoneValidator.php.
class Custom_Validator_Telephone extends Zend_Validate_Abstract
{
const INVALID = 'This field is required';
protected $_messageTemplates = array(
self::INVALID => "Incorrect telephone number"
);
public function __construct()
{
}
public function isValid($value)
{
if(preg_match("/^(\+)?(\([0-9]+\)\-?\s?)*([0-9]+\-[0-9]+)*([0-9]+)*$/", trim($value)))
{
return true;
}
else
{
$this->_error(self::INVALID);
return false;
}
}
}
How to Use it: Put $tel Zend_Element below in your Zend_Form object with addElement method
require_once("telephoneValidator.php")
$tel = new Zend_Form_Element_Text($fieldName);
$telValidator = new Custom_Validator_Telephone();
$tel->addValidator($telValidator, true)
->setAllowEmpty(false)
->addValidator('NotEmpty', true, array('messages' => array(
'isEmpty' => $label.' is required')))
->setLabel("Telephone Number");
$form->addElement($tel);
Error message from this validator can be modified using setMessage method of Zend_Validate_Abstract class
$telValidator->setMessage("%value% is not correct telephone number");
$tel->addValidator($telValidator, true)
This validator is working fine with phone numbers in following format
+(92) 345-5141637
+(92)-345-5141637
(92) 345-5141637
(92)-345-5141637
+(92)-345-5141637
92-345-5141637
+92-345-5141637
+923455141637
923455141637
(92)-(345)-5141637
I have'nt put length check yet on phone number but it will require to create a filter for filtering digits from the input telephone phone number then using StringLength
validator.
Although I am new in Zend framework, I would like to know that how can I automatically include my classes in custom folders inside application folder using autoloader of Zend framework. For example I have my custom classes in MajorClasses folder inside application folder, please tell me the way to automatically include all the classes inside my MajorClasses folder just be specifying its name because there can be many files inside that folder but I want them to be included automatically. Is this possible in Zend framework?
Why did you post your full telphone stuff? Your question is just how do you enable autoload of custom files in Zend? Right?
In Zend 1.10.7 you can add the following to public/index.php ABOVE your bootstrap->run command
require_once "Zend/Loader/Autoloader.php";
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('Custom');
You can register as many custom namespaces as you like. In this case Custom is a new namespace thus your classes should be named as follows.
class Custom_Validator_Telephone extends Zend_Validate_Abstract
Now about your directory structure, first question your MajorClasses folder is inside application/??? if so ok, in the same file, as above, there should be a set_include_path() function being run. Within it your setting your library path, now we can add the path to your new directory.
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
get_include_path(),
APPLICATION_PATH.'/MajorClasses'.PATH_SEPARATOR,
)));
WITHIN MajorClasses folder you will NOW have to create a directory FOR EACH namespace. So if you have the namespace Custom, you create the directory, also you have to create the Validator directory since you're naming it like that, so your path would be.
application/MajorClasses/Custom/Validator/Telephone.php
Telephone.php should be the name of your class file, the class filename is always the last namespace in the classname.
Did I miss anything?
This question comes under Zend Resource auotloading http://framework.zend.com/manual/en/zend.loader.autoloader-resource.html
In short, in order to include all files under particular folder we need to follow following rules.
1) Suppose all files under MajorClasses folder are started by Custom i.e. class Custom_validator_Telephone, so our namespace for this folder is Custom. In order to include files under this folder we need to create an instance of zend resource autoloader
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => "/path/to/MajorClasses",
'namespace' => 'Custom'
));
2) Now we have our resource autoloader ready, we need to add resources to this object for example if I have folder with name validators inside MajorClasses folder and all files inside of this folder are prefixed by Custom_Validator then namespace of this folder is Validator because we have already defined Custom as prefix of the parent resource object.
$resourceLoader->addResourceType('validator', 'validators/', 'Validator');
Here
1st parameter says about name of resource we are adding and is used for internal recognition.
2nd parameter defines path of the folder relative to the base Path we declared when instantiating resource autoloader object, so path of this resource is /path/to/MajorClasses/validators/.
3rd parameter specifies namespace of the class i.e. it will be concatenated by the resource object's namespace(in our case it is Custom) so prefix of complete class upto this point is Custom_Validator and php file inside this folder will be postfixed with this class name after stripping .php file extension
3) Now we can put Telephone.php inside validators folder and if we place above code in bootstrap's any function for e.g. _initPlaceHolders then we can create instance of Custom_Validator_Telephone anywhere in our application without need of using require_once statement.
$telValidator = new Custom_Validator_Telephone();
Related
A PHP 7.1 application uses composer's autoloader to find class definitions. The namespace mappings are defined in a composer.json file.
The application also uses ICU module's ResourceBundle classes to load localisable texts from *.res files. Each class with localisable texts has its own set of *.res files (one file per language). The code providing the localisation supports gets a fully qualified name of the class whose texts it should load.
I would like to have the *.res files located next to their respective class files (or in a subfolder, for example /locale/). For this I would welcome if I can somehow get the class file path without reimplementing the existing code in the composer's autoloader.
Ideally, I should be able to get the path without the need to instantiate the class and get its file location somehow.
Is this approach possible? What do you propose?
Yes, it is possible, require 'vendor/autoload.php' actually returns an autoloader instance:
/* #var $loader \Composer\Autoload\ClassLoader */
$loader = require 'vendor/autoload.php';
$class = \Monolog\Logger::class;
$loggerPath = $loader->findFile($class);
if (false === $loggerPath) {
throw new \RuntimeException("Cannot find file for class '$class'");
}
$realLoggerPath = realpath($loggerPath);
if (false === $realLoggerPath) {
throw new \RuntimeException("File '$loggerPath' found for class '$class' does not exists");
}
var_dump($realLoggerPath);
Outputs:
string(64) "/home/user/src/app/vendor/monolog/monolog/src/Monolog/Logger.php"
I created a new directory at root 'components'. Then I put a file 'ClassName.php' into this folder. Declare a namespace namespace components; and the class named ClassName Now I try to use it like
$c = new app\components\ClassName()
But there's an error. It says that Class 'components\ClassName' not found.
Where am I missing? I suppose that I should add folder components in include_path or something like that. Please help to understand.
I found the solution.
Just add
Yii::setAlias('components', dirname(dirname(\__DIR__)) . '/components');
In className.php:
namespace components;
Then usage:
$c = new components\ClassName();
This is how you can create custom components in Yii2 (basic application)
Create a folder named "components" in the root of your application.
Then create a class for your component with proper namespace and extend Component class:
namespace app\components;
use yii\base\Component;
class MyComponent extends Component {
public function testMethod() {
return 'test...';
}
}
Add component inside the config/web.php file:
'components' => [
// ...
'mycomponent' => [
'class' => 'app\components\MyComponent'
]
]
Now you can access your component like this:
Yii::$app->mycomponent->testMethod();
In ClassName.php:
namespace app\components;
Added
When you create new ClassName instance, don't forget the leading backward slash for namespace (AKA fully qualified namespace), if your current namespace is not global, because in that case namespace will be treated as relative (Like UNIX paths), use:
$c = new \app\components\ClassName(); //If your current namespace is app\controllers or app\models etc.
$c = new app\components\ClassName(); //If your current namespace is global namespace
You can read more about namespaces basics in PHP documentation
It should be late but I guest my solution may help some one later. I had the same issue and the resolved it the way bellow:
If you want to autoload (import) a customer class in your app, you to do:
create your class where ever you want e.g in my case, i created common/core/Utilities.php
then you have to create an alias (alias is a short cut name you give to your folder path). In my case in create an alias for my folder core (note i should also create an alias for my component folder) e.g
Yii::setAlias('core', dirname(DIR).'/core');
this snippet i put it in my common/config/boostrap.php file. because yii2 load this file at running time.
Now you are ready to use your customize class where ever you want. Just do
$utilities = new \core\Utilities();
Hopefully this may !!!!!!!
I have a directory structure such that I have three directories inside my root directory, namely application, public and library.
Now, inside the library directory, I made a directory Custom, inside which I have a directory Controller, inside which I have a directory Action, inside which I have a directory Helper, and this directory contains a php file named 'LinkTo.php'. Inside this file, I have a class named Custom_Controller_Action_Helper_LinkTo which extends Zend_controller_Action_Helper and provides with a simple function called linkTo($inputString)..which outputs the url as per the input string parameter. But, I get this error "Action Helper by name CustomControllerActionHelperLinkTo not found " even though I have mentioned 'Custom_' in autoload namespaces in my application.ini, and have also taken care of include paths in my index.php.
Please help! How does one make an action helper like that and invoke it?
Did you specify path for the custom Action Helpers ?
You can do this in your application.ini, add following line:
resources.frontController.actionHelperPaths.Custom_Controller_Action_Helper_ = "Custom/Controller/Action/Helper"
After you specified path for your custom helpers, you need to initialize them for the later use. This can be done in Bootstrap:
protected function _initHelpers()
{
Zend_Controller_Action_HelperBroker::addHelper(new Custom_Controller_Action_Helper_LinkTo());
}
If you want to use helper as a method of the helper broker, for instance:
$this->_helper->LinkTo(); your custom helper should implement direct() method.
I have a "forms" directory inside my application directory with custom form php files in there. In my application.ini the appnamespace is "Application". The form name I'm trying to use is BetaSignup.php. The class is Application_Form_BetaSignup.
In my controller I try to do $form = new Application_Form_BetaSignup, and I get an error saying:
Fatal error: Class 'Application_Form_BetaSignup' not found.
Thoughts on how to fix?
You can use the typical application/forms directory for your form classes if you name them appropriately using the configured appnamespace directive (default "Application"). Please note, the directory name is lowercase "forms".
For example, say you have a registration form "Registration". Create the file at application/forms/Registration.php (note the case sensitivity) containing the class
class Application_Form_Registration extends Zend_Form
{
// etc
The resource autoloader will be able to find your form when you instantiate it in your controllers, eg
$form = new Application_Form_Registration(); // will be auto-loaded
The ZF Docs reference 'Subclassing the Action Controller' (bottom of the page), but don't reference a standard place to put the new Action_Controller class.
Application_Module_Autoloader sets up pats for a bunch of things, but never controllers. I guess putting it on library/APPNAMESAPCE/Action/Contoller would work. But that seems a bit odd since every other application specific file is stored under application/.
The class gets autoloaded like any other class, there isn't a 'standard' place for it as such. So the question becomes, where do you want it to live?
The convention I usually follow in modular applications is to have most stuff in the modules, but register an app namespace and use application/models for 'core' type classes. So in your case, say your app namespace was Wordpress, you'd have:
class Wordpress_Controller_Action extends Zend_Controller_Action
{
}
and the file would live in application/models/Wordpress/Controller/Action.php.
To make this work you'll need application/models on your include path, and you'll want to init the standard autoloader with something like this (in your bootstrap class):
protected function _initAutoloader()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('Wordpress_');
return $autoloader;
}
alternatively you could setup the above in application.ini.