I'm using an autoload for my classes such as:
function my_autoloader($Class){
// classes
include "class/Class_User.php";
// helpers
include "helper/Url_Helper.php";
}
spl_autoload_register('my_autoloader');
All is working great however I have some question. The content of Url_Helper is not a class, there are just a classic php functions I use across the site. The functions in Url_Helper are accessible only AFTER I initiate some (any) class like: $User = new User();
After this the functions get loaded. But if I call a function from Url_Helper and do not use any class at all it doesn't get loaded.
Can you explain me a little bit what's going on in here?
You already debugged it. You say when you load no class, the helpers don't get loaded; this is true. If you want your helpers always to be available, you should include them outside of your autoload function.
Related
I'm looking for __autoload magic method inside the YiiBase class, but it isn't. In the official docs said that public static function autoload($className) is
Class autoload loader. This method is provided to be invoked within an
__autoload() magic method.
I'm confused. What class of yii framework contains __autoload magic method? Is it possible to get an example with a component class autoloading?
Yii uses the spl_autoload_register function to set the autoloader function. The spl_autoload_register was introduced in PHP 5.1.2 and makes it possible for us to register multiple autoload functions. It effectively creates a queue of autoload functions, and runs through each of them in the order they are defined. By contrast, __autoload() may only be defined once. In Yii you can find this in YiiBase.php, just after the definition of the YiiBase class, at the very end of the file:
spl_autoload_register(array('YiiBase','autoload'));
Where autoload is a static method definied in the YiiBase class.
Using spl_autoload_register instead of the __autoload() magic function is good for us, because this way Yii's autoloader does not conflict with our own or with another thrid-party's autoloader. The YiiBase class also defines a registerAutoloader function to register another autoloader function before or after Yii's autoloader in the chain. If you take a look at its code, it is pretty straightforward what it does:
public static function registerAutoloader($callback, $append=false)
{
if($append)
{
self::$enableIncludePath=false;
spl_autoload_register($callback);
}
else
{
spl_autoload_unregister(array('YiiBase','autoload'));
spl_autoload_register($callback);
spl_autoload_register(array('YiiBase','autoload'));
}
}
It really just uses spl_autoload_register and/or spl_autoload_unregister (yes, you can also unregister an autoload function!), to put the new autoloader before or after Yii's autoloader, because spl_autoload_register always registers the new autoloader at the end of the chain.
I think that Yii tries to autoload a class whenever you reference it. Yii is simply making use of PHP's __autoload() function. It's a magic method like __get() or __set().
For example, when you write $foo = new Foo(); and class Foo has not been loaded yet, you will get an Error.
But you can prevent that if you define an __autoload($classname) function before. This way, instead of throwing an Error, PHP will first try to run the __autoload($classname) function. In that function, you can do things like: include the variable $classname and so on.
There's more information here: http://www.php.net/manual/en/function.autoload.php
I am wondering is it possible to auto load static class, as like creating object to dynamically autoload library ?
I have done most of the part of php autoloader but really need to tips to autoload static libraries for which I don't want to create object.
Is there anyone have solution ? Please post or else give me best idea to develop the same.
Thanks
Yes SPL Autoloader will load classes and interfaces. Once the autoloader is triggered you can use any reference to an auto-loadable asset to trigger the load
My_Special_Class::SOME_CONSTANT
will trigger a load as well as calling or referencing any visible static method or property.
In fact exploiting this is one way to trigger the auto_loading of namespaced functions. Define a class file like this.
namespace My\Namespace;
abstract class Functions{
const LOADED = true;
}
function func1(){}
function func2(){}
function func3(){}
And in your code when you need the functions defined in My\Namespace simply
if (\My\Namespace\Functions::LOADED){
func1();
func3();
}
The reference to the abstract class triggers the autoloader to include the file that defines the functions.
My whole project is basically divided into two parts:
core
helper classes
User creates his custom classes and uses methods from helper classes in there like:
\Project\System\Helpers\Class::foo();
So every public method in each helper class is declared as static. I've came up with an idea to change this, make all user custom classes inherit one special class:
class SingleBeingInheritedClass {
public function helper($class)
{
return new \Project\System\Helpers\$class; // it's just to show the idea
}
}
so that instead of calling static function, user could write:
$this->helper('class')->foo();
The problem is I use some of these helper classes inside a couple of core classes. And I don't want core classes to inherit anything related to helpers.
In these core classes I also don't want to make the code longer and initialize objects in every method using these helpers.
How should I handle this? Or maybe static methods aren't that bad here?
You wrote:
I also don't want to make the code longer and initialize objects in
every method using these helpers.
I you would like to avoid instantiating objects, then you shall stick to static methods. In my projects I use static methods for helpers, for the exact same reason.
These helper classes are then used as 'function libraries'. In this case, class is more like a namespace for the helper functions, not something which gets instantiated.
When you manually include a PHP class you can do it while the current script is running, right? Then you can decide, if a condition matches you load it and if it doesn't you don't. Like this:
if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
include '../../../Whatever/SanitizeUserInput.class.php';
SanitizeUserInput::sanitize($_POST['someFieldName']);
}
But let's say I use the autoload feature with this class. Will it be effectively loaded at the beginning or will it be loaded only if it's used?
I mean, should I add the __autoload function only in classes that I'm 100% sure I'm going to use in any script (e.g. database connection, session management, etc.)?
Thanks
Autoload is called only when you are trying to access desired class. And it would be better to use spl_autoload_register() instead of __autoload
Documentation:
You may define an __autoload() function which is automatically called
in case you are trying to use a class/interface which hasn't been
defined yet.
and
spl_autoload_register() provides a more flexible alternative for
autoloading classes. For this reason, using __autoload() is
discouraged and may be deprecated or removed in the future.
Autoloading kicks in when you are trying to use a class that has not yet been loaded:
include 'foo.php';
new Foo; // autoload not used, because the class already exists
// Bar is not yet loaded here, auto or otherwise
new Bar; // Bar is being autoloaded, because it was not yet loaded
As such, autoloading can be very efficient. It's slightly less efficient than loading classes by hand at the time when you need them, because of the overhead of invoking the autoload function. But keeping track of loaded classes by hand is more work for very little return over autoload.
Try it out, you will see, that whenever PHP stumbles over a class it doesn't know yet, it will call your autoload function. When your autoload function tells PHP in which file the class is, it will load this file.
To make the answer short, PHP only loads the file when needed, that is true even for conditions, so following test class will never be loaded.
if (false)
{
$test = new CTest(); // never loaded with autoload.
}
Just starting to use CodeIgniter, and I'd like to import some of my old classes for use in a new project. However, I don't want to modify them too much to fit into the CI way of doing things, and I'd like to be able to continue to use NetBeans' autocomplete functionality, which doesn't work too well with CI.
So, what is the best way to load custom classes & class files into CodeIgniter without having to use the library/model loading mechanisms?
I apologise if this is something I should be able to find quickly, but I can't seem to find what I'm after. Everything I see is just telling me how to go through CI.
To do it codeigniter way, place your custom classes in libraries folder of codeigniter. And then use it by adding that class as library in your controller like this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Someclass {
public function some_function()
{
}
}
/* End of file Someclass.php */
using in controller:
$this->load->library('someclass');
checkout complete article at http://www.codeigniter.com/user_guide/general/creating_libraries.html
Libraries are easy to write but they have a few restrictions. Constructors can only take an array as a parameter and it's assumed that only one class will exist per file.
You can include any of your own classes to work with them however you want, as this is only PHP ofc :)
include APPPATH . 'classes/foo.php';
$foo = new Foo;
Or set up an __autoload() function in your config.php (best place for it to be) and you can have access to your classes without having to include them.
I'd say you at least write a wrapper class that could require the classes and instantiate the objects and make them accessible. Then you could probably autoload such library and use it as needed.
I would recommend that you at least tried to have them fit in the CI way, as moving forward this will make you life much more easy. I've been in kind of the same position and learned just this along the way.
require_once(PHYSICAL_BASE_URL . 'system/application/controllers/abc.php');
$report= new abc();
Next use the function detail in abc contoller:
$mark=$report->detail($user);
If you're just starting to use CodeIgniter, maybe you ought to check Kohana (http://kohanaframework.org/). It is very similar to CodeIgniter in many ways but it loads classes in the normal way (using new ClassName()) so Netbeans' autocompletion features should works normally.