I am trying to build my own simple MVC framework, mainly for educational purposes than anything else, I have used CodeIgniter in the past which has provided most of the inspiration for the features I would like to incorporate into my framework.
I would like to build a loader class like CodeIgniters, but I can't understand how CI loads the classes as if they are properties of the calling class i.e
class Random_Controller{
function __construct(){
$this->load->helper('some_class');
$this->some_class->do_something();
/*
How does CI load some_class as if it were a property of Random_Controller?
I can understand using something like $$class_name = new $class_name();
Or $$this->class_name = new $class_name();
But how can the dynamically named object be used with $this->?
*/
}
}
Hopefully that makes sense...
I am always surprised at how simple things appear with the right explanation. One more question though.
If $load is a reference to an instance of load class, and a record of all loaded classes is kept in an array, we are essentially doing:
$this->loaded_classes[$key]->do_something()?
So how does CI resolve the array to a variable name? I have seen some PHP magic methods that are called when variables do not exist or methods do not exist, would this be done in conjuction with these magic methods? In other words if the $this->some_class property does not exist we search for an element in the array with that key?
If that makes sense..
Uhm, well, let's start with this: the CI_Controller super class; it's the one all controllers extends, and acts as the CI superobject all the $this refer to.
CI_Controller acts as a singleton, and during initializing it calls a function, load_class() (you can find in core/common.php) which works as an autoloader : inside a static array ($_classes) it assignes as index the class name, and as value the class instance:
$_classes[$class] = new $name();
Then the companion is_loaded() function (in the same file) registers in an array all the function loaded, and is used to check later if the class has already been instantiated or not.
Ci_Controller assigns then to its $load property an instance of the Loader class (core/loader.php, by using the above mechanism)
$this->load =& load_class('Loader', 'core');
which, in turn, is responsibile for loading all other resources using its own methods: helper(),library(),model() and so on. Have a look at the source for all details, hope you got the picture though
To clarify as per your comment:
$load = new Loader();
$load->helper('helper');
would be the same as:
$this->load->helper('helper'),
as $this->load contains an instance (by reference) of the Loader class.
Then how the helper(),library(),etc methods of the Loader class work would be too much to write here, and beside you can open up the Loader.php file and have a look by yourself.
Related
I am working on an MVC framework in PHP.
I have several controller classes called "index" with methods called "index" within them. The classes do not have __construct() methods.
Inevitably, this is resulting in PHP calling the "index" method as the constructor instead, using the old PHP4 convention of the constructor being the method with the same name as the class.
Is there any way to disable this behaviour or do I have to define an empty __construct() to prevent it? (Or just change my own coding style so I don't have methods with the same name as their classes.)
I want PHP5 to stop parsing for the PHP4 constructors essentially.
Ilmiont
I have been down the same road with MVC frameworks before and I have never heard of an index() function being called like this. Upon instanciation it will call the __constructor if present or do nothing. When calling your controller you should be geting the class and method name and checking if they exist and if they do then instantiate it. However if you have the same general setup as me you should have a registry storing all of your variables being passed to the controller when you create an instance, then when/if the view is called from index it should pass the altered registry to the view
I want to research the source code of pyrocms, and when I read the Base.php, I can't understand the following code
new CI;
the file is system/cms/libraries/Base.php
My problems are
why there has no a variable name, like $CI = new CI;
why it can be used as CI::$APP->config->item('controller_suffix') in it's sub class MX_Controller since there does not have variable name?
Thank you very much!!!
This object isn't stored in a variable because it seems we don't need to manipulate it. On the other hand, look at its constructor: it does a lot of things (since it also calls the constructor of CI_Controller, which in turns loads a Loader and initializer it, ....)
So, we don't build it in order to manipulate it afterwards, but in order to run the code in its constructor.
We can use CI::$APP-> whatever because $APP is a static member, hence it doesn't require to have an instance of CI to be manipulated
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static cannot be accessed with an instantiated class object (though a static method can).
see statics on php.net
Ok, so I am building a web application relying on Zend PHP....
Before having to read everything to describe my nested functions, what I need is to be able to call a function from one class to another, which neither are extended upon another, are already extending a db constructor, which are all independently separate files called by one master initializing script .... (?) ... Thanks in advance, and there is a better example below as to what I mean.
My HTML Page calls a "master" include list which initializes and creates all the instances of all my classes so that all pages have common access to the functions. i.e. require('app_init.php');
Here is the most important excerpt of app_init.php:
require_once('class-general.php');
require_once('class-users.php');
require_once('class-identities.php');
$general = new General();
$users = new Users($db);
$iden = new Iden($db);
---class-general.php
$general is my basis for stupid common functions I use, as well as the DB constructor that all classes can be extended from.
----class-users.php
<?php
class Users extends General{
public function getUserID(){....random block of auth code.... return $randomID#; }
}?>
-----class-identities.php
<?php
class Iden extends General{
public function do_random_change_to_db($with_me){
....random prepared function using $with_me....
$this->logger->log("Someone with UserID: ". /*((?$this?) HERE:)*/ FIXME->getUserID() . " did something : ".$with_me ."." , Zend_Log::INFO);
$success="gucci";
return $success;
}
}?>
Right now, I am being tossed a PHP error for
Fatal error: Call to undefined method Iden::getUserID() in ...`
What would be the best way to go about this? I've tried to include one class file with the other one, but i dont exactly want to create a $FIXME= new Users(); either to save on memory space.
I also honestly would prefer to not extend any more classes off another at this time.
Thank you in advance.
If the getUserID method does not depend on any instance state (and it doesn't look like it does, though you haven't made it entirely clear), making it static will allow you to call it like so:
Users::getUserID();
If it does depend on instance state, you will need to call it on an instance of the Users class.
It seems to me that General's methods should actually be static as well, or perhaps even be free functions outside of a class. Remember: classes are used to encapsulate state. If there's no state that needs to be encapsulated, use class (static) methods or simple functions. Do not needlessly complicate your code by introducing objects and inheritance in which those paradigms don't make sense.
I'm very new to codeigniter ,
I wanted to know what is the meaning of a constructor in a controller . I saw the following code in a codeigniter tutorial -
class upload extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->helper(form);
}
// rest of the class...
My question is when is the constructor invoked - is it called every time the controller serves a request (e.g the controller class is instantiated for each request it receives?)
Well, that's a more general PHP question. Anyway, yes, the magic method __construct() is called (automatically) upon each instantiation of the class, as you can see in the manual: http://www.php.net/manual/en/language.oop5.decon.php
Usually, in CI is not necessary to call a constructor, unless you actually want one. In the example you posted, the code loads the helper on every instantiation of the class - which is the same as loading the helper in every method, just saves a lot of typing and ensures it's not forgotten. You can alternatively put the library/helper/model you want to have alywas loaded in the respective autoload array in config/autoload.php (check "autoloading" in CI's manual)
Once you define a constructor in your child Controller you're compelled to call the parent constructor (of the mail CI_Controller class), because there is where the main CI object is created and all the classes are loaded, and you need those in your child controller too; if fail to do so your child class will construct separately and won't inherit.
I hope I made myself clear, english is not my mothertongue :)
the constructor is magic Literally its called a magic method.
what makes the constructor cool is that it will do things for you BEFORE any of the methods. So if you have an admin class, and someone should be logged in in order to access it - you can check for login in the constructor and bounce them out if they are not authorized.
in the constructor you can load the models, libraries, helpers, etc that your class needs, and they will be available for any method in the class.
you can load in variables that are used by methods. this is really useful for models.
Don't use _construct() function in latest apache & codeigniter
Use helperlin in index() function
That's a general question. Constructor is a function that is automatically called when instantiated. this function helps us to intialize the things that we are going to need frequently in our code like when we have to load the models of helpers like form e.t.c.
$this->load->model('Model_name');
now when you write this line in your constructor you don't need to load this model again and again in your methods of that class.
I am new to OO concepts in PHP. I have a class called MY_ controller which is my base class. All classes extend this class. I am using MVC architecture. I am using caching in my system now. So i load the cache variable in the constructor of my base class. I use normal php variable like $cacheVariable in my function to store the value from cache. I was wondering if it would serve any help if i store it as a class parameter and use like $this->cacheVariable? In each function i get cache value like $this->cache->get('cacheVariable'); will it help if i get value from $this->cacheVariable
If you want to be able to use $cacheVariable anywhere else besides your constructor you'll want to use $this
public function __construct() {
//...
$this->cacheVariable = $this->cache->get('cacheVariable');
//...
}
Also remember, if you want your children classes to inherit this variable from your base class you will need to set it as either public or protected. If it's private children will not inherit it.
When you say "class variable" I assume you are referring to a property (property of an instance=. Note the difference:
if you have a class, say MyClassA, then in your scripts you will instantiate that class using the operator new (depending on your PHP version you can use a different constructor syntax it changed since PHP-5.3.0):
<?php
class MY_controller{
public $cacheVariable;
// constructor
function MY_controller($aValue){
// constructor code which loads cacheVariable, for example with parameter
$this->cacheVariable = $aValue;
}
public function someFunction(){
//... some code, then access the property
$cv = $this->cacheVariable;
}
}
$aController = new MY_controller(42);
?>
As you inherit from MY_controller, every instance of that class, will have access to cacheVariable through $this->cacheVariable.
The important thing I wanted to clarify is that it is an instance property, not a class one. For further reference on OOP in PHP, refer to the properties section in PHP's OOP manual and the inheritance section.
When you instantiate only one instances of your controller (derived from your main controller), its a conceivable solution.
In my opinion the better idea is getting variable directly from cache service everywhere you want in your class and don't keep it as a class property. The reason is simple: let's say value of some key from cache will be changed (or expires) in the other place than your class. If you have this value as class property you need to keeping eye on it every time you access this value but if you retrieving it from cache you just don't care (because the cache cares if value of some key doesn't changed or expired).