I am using a custom scheme in naming my files. Any pointers on how to autoload them with Zend's autoloader?
Thanks!
You can write your own autoloader class and register it with the ZF autoloader. There is a brief bit about this in the manual: http://framework.zend.com/manual/en/zend.loader.autoloader.html#zend.loader.autoloader.interface
Basically it's just a class defining one method which takes the class name as the parameter. So for you it would be something like:
class My_Autoloader implements Zend_Loader_Autoloader_Interface
{
public function autoload($class)
{
$filename = $class.'.obj.php';
require $filename;
}
}
the above assumes the classes are on the include path, if not, just stick the full path in front of $filename. Add any other mapping/checking you need in here and then register it as per the example in the manual. Normally you would do this in your bootstrap.
Related
spl_autoload_register('Think\Think::autoload');
Under namespace Think\ I created the above register function,when I try to use a class that has not been included like class Storeage,php will surposely pass Storeage as the variable to function Think\Think::autoload,but it actually passed Think\Storeage as the variable,why it adds the extra Think\ to the autoload instead of just Storeage?
Does that mean autoload will only search for classes which are declared under the same namespace where the autoload function is created?
Autoload functions generally work by including files for you on demand. So, for instance, I have a class called Spell in the namespace Write and it's in write/spell.php. So I tell my autoload function how to find the file (in this case, my directories mirror my namespacing).
The autoload function itself doesn't care about namespaces per se. It cares about finding the files that contain your class and loading them. So, to answer your question, your autoload will only restrict itself to a namespace if you write the function to do that.
Now, here's the caveat with the way you're doing it. Your autoload function is already in a namespace. That means you will have to manually include the file that contains that class or else your autoload will fail.
Here is an example for you .
loader.php
namespace bigpaulie\loader;
class Loader {
/**
* DIRECTORY_SEPARATOR constatnt is predefined in PHP
* and it's different for each OS
* Windows : \
* Linux : /
*/
public static function load($namespace){
$filename = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . ".php";
if(file_exists($filename)){
require_once $filename;
}else{
throw new \Exception("Error Processing Request", 1);
}
}
}
index.php
require_once 'path/to/loader.php';
spl_autoload_register(__NAMESPACE__ . 'bigpaulie\loader\Loader::load');
$class1 = new \demos\Class1();
// or
use bigpaulie\core\Class2;
$class2 = new Class2();
as you can see we can use whatever namespace needed we just have to make sure that the path to the class file exists .
Hope this helps!
Best regards,
Paul.
I have a autoload function that looks like so:
function __autoload_HTTP_Client($class_name) {
$HC = $class_name . '.class.php';
return require_once($HC);
}
when i call a class i use the $users = new users();
What i want to do is place my class files in folders within my class directory. So i will have
/users/users.class.php
/general/general.class.php
In my users class i want to be able to extend general.class.php
class users extends general {
}
because I want to be able to use $this-> from general so i dont want to use include. but when i do extend general it says that the class is not found since its in a different directory.
Any ideas on fixing this (I know the autoload needs to change to use directory/ $file.class.php
but how can i extend a class that is outside of the directory of the current class.
Use:
set_include_path(get_include_path().':/users:/general');
The above will then look for files within those directories, and you don't have to use a path, just filename, etc on the include/require inside the autoloader.
I'm trying to implement custom exception classes for a zend project.
I use modules and all my classes are under library.
so a filename DuplicateFileException.php which is under
APPLICATION_PATH "/../library/Abra/Exception" contains
class Abra_Exception_FileNotFoundExcpetion extends Exception {}
class Abra_Exception_MissingFileException extends Exception {}
class Abra_Exception_DuplicateFileException extends Exception {}
class Abra_Exception_FileIOException extends Exception {}
so the ErrorController works fine when i only throw Abra_Exception_DuplicateFileException
because there is indeed a file called DuplicateFileException, but the app breaks when i throw any other than that Exception.
I just can't believe that i have to create a file for each of them.
so how to work around it?
thanks for reading.
Proper zend-way would be implementing your own autoloader class. IT will implement autoload method. You can then use Zend_Autoloader autoloader stack to oad your classes. You just need to have some kind of system/logic in your classname->filename mapping.
class Abra_Autoloader
{
public function autoload($className)
{
if (strpos('Abra_Exception', $className) !== false) {
include $someFile; //faster
}
}
}
//anywhere in bootstrap (preferably in some autoloading section of yours)
// autoloader will load only classes starting with "abra"
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->setFallbackAutoloader(true);
$autoloader->pushAutoloader(array('Abra_Autoloader ', 'autoload'), 'Abra');
Please note that at least teh autoloader class should be Zend_Loader-loadable :)
The Zend autoloader works by mapping requested class names to filesystem paths so you can't make it load a file for a class where the filename does not match.
If you really want to persist down this path, I'd just include the file in your Bootstrap class, eg
protected function _initRequires()
{
require_once 'Abra/Exception/DuplicateFileException.php';
// assuming your "library" folder is on the include path
}
I have a folder in my library folder which is named after my website. The folder path is like:
~\www\library\myWebsite.com
If I'm using Zend autoloader to load the namespace of everything in the library path, will I have any trouble autoloading a class from that file with a namespace like this:
\myWebsite.com\myClass::myFunction();
I have looked online for documentation on this and I can't find any info about using periods in this way.
I tried it and the complication is in PHP. I think Zend is registering the namespace fine, because when I call \Zend_Load_Autoloader::getRegisteredNamespaces() it shows that it's registered. but when I call the static method from the fully qualified namespace, php gives an error of this:
Fatal error: Undefined constant 'myWebsite' in /home/jesse/www/application/controllers/MyController.php on line 15
It seems like PHP is terminating the namespace identifier, during parsing, at the . (period character). This is dissapointing because to me having a library named after the website was important to my design.
I will rename the directory to myWebsitecom or possibly make the .com it's own sub directory like
myWebsite\com and incorporate that into my namespace tree like: \MyNamespace\Com\MyClass::myFunction();
The easiest way to find out is to try it.
If it doesn't work, you could always write a custom autoloader to make it work. I don't have much experience with php namespaces, but the autoloader would look something like this (I imagine you'll have to tinker with it a bit to determine the correct file path given the class name):
<?php
class My_Loader_Autoloader_MyWebsite implements Zend_Loader_Autoloader_Interface {
/**
* (non-PHPdoc)
* #see Zend_Loader_Autoloader_Interface::autoload()
*/
public function autoload($class) {
if (strtolower(substr($class, 0, 9)) == 'mywebsite') {
$file = realpath(APPLICATION_PATH . '/../library/myWebsite.com/' . $class);
if ($file) {
require_once $file;
return $class;
}
}
return false;
}
}
then put this in your bootstrap:
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->pushAutoloader(new My_Loader_Autoloader_MyWebsite());
and if this class must be in that myWebsite.com directory, you could just cheat and throw in a require in there too:
require_once(APPLICATION_PATH . '/../library/myWebsite.com/Loader/Autoloader/MyWebsite.php');
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.