Home  >  Article  >  Backend Development  >  Simple Factory Pattern in Zend Framework Graphics_PHP Tutorial

Simple Factory Pattern in Zend Framework Graphics_PHP Tutorial

WBOY
WBOYOriginal
2016-07-21 15:17:51895browse

I used ZF some time ago, and it didn't feel very good to treat it as a black box. I always had the urge to look at its source code, but. . . If you look at it bit by bit, the challenge is indeed a bit big. One day it occurred to me that I haven't reviewed design patterns for a long time. To sum it up, after reviewing a design pattern, look for the source code that uses this pattern in ZF. Don’t read all the source code, but read the more “advanced” parts. When it comes to patterns, I don’t know if all patterns are included in ZF. , but there should be enough patterns. I have looked at it recently, and I am saying that I can look for other open source software to find patterns. During this period of time, all kinds of written examinations have made my life a little chaotic, but no matter what, review is still necessary. Let’s talk about ZF again. One of the advantages of ZF is that each component is relatively independent, and there is not too much dependence between components. This provides convenience for users, and of course it also provides convenience for boring and lazy people like me who want to read the source code. convenient.

Let’s take a look at the simple factory today. There is no shortage of patterns in ZF, let alone factory patterns. The famous Zend_Db uses simple factories without hesitation. Then ctrl+h (under zend studio) you will find factory There are a lot of them. If I guess correctly, most of them should be simple factories. Since Zend_Db is the most commonly used, I naturally want to see its implementation. Before looking at the source code, first review how to use Zend_Db and a simple factory (this is a stack, review the simple factory first).

Review the simple factory pattern
Use a class diagram to recall the simple factory class diagram:

Borrowing a picture from the author of "Grinding Design Pattern", you can see that the Client obtains the object through the factory and calls it through the Api structure. Use factory to hide the creation of specific APIs. When all other users use it, they only need to know how to create it with the factory and call it through the Api structure. A simple review is completed. When you see the class diagram, you should think of a simple factory, because it is indeed very simple. After reviewing the simple factory, let’s jump in a little and let’s look directly at the use of Zend_Db.
1. Review the use of Zend_Db
If you don’t know how to use it, it’s a bit embarrassing to look at the source code of XXX but don’t know how to use XXX, so let’s take a brief look at the use of Zend_Db. The following paragraph is in From ZF official documents (I personally don’t like ZF documents very much, they are not as easy to read as Yii)
/public/index.php
Copy code The code is 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 into the code Inside, it looks the simplest (actually the others are not difficult, it’s just that the database is placed in a different location for easier management), but this is not the best way under normal circumstances, but in order to highlight the key points, the simplest one is chosen here. Way. Pay attention to the Zend_Db::factory('Pdo_Mysql'... This paragraph
generates a $db (a Zend_Db object) above. Use the above $db to query as follows:
Copy the code The code is as follows:

$db->setFetchMode(Zend_Db::FETCH_OBJ);
$result = $db->fetchAssoc(
' SELECT bug_id, bug_description, bug_status FROM bugs'
);

Continuing from the official website document, this is to fetch the record mode as Object, and then fetch, everything seems natural now, but it is still Use Zend_Db as a black box.
First, look at the code summary of zend/Db.php:
Copy the codeThe code is as follows:

< ?php
class Zend_Db
{
/**
Set some constants and default values ​​
*/
/**
* Factory for Zend_Db_Adapter_Abstract classes.
*
* First argument may be a string 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 is not 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 is best to use the name exactly as it
* is defined in the class. This will ensure proper use of the factory API.
*
* First argument may alternatively be an object of type Zend_Config.
* The adapter class base name is read from the 'adapter' property.
* The adapter config parameters are read from the 'params' property.
*
* Second argument is optional and may be an associative array of key-value
* pairs. This is used as the argument to the adapter constructor.
*
* If the first argument is of type Zend_Config, it is assumed to contain
* all parameters, and the second argument is 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())
{
//使用Zend_Config对象,上述方式没有使用,直接使用Array
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 in an array.
*/
if (! is_array($config)) {
/**
* @see Zend_Db_Exception
*/
require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception(
'Adapter parameters must be in an array or a Zend_Config object');
}
/*
* Verify that an 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 be 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 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 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;
}
}

最上方的注释非常值得看,它清楚的说明了这个工厂,另外一段比较重要的几段代码(忽略其中的异常处理)是:
复制代码 代码如下:

//factory有一个参数叫做$adapter
public static function factory($adapter, $config = array())

//确定namespace
$adapterNamespace = 'Zend_Db_Adapter';

//用namespace和上面传入的$adapter构造类名
$adapterName = $adapterNamespace . '_';
$adapterName .= str_replace(' ', '_', ucwords(str_replace('_', ' ', strtolower($adapter))));

//用上面生成的类名new出obj,看起来PHP比java方便那么一点点哈(Class.forName(‘XXX').newInstance())
$dbAdapter = new $adapterName($config);

Recall the above place where Zend_Db::factory was used to generate $db:
Copy the code The code is 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 that $adapter is Pdo_Mysql, remember here is Pdo_Mysql , jump again, according to the above $adapterNamespace = 'Zend_Db_Adapter'; you can see that the generated value of $dbAdapter must eventually be: Zend_Db_Adapter_Pdo_Mysql, ok, according to this name, find the zend/db/adapter/pdo directory, ha, so There are so many familiar faces. I saw familiar old faces such as MySql, Mssql, and Sqlite.


Note, note, there is also a low-key Abstract.php inside, which contains their parent class Zend_Db_Adapter_Pdo_Abstract. Open Mysql.php and you can see
class Zend_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Abstract

Well, the class name Zend_Db_Adapter_Pdo_Mysql is the same as the name generated above. Looking at the classes in several other files, they all inherit from Zend_Db_Adapter_Pdo_Abstract. If you want to draw a class diagram, you should have a class diagram like the following:

Then add Zend_Db, where the Client and factory functions are called, this is simple The class diagram should be,

A very, very pure simple factory comes out like this (isn’t it like a simple factory class diagram? That’s just because the position of the class is not placed good).

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/325670.htmlTechArticleI used ZF some time ago and it didn’t feel very good to treat it as a black box. I always had the urge to look at its source code. but. . . If you look at it bit by bit, the challenge is indeed quite big. One day I thought again...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn