Rapid development of PHP applications using the CodeIgniter framework (7)
Source: Internet
Author: User
This is a gamer chapter. It tells the working principle of CodeIgniter, that is, to unveil the secret of CI '. If you are new to CI, you may want to skip it. However, sooner or later, you may want to know what is happening behind the scenes of CI. why don't you really think about it? CodeIgniter and object
This is a gamer chapter. It tells the working principle of CodeIgniter, that is, to unveil the secret of CI '. If you are new to CI, you may want to skip it. However, sooner or later, you may want to know what is happening behind the scenes of CI. why don't you really think about it?
When I first started using CodeIgniter, the object confused me. I came into contact with CI when using PHP 4. PHP4 is not a real object-oriented language. I am wandering around a lot of objects and methods, attributes and inheritance, as well as encapsulation and other data structures. it is always surrounded by similar error information "calling non-object member functions ". I saw them so frequently, so I thought of printing a T-shirt, which says: mysterious, irregular, and I seem to be wearing it at the venue of a modern art exhibition.
This chapter contains the CI method of using objects and your OO programming method. By the way, the terms 'variables/attribute' and 'Methods/functions' are idempotent. CI and PHP often mix and use them. For example, if you write a 'function' in your controller, pure OO programmers will call them 'method '. You call them class variables while pure OO programmers call them 'properties '.
Object-oriented programming
I am assuming that you have basic OOP knowledge just like me, but it may not be enough if you have tried it in PHP4. PHP 4 is not an OO language, although it has some OO features. PHP 5 is better, and its introduction has been completely rewritten as object-oriented.
However, the basic OO features of PHP4 can also be achieved, and CI tries to make you have the same behavior features, whether using PHP4 or PHP5.
It is important to remember that when the OO program runs, there will always be one or more real objects. Objects may call each other. you can read variables (attributes) and methods (functions) only when the object is in the running state ). Therefore, it is important to know and control which object is currently running. When a class is not instantiated, you cannot operate on its internal attributes and methods, except for static methods and properties.
PHP, as a mixture of procedural and OO programming, allows you to mix programming with procedural and OO programs. you can instantiate a class in a procedural code, then, use its attributes and methods to release it from the memory after it is used up. CI can work for you.
How CI 'super-object' works
CI generates a super large object: it treats your entire project as a large object.
When you enable CI, a series of complex events begin to occur. If you set your CI to generate logs, you will see records similar to the following:
1 DEBUG-2006-10-03 08:56:39 --> Config Class Initialized
2 DEBUG-2006-10-03 08:56:39 --> No URI present. Default controller
Set.
3 DEBUG-2006-10-03 08:56:39 --> Router Class Initialized
4 DEBUG-2006-10-03 08:56:39 --> Output Class Initialized
5 DEBUG-2006-10-03 08:56:39 --> Input Class Initialized
6 DEBUG-2006-10-03 08:56:39 --> Global POST and COOKIE data
Sanitized
7 DEBUG-2006-10-03 08:56:39 --> URI Class Initialized
8 DEBUG-2006-10-03 08:56:39 --> Language Class Initialized
9 DEBUG-2006-10-03 08:56:39 --> Loader Class Initialized
10 DEBUG-2006-10-03 08:56:39 --> Controller Class Initialized
11 DEBUG-2006-10-03 08:56:39 --> Helpers loaded: security
12 DEBUG-2006-10-03 08:56:40 --> Scripts loaded: errors
13 DEBUG-2006-10-03 08:56:40 --> Scripts loaded: boilerplate
14 DEBUG-2006-10-03 08:56:40 --> Helpers loaded: url
15 DEBUG-2006-10-03 08:56:40 --> Database Driver Class Initialized
16 DEBUG-2006-10-03 08:56:40 --> Model Class Initialized
At startup-each page sends a request over the Internet-CI executes the same program each time it starts. You can track records through CI files:
1. the index. php file receives a page request. The URL may indicate which controller is called. if not, the CI has a default controller (row 2nd ). index. php starts some basic checks and then calls codeigniter. php file (\ codeigniter. php ).
2. codeigniter. php file instantiation Config, Router, Input, URL (and so on) class. (lines 1st and 3-9) these called 'base' classes: you rarely directly interact with them, but everything CI does is related to them.
3. codeigniter. php testing to know which PHP version it is using. you can decide whether to call base4 or base5 (/codeigniter/base4. (or base5) php) based on the version ). create a 'Singles' instance: a class can have only one instance. No matter which one has an & get_instance () method. Note symbol: this is the symbol that references the instance. Therefore, if you call the & get_instance () method, it generates a single instance of the class. In other words, this instance is unique in the entire application and contains many other classes in the framework.
4. after the security check, codeigniter. php instantiates the requested controller, or a default controller (10th rows ). The new class is called $ CI. The specified function in the URL (or default value) is called. after the class is instantiated, it is equivalent to live and actually exists in the memory. CI will then instantiate any other classes you need and include the Library script file. Therefore, the model class is instantiated in the log. (Row 3) the 'Template file' script is also loaded (row 3). This is a file I wrote that contains standard code. It is a. php file stored in the scripts directory, but it is not a class: just a group of functions. If you are writing 'purely 'php code, you may use 'include 'or 'require' to put this file into the namespace, CI uses its own 'loaders 'function to put it into a "super object.
The concept or scope of 'namespace' is decisive here. When you declare a variable, array, object, and so on, PHP saves the variable name in the memory and allocates a memory block for their content. If you define two variables with the same name, the problem may occur. (In a complex website, it is easy to make such a mistake .) For this reason, PHP has several rules. For example:
. Each function has its own namespace or range, and the variable defined in a function is generally a local variable. They are invisible outside the function.
. You can declare the 'global' variable and place it in a special global namespace, which can be called throughout the program.
. The object has its own namespaces: the variables (attributes) in the object exist at the same time with the object and can be referenced through the object.
Therefore, $ variable, global variable, and $ this-> variable are three different things.
In particular, before OO, this could lead to various chaos: you may have too many variables in the same namespace (so that many conflicting variable names overwrite each other ), you may also find that some variables cannot be accessed at a certain location. CI provides a solution for this.
If you have already typed the following URL: www.mysite.com/index.php/welcome/index, you want to call the index function of the welcome controller.
If you want to know which classes and methods are available in the current namespace, try to insert the following 'check' code in the welcom controller:
$ Fred = get_declared_classes ();
Foreach ($ fred as $ value ){
$ Extensions = get_class_methods ($ value );
Print "class is $ value, methods are :";
Print_r ($ extensions );
}
Try to run it. it lists 270 clear classes. Most of them are PHP. The last 11 are from CI: 10 are CI basic classes (config, router, and so on .) And they are all called by my controller. The 11 classes are listed below. the list only retains the last two methods, and the others are omitted:
258: class is CI_Benchmark
259: class is CI_Hooks,
260: class is CI_Config,
261: class is CI_Router,
262: class is CI_Output,
263: class is CI_Input,
264: class is CI_URI,
265: class is CI_Language,
266: class is CI_Loader,
267: class is CI_Base,
268: class is Instance,
269: class is Controller, methods are: array ([0] => Controller [1] => _ ci_initialize [2] => _ ci_load_model [3] => _ ci_assign_to_models [4] => _ ci_autoload [5] => _ ci_assign_core [6] => _ ci_init_scaffolding [7] => _ ci_init_database [8] => _ ci_is_loaded [9] => _ ci_scaffolding [10] => CI_Base)
270: class is Welcome, methods are: Array ([0] => Welcome [1] =>
Index [2] => Controller [3] => _ ci_initialize [4] => _ ci_load_model [5] => _ ci_assign_to_models [6] => _ ci_autoload [7] => _ ci_assign_core [8] => _ ci_init_scaffolding [9] => _ ci_init_database [10] => _ ci_is_loaded [11] => _ ci_scaffolding [12] => CI_Base)
Note: Let's take a look at the content in the brackets of the Welcome class (270: the Controller I am using). it lists all the methods of the Controller class (269 ). that's why you always need to derive subclass from a controller class-because you need your new controller to keep these functions. (Similarly, your models should always inherit from the model class.) the Welcome class has two additional methods: welcome () and index (). So far, of the 270 classes, I have only written these two functions!
You may also notice the instance of the class-object. There is a variable pointing to it. Have you noticed the referenced symbol? It indicates that the CI_Input class has only one instance in the system and can be called using the class variable input:
Remember when we loaded the input file and created the original input class? It contains the following attributes:
Use_xss_clean is bool (false)
Ip_address is bool (false)
User_agent is bool (false)
Allow_get_array is bool (false)
As you can see, they have now all been included in the instance, and "design drawings" have become houses, haven't they?
All other basic CI classes (routers, output, and so on .) It is also included. You don't need to call these basic classes, but CI itself needs them to make your code work.
Reference replication
As mentioned earlier, the class variable input references the CI_Input class: (["input"] => & object (CI_Input). The difference between adding a reference symbol and adding a reference symbol is, the content of the original object remains unchanged without the reference symbol. You may be confused about this and use a simple example to describe it:
$ One = 1;
$ Two = $ one;
Echo $ two;
Show 1 because $ two is a copy of $ one. However, if you assign a value to $ one again:
$ One = 1;
$ Two = $ one;
$ One = 5;
Echo $ two;
Still show 1, because $ two has been assigned 1 before the value is assigned again to $ one, and $ one and $ two are two different variables, each allocated with a small block of memory, store their values respectively.
If $ two needs to be changed when $ one is changed, we need to use the reference. at this time, $ one and $ two actually point to the same memory block, all changed:
Code:
$ One = 1;
$ Two = & $ one;
$ One = 5;
Echo $ two;
Now show 5: We changed the variable $ one, and actually changed $ two at the same time.
Changing the symbol "=" to "= &" means "referencing '. for objects, if you want to copy an object that is not associated with the original object, use "=". if you want to use two variables to point to the same object, use "& = ", at this time, any change made to a variable will affect other variables.
Add your own code to the CI 'super object'
You can add your own code to the CI 'super object. Assume that you have written a model named Status, which has two attributes: $ one and $ two. The constructor assigns two values to them: $ one = 1 and $ two = 2. When you load this model, let's see what will happen.
The instance class has a variable called load, which is used to reference the object CI_Loader. Therefore, the code you write in your controller is:
$ This-> load-> model ($ status );
In other words, call the model method of the class variable load of the current CI "super object" to load a model. The model name is stored in the variable $ status. let's take a look at the files stored in/system/libraries/loader. php) in the model method:
Function model ($ model, $ name = ''){
If ($ model = ''){
Return;
}
$ Obj = & get_instance ();
$ Obj-> _ ci_load_model ($ model, $ name );
}
(The variable $ name in this function is an alias of the model you want to load. I don't know why I want to use an alias. maybe it will be used in other namespaces .)
As you can see, the model instance is referenced by class variables. Because get_instance () is a single instance method, you always operate on the same instance.
If you run the controller again and run our 'check' code to display the class variables, you will now see that this class instance contains two new attributes, $ two of $ one:
["Status"] => object (Status) #12 (14) {["one"] => int (1) ["two"] => int (2 )... (and so on)
In other words, CI 'super object' now includes an object named $ status, which contains the two variables we just defined and is assigned with the given values 1 and 2.
Therefore, we are gradually creating a large CI 'super object', allowing you to use some of its methods and attributes without worrying about where they come from or what namespace they are in.
This is why the CI arrow is needed. To use the method in a model, you must first load the model to your controller:
$ This-> load-> model ('Model _ name ');
This causes the model to be loaded into the instance of the current controller class, that is, $ this->. You can then call the method in the model object in the controller, as shown in the following code:
$ This-> Model_name-> function ();
That's all.
CI 'super object' problems
When Rick started to develop CI, in order to make the CI behave the same in PHP4 and PHP5, he had to use ugly code in the Base4 file. no matter whether it is ugly or not, we don't have to worry about it, as long as CI can work in the PHP4 environment as well as PHP5.
There are two other topics worth mentioning here:
. You can try to develop a non-ready-made object and get it involved in the work.
. You must carefully construct your website because you cannot call methods in a controller from another controller.
Let's analyze these two problems one by one. Do you remember the T-shirt I mentioned? When I call a member function, I always receive the error message "an attempt to call a non-object member function". This error message is generally generated because you call a class method, but I forgot to load this class. In other words, you have written the following statements:
$ This-> Model_name-> function ();
But I forgot to call it before it:
$ This-> load-> model ('Model _ name ');
There are other cases, such as loading the model in a method of the class, and then you attempt to call the member method of the model in another method, although in the same object, this does not work either. Therefore, the best method is to load the model in the class constructor and then use it in all the methods of the class.
The problem may be more serious. If you write your own class, for example, you may want to use this class to access the database or read information in your config file. In other words, allow this class to access some parts of the CI super object. (How to load your own classes and libraries will be discussed in Chapter 13th .) In summary, unless your new class is a controller, a model, or a view, it cannot be constructed in a CI super object. Therefore, you cannot write such code in your new class:
$ This-> config-> item (base_url );
This won't work, because for your new class, $ this-> means it itself, not the CI super object. Instead, you must add your new class to the CI super object by calling the Instance class with another variable name (usually $ obj:
$ Obj = & get_instance ();
Now you can call it like calling a CI super object:
$ Obj-> config-> item ('base _ url );
And this time it can work.
Therefore, when you write your new class, remember that it has its own identifier. Let's use a short example to make this question clearer.
You want to write a library class and use the URL that sends a page request to your server to find its geographical location. This library class is a bit like the netGeo class. you can find it on the following URL:
Http://www.phpclasses.org/browse/package/514.html
This class uses a switch function to distribute different web pages based on the URL region. for example, for URL requests from the UK and the United States, you will return an English web page, A German webpage is returned for URL requests from Germany and Austria. The complete URL is divided into two parts: basic URL (www.mysite.com/index.php) and additional URL (mypage/germanversion ).
You need to obtain the basic URL from the config file of CI. The second half of the URL is generated using the swith statement in your new class constructor. If this customer is in Germany, call the German page function, and so on. After this work is completed in the constructor, you need to put the result into a class variable, so it can be used in other functions of the same class, which means:
. The basic URL is obtained from the CI config file, which can only be obtained by referencing the CI super object. In other words, you can use $ obj-> config-> item ('base _ url '); obtain
. The second half of the URL is generated by the constructor of your new class and written to a class variable: $ base. this variable is irrelevant to the CI super object. it belongs to your new class and is referenced as $ this-> base
Two keywords are used for loading: $ this-> and $ obj->, which are referenced in the same code. for example:
// Geolocation code here, returning a value through
// Switch statement
// This value is assigned to $ local_url
$ This-> base = $ obj-> config-> item ('base _ url ');
$ This-> base. = $ local_url;
}
}
If you do not know these concepts, they will become the cause of frequent "calling non-object member functions. for example, if you try to call $ obj-> base or $ this-> config-> item (), this error message appears.
You cannot call other controller member methods from a controller. Why do you want to do this? This depends on the situation. In an application, I write a series of self-test functions in each controller. if I call $ this-> selftest (), it completes various useful tests. However, repeated code in each function seems to be inconsistent with the design principles of OO programming. Therefore, I want to write a function in one of the controllers to access other controllers to execute self-testing code. When I do this, I want to get the desired result. The result, of course, cannot be as expected, because the Member methods of another controller cannot be called in one controller.
As a criterion, if your code is called by more than one controller, you can put it into a model or another separated code file.
These are all minor issues. As Rick told me:
"I want to simplify the problem, so I decided to create a large controller object containing a lot of object instances needed... when a user creates their own controllers, they can easily access any resources without worrying about scope issues ".
This is quite good. In most cases, the CI super object is efficient and completely behind the scenes to complete the work. So I don't have to make that T-shirt.
Summary
We have seen that the 'superobject' created by CI ensures that all methods and variables can be automatically obtained without worrying about how to manage and scope.
CI combines a class instance into a super object by referencing an instance. In most cases, you don't need to know how the CI super object works. you just need to use the "->" symbol correctly.
We also learned how to write our own classes and make them work in concert with CI.
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.