Yii PHP framework analysis (1)

Source: Internet
Author: User
Tags autoload aliases

I recently read the PHP yii framework and now I will repost the information I found online:

Yii PHP framework analysis (1)
Author: wdy

Http://hi.baidu.com/delphiss/blog/item/f7da86d787adb72506088b4b.html

Code Analysis Based on yii1.0.8. It took an afternoon to sort out and keep up with the account. If you are interested, we will release a revised version during the National Day, and then complete the last two parts (Overall Structure Analysis of MVC and yii ).

1. Start

The only website Entry Program index. php:


$ Yii = dirname (_ file _). '/../framework/yii. php ';
$ Config = dirname (_ file _). '/protected/config/Main. php ';

// Remove the following line when in production mode
Defined ('II _ debug') or define ('II _ debug', true );

Require_once ($ yii );
Yii: createwebapplication ($ config)-> Run ();

The above require_once ($ yii) references the global yii class to be used later. The yii class is the full inheritance of the yiibase class:

Class yii extends yiibase
{
}

Global access of the system is implemented through yii class (that is, yiibase class), and all Members and methods of yii class are static.

2. class loading

Yii uses the SPL library provided by PhP5 to automatically load classes. At the end of the yiibase. php file

Spl_autoload_register (Array ('yibase', 'autoload '));

Register the static method autoload of the yiibase class as the class loader. The simple principle of PHP autoload is that when a new object is created or a static member is accessed through the class name, the system passes the class name to the registered Class Loader function, the classloader function finds the corresponding class file based on the class name and includes it.

The following is the autoload method of the yiibase class:

Public static function autoload ($ classname)
{
// Use include so that the error PHP file may appear
If (isset (Self ::$ _ coreclasses [$ classname])
Include (yii_path.self: $ _ coreclasses [$ classname]);
Else if (isset (SELF: $ _ classes [$ classname])
Include (SELF: $ _ classes [$ classname]);
Else
Include ($ classname. '. php ');
}

You can see that the yiibase static member $ _ coreclasses array contains the file path of the classes used by the yii system in advance:

Private Static $ _ coreclasses = array (
'Capplication '=>'/base/capplication. php ',
'Cbehavior '=>'/base/cbehavior. php ',
'Ccomponent' => '/base/cComponent. php ',
...
)

Non-coreclasse classes are registered in the $ _ classes array of yiibase:
Private Static $ _ classes = array ();

To import other classes, use the yii: Import () Class path to PHP Include paths.
Include ($ classname. '. php ')

3. Create cwebapplication

Return to the yii: createwebapplication ($ config)-> Run ();

Public static function createwebapplication ($ Config = NULL)
{
Return new cwebapplication ($ config );
}

Now the autoload mechanism is working.
When the system executes new cwebapplication (),
Include (yii_path. '/base/capplication. php ')

Pass the configuration information array $ config in Main. php to the cwebapplication to create an object and execute the run () method of the object to start the framework.

Inheritance relationship of the cwebapplication class

Cwebapplication-> capplication-> cmodule-> cComponent

$ Config is first passed to the constructor of capplication.

Public Function _ construct ($ Config = NULL)
{
Yii: setapplication ($ this );

// Set basepath at early as possible to avoid trouble
If (is_string ($ config ))
$ Config = require ($ config );
If (isset ($ config ['basepath'])
{
$ This-> setbasepath ($ config ['basepath']);
Unset ($ config ['basepath']);
}
Else
$ This-> setbasepath ('protected ');
Yii: setpathofalias ('application', $ this-> getbasepath ());
Yii: setpathofalias ('webroot', dirname ($ _ server ['script _ filename']);

$ This-> preinit ();

$ This-> initsystemhandlers ();
$ This-> registercorecomponents ();

$ This-> Configure ($ config );
$ This-> attachbehaviors ($ this-> behaviors );
$ This-> preloadcomponents ();

$ This-> Init ();
}


Yii: setapplication ($ this); assigns its instance object to the static member $ _ app of yii, which can be obtained later through yii: APP.
The following section sets the _ basepath of the capplication object and points to the proteced directory.

Yii: setpathofalias ('application', $ this-> getbasepath ());
Yii: setpathofalias ('webroot', dirname ($ _ server ['script _ filename']);

Two System Path aliases are set: Application and webroot. You can use the alias to replace the actual full path when importing the system later. The alias configuration is stored in the $ _ aliases array of yiibase.

$ This-> preinit ();
Pre-initialization. Preinit () is defined in the cmodule class without any action.

$ This-> initsystemhandlers () method content:

/**
* Initializes the class autoloader and error handlers.
*/
Protected function initsystemhandlers ()
{
If (yii_enable_exception_handler)
Set_exception_handler (Array ($ this, 'handleexception '));
If (yii_enable_error_handler)
Set_error_handler (Array ($ this, 'handleerror'), error_reporting ());
}

Set the system exception_handler and error_handler to point to the two methods provided by the object itself.

4. Register Core Components

$ This-> registercorecomponents ();
The Code is as follows:

Protected function registercorecomponents ()
{
Parent: registercorecomponents ();

$ Components = array (
'Urlmanager' => array (
'Class' => 'curlmanager ',
),
'Request' => array (
'Class' => 'chttprequest ',
),
'Session '=> array (
'Class' => 'chttpsession ',
),
'Assetmanager' => array (
'Class' => 'cassetmanager ',
),
'User' => array (
'Class' => 'webuser ',
),
'Themanager '=> array (
'Class' => 'cthemanager ',
),
'Authmanager' => array (
'Class' => 'cphpauthmanager ',
),
'Clientscript' => array (
'Class' => 'ccclientscript ',
),
);

$ This-> setcomponents ($ components );
}

You have registered several system components ).
Components is defined and managed in the cmodule, mainly including two Arrays

Private $ _ components = array ();
Private $ _ componentconfig = array ();

Each component is an instance of the iapplicationcomponent interface. The componemts instance is stored in the $ _ components array, and the related configuration information is stored in the $ _ componentconfig array. The configuration information includes the class name and attribute settings of component.

The cwebapplication object registers the following components: urlmanager, request, session, assetmanager, user, themanager, authmanager, and clientscript. The cwebapplication parent registers the following components: coremessages, DB, messages, errorhandler, securitymanager, and statepersister.

Component is a very important thing in yiiphp. Its feature is that it can be accessed through the _ Get () and _ set () Methods of cmodule. When component is registered, it does not create an object instance. Instead, it is created by the cmodule (actually yii: APP () when the program is accessed for the first time.

5. Process $ config Configuration

Continue, $ this-> Configure ($ config );
Configure () is still in cmodule:

Public Function configure ($ config)
{
If (is_array ($ config ))
{
Foreach ($ config as $ key => $ value)
$ This-> $ key = $ value;
}
}

In fact, each item in the $ config array is passed to the cComponent _ set () method of the parent class of cmodule.

Public Function _ set ($ name, $ value)
{
$ Setter = 'set'. $ name;
If (method_exists ($ this, $ setter ))
$ This-> $ setter ($ value );
Else if (strncasecmp ($ name, 'on', 2) = 0
& Method_exists ($ this, $ name ))
{
// Duplicating geteventhandlers () HERE FOR PERFORMANCE
$ Name = strtolower ($ name );
If (! Isset ($ this-> _ e [$ name])
$ This-> _ e [$ name] = new clist;
$ This-> _ e [$ name]-> Add ($ value );
}
Else if (method_exists ($ this, 'get'. $ name ))
Throw new cexception (yii: T ('yii', 'Property "{class}. {property}" is read only .',
Array ('{class}' => get_class ($ this), '{property}' => $ name )));
Else
Throw new cexception (yii: T ('yii', 'Property "{class}. {property}" is not defined .',
Array ('{class}' => get_class ($ this), '{property}' => $ name )));
}
}

Let's take a look:
If (method_exists ($ this, $ setter ))
According to this condition, the basepath, Params, modules, import, and components in the $ config array are all passed to the corresponding setbasepath () and setparams () methods for processing.

6. $ config Import

Here, import is passed to the cmodule's setimport:

Public Function setimport ($ aliases)
{
Foreach ($ aliases as $ alias)
Yii: Import ($ alias );
}

Processing in yii: Import ($ alias:

Public static Function Import ($ alias, $ forceinclude = false)
{
// First determine whether $ alias exists in yiibase: $ _ imports []. The existing direct return statement avoids repeated import.
If (isset (Self ::$ _ imports [$ alias]) // previusly imported
Return self: $ _ imports [$ alias];

// $ The alias class has been defined. It is recorded in $ _ imports [] and directly returned.
If (class_exists ($ alias, false ))
Return self: $ _ imports [$ alias] = $ alias;

// A class similar to urlmanager defined in $ _ coreclasses [] or a direct class name without. is recorded in $ _ imports [] and returned directly.
If (isset (SELF: $ _ coreclasses [$ alias]) | ($ Pos = strrpos ($ alias ,'. ') = false) // a simple class name
{
SELF: $ _ imports [$ alias] = $ alias;
If ($ forceinclude)
{
If (isset (SELF: $ _ coreclasses [$ alias]) // a core class
Require (yii_path.self: $ _ coreclasses [$ alias]);
Else
Require ($ alias. '. php ');
}
Return $ alias;
}

// Generate a variable $ classname, which is the last part of $ alias.
// Like this: 'x. Y. classnamer'
// $ Classname is not equal to '*'. If the classnamer class has been defined, the classnamer is recorded in $ _ imports [] and returns directly
If ($ classname = (string) substr ($ alias, $ POS + 1 ))! = '*' & Class_exists ($ classname, false ))
Return self: $ _ imports [$ alias] = $ classname;

// Get the actual path in $ alias and the path is valid
If ($ Path = self: getpathofalias ($ alias ))! = False)
{
// $ Classname! = '*', $ Classname is recorded in $ _ imports []
If ($ classname! = '*')
{
SELF: $ _ imports [$ alias] = $ classname;
If ($ forceinclude)
Require ($ path. '. php ');
Else
SELF: $ _ classes [$ classname] = $ path. '. php ';
Return $ classname;
}
// $ Alias is a path ending with * Like 'System. Web. * '. Add the path to include_path.
Else // a directory
{
Set_include_path (get_include_path (). path_separator. $ PATH );
Return self: $ _ imports [$ alias] = $ path;
}
}
Else
Throw new cexception (yii: T ('yii', 'Alias "{alias}" is invalid. Make sure it points to an existing directory or file .',
Array ('{alias}' => $ alias )));
}

7. $ config Components

$ Components in the $ config array is passed to the setcomponents ($ components) of the cmodule)

Public Function setcomponents ($ components)
{
Foreach ($ components as $ id => $ component)
{
If ($ component instanceof iapplicationcomponent)
$ This-> setcomponent ($ id, $ component );
Else if (isset ($ this-> _ componentconfig [$ id])
$ This-> _ componentconfig [$ id] = cmap: mergearray ($ this-> _ componentconfig [$ id], $ component );
Else
$ This-> _ componentconfig [$ id] = $ component;
}
}

When $ componen is an iapplicationcomponen instance, the value is assigned directly:
$ This-> setcomponent ($ id, $ component ),

Public Function setcomponent ($ id, $ component)
{
$ This-> _ components [$ id] = $ component;
If (! $ Component-> getisinitialized ())
$ Component-> Init ();
}

If $ ID already exists in _ componentconfig [] (corecomponent registered earlier), add the $ component attribute.
Other component attributes are stored in _ componentconfig.

8. $ config Params

This is simple
Public Function setparams ($ value)
{
$ Params = $ this-> getparams ();
Foreach ($ value as $ k => $ V)
$ Params-> Add ($ K, $ V );
}

Configure complete!

9. attachbehaviors

$ This-> attachbehaviors ($ this-> behaviors );
Empty, no action

Pre-Create component object
$ This-> preloadcomponents ();

Protected function preloadcomponents ()
{
Foreach ($ this-> preload as $ id)
$ This-> getcomponent ($ id );
}

Getcomponent () determines whether there are $ id instances in the _ components [] array. If not, create a Component Object Based on the configuration in _ componentconfig [$ id, call the init () method of the component and save it to _ components [$ id.

10. INIT ()

$ This-> Init ();

Function: $ this-> getrequest ();
The reques component is created and initialized.

11. Run ()

Public Function run ()
{
$ This-> onbeginrequest (New cevent ($ this ));
$ This-> processrequest ();
$ This-> onendrequest (New cevent ($ this ));
}

Contact Us

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.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.