I'm using php and codeigniter, It has autoload class.
My first question is,
If I use autoload class to load all model will it make my application slower? Or is there no effect?
My second question :
Which one is better and faster, loading all model you need using autoload class, Or load only some models you need in a class function?
1) Autoload class will obviously make your application slower. because it uses php4 require function to load files. there are some hacks to use php 5 autoloading feature. Hope, new owner of codeigniter will add add support for autoloading.
2) It is best to use load specific models rather than autoload. in previous point I stated the reason behind this. basically it is good practice to load only the needed model, helper, library and assets. it assures that you use minimum time and memory.
I use autoload. and its working like a charm with no significant impact on loading time.
Method
Add this peace of Code on top of any libraries/models that you use in you CI autoload.php
example for me my config/autoload.php looks like
$autoload['libraries'] = array('database','door','acl','form_validation','notify');
and in libraries/Door.php i added
<?php//libraries/Door.php
function multi_auto_require($class) {
#var_dump("requesting $class");
if(stripos($class, 'CI') === FALSE && stripos($class, 'PEAR') === FALSE) {
foreach (array('objects','core') as $folder){//array of folders to look inside
if (is_file(APPPATH."{$folder}/{$class}.php")){
include_once APPPATH."{$folder}/{$class}.php";
}
}
}
}
spl_autoload_register('multi_auto_require');
class Door {
i added this snippet just above class Door{ in this way this snippet will run on every time codeigniter loads door library.
Testing and benchmarking
now For benchmarking i tested this code in a page with 17 DB queries from 8 Autoloaded Objects from 2 different folder with array of 3 folders to look in.
Result
using above mentioned method Vs include_once 'classlocation.php' for all project classes,
the average of 10 page refreshs for both methods where around 0.6sec;
so you can see there is no significant difference between both methods.
yet although i didn't test it on pages that doesn't use all class's, yet im sure autoloading makes my CI life much better and i'm happy with it.
Related
I'm building a website and are getting more and more classes to load. Currently I'm including every class in index.php and I also have a ajax handler where every class is included, so I basically include all my PHP files at ajax calls and on every page on the website.
Is this bad practice?
I've tried searching a bit around an have seen that there is a function called spl_autoload_register. By reading a little about it, my understanding is that it tries to include the files defined if a class is not found. But, how is that different from require_once or include_once.
Lets say I have the class underneath in a file and then use require_once('myclass.php');
class Myclass {
function myMethod {
//some code here
}
}
But, the class is not in use before I initialize it with $class = new Myclass; So what is now the difference from running
function my_autoloader($class) {
require_once('classes/' . $class . '.php');
}
spl_autoload_register('my_autoloader');
I would still have to initialize it with $class = new Myclass; when I want to use it. Are there some performance gains from either of them or is it more a preference thing?
And one more question. Should PHP be minifyed like its done with JS and CSS or is this pointless with PHP?
In 2018 the best way to work with autoloading is Composer - build for easy work and performance optimization.
4. Steps to Load Your Classes Fast and Clean
Download composer (for start even right to your project, it's up to you)
Create composer.json and tell him directories or files to load classes from:
{
"autoload": {
"classmap": "/src"
}
}
Using most open and friendly classmap option.
Rebuild cache by CLI command:
composer.phar dump
Include it in index.php
require_once __DIR__ . '/vendor/autoload.php';
And you're ready to go!
The code will technically run faster if you don't load every file on every page, but this will largely go away if you configure "OpCache", which loads all the compiled class definitions into shared memory. And at some point, you may end up with a page that needs 90% of your code loaded to do its job anyway. (This is also relevant to your question about minification - PHP is compiled on the server, so minification doesn't really help anyone.)
The other advantage with autoloading though is maintenance - when you define a new class, you don't have to add it to some master-list of includes, make sure it loads after its parent class but before its child classes, etc. Instead, you place the class definition in a meaningfully named file and directory (great for humans finding it too!) and the autoloader will find it when it's needed.
I did extensive measurements on TYPO3 (PHP) including hundreds of class files on a machine with SSD. I created a script including all available classes. Class reading was not a very expensive part compared to other issues.
I would focus on this optimisation, once all more important questions are addressed.
In my autoload file I have several common libraries and several common model autoloaded:
$autoload['libraries'] = array('database','session','tools','common'....);
$autoload['model'] = array('mauth','madmin',...);
I'm in calling this code inside a library that calls another library:
class library1{
function x(){
$this->CI =& get_instance();
$this->CI->library2->y();
}
}
class library2()
function y(){
$this->CI =& get_instance();
$array_notifications = $this->CI->madmin->getNotifications();
}
}
And I get:
Message: Undefined property: Splash::$madmin
I guess I may do this:
$this->CI->load->model('madmin');
But.. why? Why Can't I decide the load priority of my autoloaded classes?
Thanks
EDIT: Clarification
AFAIK there's no possibility of choosing the loading priority, and I think that hacking the core just to avoid writing a line is a bit...off.
I had to go search the core system to see better how things work. Looks like libraries are autoloaded before models, so you are right when saying that you need to load the model before calling one of its methods (I didn't tested though, but I think it works like this).
I don't know why is this done, but so far the only solution I see is to change yourself the order in which are loaded, but I warn you: I think that if things work this way there's a reason the CI developers has thought about; this might have drawbacks you cannot tell, so always be ready to a drawback in case you find problems.
This solution is just a bit speculative and not guaranteed, I'll appreciate your feedback as I cannot set up a testing environment right now to prove it
Go to the system/core/loader.php file, around line 1166 (the method is _ci_autoloader()) where the "libraries" index of $autoload array is checked, and swap its position with the 'model' index checking which is around line 1183.
And good luck :)
I personally think you should avoid autoloading as much as possible, since all resources will remain loaded whether you use them or not, as said here.
Also, be aware that Model autoloading works somewhat differently than autoloading for other objects.
When working with models, CI assumes that any loaded library is also available within the model. So loading libraries before models is actually the right thing to do.
I'm building a library for our CodeIgniter app, but it requires many classes (currently I'm at 12).
Is there a best practice for packaging these many clients into one library. So I can just make one call to load it. i.e:
$this->load->library('soaplibrary');
Thanks!
As Summer points out, they have handled this situation somewhat elegantly in CI 2.0 with the concept of Drivers.
With a Driver, you actually create a subdirectory within your 'libraries' directory that contains your 'super' class, and another directory for 'child' classes. Better visual representation of the structure...
This was taken from Here.
and once you have constructed your library, here is the documentation on how to use it.
In CI 2.0, there are drivers to handle this situation. Good luck!
In CodeIgniter 3.1.9 when you load a library file, all classes in this file are included into code.
Let's say in soaplibrary.php you have
class SoapLibrary {
public function someMethod(...
class Test {
public function anotherMethod(...
In your controller you can do:
$this->load->library('soaplibrary');
//now on you can do
$this->soaplibrary->someMethod();
//but also
$test = new Test();
$test->anotherMethod();
CodeIgniter attempts to call the constructor of class SoapLibrary, hence a class with that name must be in there.
In Codeigniter, when we use $this->load('class_name') in the controller, CI will try to create an instance of the class/model using its constructor.
But sometimes, I don't actually need an instance from that class, I just want to call some static functions from it. Also, there is a big limitation with $this->load('class_name'), it does not allow me to pass parameters to the constructor (unless we extend or modify the core class of CI).
I think the $this->load('class_name') function should only do a require_once on the class php file for me, and let me freely do things (create instance/call static functions) with the class in the controller.
Should I simply ignore this function and use require_once or writing my own __autoload function to load up the classes? This way, I just feel strange because it seems I am not writing codes inside the CI box.
You can pass parameters to your constructor. See the "Passing Parameters When Initializing Your Class" section in the user guide.
I found CodeIgniter's object creation and loading to be very limiting. I want full control over my code, and little magic in the background. I have instead started using Doctrine's Class Loader. It's very lightweight and is essentially SPL autoloading (also a good alternative). You don't need the whole Doctrine shebang with ORM and all that stuff, just the ClassLoader. There's some configuration tinkering to get this right, but it works wonders.
With PHP 5.3 I now have namespaced classes in the Application directory. For instance I created a new class in the Tests directory: Application\Tests\SomeTest.php
That test could look something like this:
namespace Tests;
class SomeTest {
...
}
I would use this class in my code (controllers, views, helpers) by simply using the fully qualified namespace (i.e. $test = new \Tests\SomeTest) or a "use" statement at the top of my code (use \Tests\SomeTest as SomeTest).
In this way I intend to replace all libraries and models with OO namespaced variants. There are many benefits to this: fast autoloading with SPL, full IDE intellisense support for classes/methods (CodeIgniter is really bad for that), your code is more portable to other frameworks or projects.
That said, I still use a lot of the CodeIgniter engine. This basically means I have $CI =& get_instance() in most of my classes. It's still a work in progress and I think the main reason I need CI is for it's database access. If I can factor that out ... and use something like Dependency Injection, then I won't need CodeIgniter in my classes at all. I will simply be using it for it's MVC framework, and using it's methods occasionally in my controllers.
I know this goes above and beyond your question, but hopefully it's some food for though - and it helps me to get it in writing too.
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.