Some time ago used ZF, put him when the black box feeling is not very good, has been looking at its source of impulse, but ... If you look at 1.1, the challenge is a little bit bigger. One day and then thought for a long time did not review the design pattern. After reviewing a design pattern, look for a source code that uses this pattern in ZF. Do not read all the source code, read more "Advanced" part of it, to say that the model, do not know whether the model is not all the ZF inside, but there should be enough mode enough I recently read, in the said can look for other open source software to find patterns. This time was a variety of written Test God horse mess of life make a little bit messy, but anyway, review is necessary. Again, ZF, one of the benefits of the ZF is that each component more independent, component not too much dependence between, thus, for the user to provide convenience, of course, for me so boring and lazy to see the source of the people to provide convenience.
Today look at a simple factory, ZF inside the model, but not lack of factory model, the famous zend_db is not stingy with the use of simple factory, and then Ctrl+h (Zend Studio) will find factory especially many, if not wrong should be most of the simple factory. Because zend_db is most commonly used, I also naturally would like to see his implementation. Before looking at the source code, review how to use zend_db and simple factory (here is a stack, first review simple Factory).
Review the Simple factory model
Use the class diagram to recall a simple factory class diagram:
Using a diagram from the author of the abrasive design pattern, you can see that the client gets the object through the factory and invokes it through the API structure. Use factory to hide the creation of specific APIs. And all other users in the use, only need to know to create with factory, through the API structure call can be simple review completed. Seeing a class diagram should remind of a simple factory, because he is really simple. Review the Simple factory, thinking a little jump, directly to see the use of zend_db.
1. Review the use of zend_db
If you do not know how to use, ready to see XXX's source code but do not know how to use XXX, this is a bit embarrassing, so a small look at the use of zend_db, the following paragraph is in the ZF official documents (the individual is not very like ZF documents, no yii easy to read)
/public/index.php
Copy Code code as follows:
$db = zend_db::factory (' Pdo_mysql ', Array (
' Host ' => ' 127.0.0.1 ',
' username ' => ' webuser ',
' Password ' => ' xxxxxxxx ',
' dbname ' => ' test '
));
Here is the database configuration also put in the code, it looks the simplest (in fact, the other is not difficult, but the database is placed in a different location, easy to manage), but this is not the best way under normal circumstances, but in order to highlight the focus, this is the easiest way to choose this. Notice inside the zend_db::factory (' Pdo_mysql ' ...). This paragraph
A $db (a zend_db object) is generated above, using the $db above to query as follows:
Copy Code code as follows:
$db->setfetchmode (zend_db::fetch_obj);
$result = $db->fetchassoc (
' SELECT bug_id, bug_description, bug_status from Bugs '
);
Continue to come from the official website documents, this is the record of the mode of object, and then fetch, everything now seems natural, but still zend_db it as a black box to use. Let's get down to business.
First, look at the zend/db.php code summary:
Copy Code code as follows:
< PHP
Class zend_db
{
/**
Set some constants and default values
*/
/**
* Factory for zend_db_adapter_abstract classes.
*
* The containing the base of the adapter class
* Name, e.g. ' mysqli ' corresponds to class zend_db_adapter_mysqli. This
* Name is currently case-insensitive, but isn't ideal to rely on this behavior.
* If your class is named ' My_company_pdo_mysql ', where ' my_company ' is the namespace
* and ' pdo_mysql ' is the adapter name, it's best to use the name exactly as it
* is defined in the class. This would ensure proper use the factory API.
*
* argument may alternatively is an object of type Zend_config.
* The adapter class base name is read from the ' adapter '.
* The adapter config parameters are read from the ' params '.
*
* Second argument is optional and may a associative array of key-value
* Pairs. This is used as the argument to the adapter constructor.
*
* If The is of type zend_config, it's assumed to contain
* All parameters, and the second argument are ignored.
*
* @param mixed $adapter String name of base adapter class, or Zend_config object.
* @param mixed $config OPTIONAL; An array or Zend_config object with adapter parameters.
* @return Zend_db_adapter_abstract
* @throws zend_db_exception
*/
public static function Factory ($adapter, $config = Array ())
{
Using the Zend_config object, this method is not used, use array directly
if ($config instanceof zend_config) {
$config = $config->toarray ();
}
/*
* Convert zend_config argument to plain string
* Adapter name and separate config object.
*/
if ($adapter instanceof zend_config) {
if (Isset ($adapter->params)) {
$config = $adapter->params->toarray ();
}
if (Isset ($adapter->adapter)) {
$adapter = (string) $adapter->adapter;
} else {
$adapter = null;
}
}
/*
* Verify that adapter parameters are into an array.
*/
if (! Is_array ($config)) {
/**
* @see Zend_db_exception
*/
Require_once ' zend/db/exception.php ';
throw New Zend_db_exception (
' Adapter parameters must is in an array or a Zend_config object ');
}
/*
* Verify that a adapter name has been specified.
*/
if (! is_string ($adapter) | | | empty ($adapter)) {
/**
* @see Zend_db_exception
*/
Require_once ' zend/db/exception.php ';
throw New Zend_db_exception (
' Adapter name must is specified in a string ');
}
/*
* Form Full Adapter class name
*/
$adapterNamespace = ' Zend_db_adapter ';
if (Isset ($config [' adapternamespace '])) {
if ($config [' adapternamespace ']!= ') {
$adapterNamespace = $config [' Adapternamespace '];
}
unset ($config [' adapternamespace ']);
}
Adapter no longer normalized-see http://framework.zend.com/issues/browse/ZF-5606
$adapterName = $adapterNamespace. '_';
$adapterName. = Str_replace (', ' _ '),
Ucwords (Str_replace (' _ ', ', ', Strtolower ($adapter)));
/*
* Load the adapter class. This is throws an exception
* If the specified class cannot be loaded.
*/
if (! class_exists ($adapterName)) {
Require_once ' zend/loader.php ';
Zend_loader::loadclass ($adapterName);
}
/*
* Create An instance of the adapter class.
* Pass the config to the adapter class constructor.
*/
$dbAdapter = new $adapterName ($config);
/*
* Verify That's the object created is a descendent of the abstract adapter type.
*/
if (! $dbAdapter instanceof Zend_db_adapter_abstract) {
/**
* @see Zend_db_exception
*/
Require_once ' zend/db/exception.php ';
throw New Zend_db_exception (
"Adapter class ' $adapterName ' does not extend Zend_db_adapter_abstract");
}
return $dbAdapter;
}
}
The top comment is well worth looking at, and it clearly illustrates the factory, while another important piece of code (ignoring exception handling) is:
Copy Code code as follows:
Factory has a parameter called $adapter
public static function Factory ($adapter, $config = Array ())
Determine namespace
$adapterNamespace = ' Zend_db_adapter ';
Construct class names with namespace and the $adapter passed in above
$adapterName = $adapterNamespace. '_';
$adapterName. = Str_replace (', ' _ ', Ucwords (Str_replace (' _ ', ', ', Strtolower ($adapter)));
Using the class name generated above to new obj, it looks like PHP is a little bit more convenient than Java (Class.forName (' XXX '). newinstance ())
$dbAdapter = new $adapterName ($config);
Recall the place where you used zend_db::factory to generate $DB:
Copy Code code as follows:
$db = zend_db::factory (' Pdo_mysql ', Array (
' Host ' => ' 127.0.0.1 ',
' username ' => ' webuser ',
' Password ' => ' xxxxxxxx ',
' dbname ' => ' test '
));
The first parameter of the factory method is $adapter for Pdo_mysql, remember here is pdo_mysql, and then jump again, according to the above $adapternamespace = ' zend_db_adapter '; you can see the generated find $ Dbadapter value will eventually be: Zend_db_adapter_pdo_mysql,ok, according to the name of the Zend/db/adapter/pdo directory, ha, so many familiar faces, see the familiar Mysql, Mssql, SQLite these old faces.
Note that there is also a low-key abstract.php inside their parent class zend_db_adapter_pdo_abstract. Open mysql.php to see
Class Zend_db_adapter_pdo_mysql extends Zend_db_adapter_pdo_abstract
Well, the class name Zend_db_adapter_pdo_mysql, like the name generated above, looks at the classes in several other files, and they all inherit from Zend_db_adapter_pdo_abstract, if you want to draw a class diagram, Then there should be a class diagram as follows:
Then add the location where the client and factory functions are called zend_db, and this simple class diagram should be
A very, very pure simple factory just came out. (Unlike a simple factory class diagram?) That's just because the class is not positioned properly.