营造协调的PHP框架–创造组件的体制

在事先的博客中,大家成功了着力的Model类,但是大家应该还记得,大家创制数据库的pdo实例时,是hard好的配置,并且直接hard在Model类中。

代码如下:

    public static function getDb()
    {
        if (empty(static::$pdo)) {
            $host = 'localhost';
            $database = 'sf';
            $username = 'jun';
            $password = 'jun';
            $options = [
                PDO::ATTR_EMULATE_PREPARES => false,
                PDO::ATTR_STRINGIFY_FETCHES => false
            ];
            static::$pdo = new PDO("mysql:host=$host;dbname=$database", $username, $password, $options);
            static::$pdo->exec("set names 'utf8'");
        }

        return static::$pdo;
    }

那明显是不正好的,修改的时候须要取修改框架的代码。未来大家就来将它抽出来。

先是大家供给将安插获得对应的布署文件中,大家在simple-framework文件夹下创建1个config文件夹,然后添加3个db.php文件。在在那之中添加相关的配备。

代码如下:

return [
    'class' => '\PDO',
    'dsn' => 'mysql:host=localhost;dbname=sf',
    'username' => 'jun',
    'password' => 'jun',
    'options' => [
        \PDO::ATTR_EMULATE_PREPARES => false,
        \PDO::ATTR_STRINGIFY_FETCHES => false,
    ],
];

实际正是回到二个数组,数组中是大家创设pdo实例所须要的参数。在开创pdo实例在此以前,将db.php文件require进来即可。

代码如下:

    public static function getDb()
    {
        if (empty(static::$pdo)) {
            $config = require('../config/db.php');
            static::$pdo = new $config['class']($config['dsn'], $config['username'], $config['password'], $config['options']);
            static::$pdo->exec("set names 'utf8'");
        }

        return static::$pdo;
    }

这么还是有点不爽,在require配置文件的时候,小编供给一薄薄的去六柱预测对地点,假设错了,就找不到了。而且以往无论是安插文件恐怕Model文件的地方变动了,相对地方就变了,小编都亟待修改那段代码。就算改成相对地址是或不是会好有的,至少安排文件地方不变,就不要求修改那段代码。

不过要改成相对地址,笔者就供给稳定simple-framework文件夹的地方,所以我们在public/index.php中define八个常量,标记simple-framework文件夹的地址。

public/index.php代码如下:

<?php
define('SF_PATH', dirname(__DIR__));
require_once(SF_PATH . '/vendor/autoload.php');

$application = new sf\web\Application();
$application->run();

概念了常量SF_PATH,Model中的require可改为如下代码:

$config = require(SF_PATH . '/config/db.php');

OK,这样看起来好多了。

只是本身又想到,要是以往本人又须要3个cache的实例,笔者是不是又要把getDb的章程写三遍呢?如若要制止那种气象,小编是或不是理所应当把它抽想出去吗?那要什么抽象呢?

这些时候大家或者需求有3个艺术,大家只供给报告它大家需求创造七个怎么实例,然后它就和好去取相应的参数,并创制出相应的实例来。那样是还是不是很爽。

作者们供给在src文件夹下成立3个Sf.php,在内部成立一个createObject方法,用来创建实例。

但以此时候大家又遇上二个标题,pdo实例创造的时候,要按自然的逐一传一定个数的参数,但大家以后须要创设的别样的实例,恐怕传递的参数的个数和key都不可同日而语,那大家该如何做?

于是大家需求一种体制可以将参数存起来,真正成立实例时,再取出来使用。大家得以在src/db文件夹下成立一个Connection类,Sf中的createObject方法创设了那几个类的实例,那几个类提供一个创办pdo实例的主意即可。

Sf.php中的代码如下:

<?php
/**
 * Sf is a helper class serving common framework functionalities.
 * @author Harry Sun <sunguangjun@126.com>
 */
class Sf
{
    /**
     * Creates a new object using the given configuration.
     * You may view this method as an enhanced version of the `new` operator.
     * @param string $name the object name
     */
    public static function createObject($name)
    {
        $config = require(SF_PATH . "/config/$name.php");
        // create instance
        $instance = new $config['class']();
        unset($config['class']);
        // add attributes
        foreach ($config as $key => $value) {
            $instance->$key = $value;
        }
        return $instance;
    }
}

Sf类没有namespace,所以不切合psr4的规则,要求手动引入,在public/index.php中进入如下一句话:

require_once(SF_PATH . '/src/Sf.php');

Connection.php中的代码如下:

<?php
namespace sf\db;

use PDO;

/**
 * Connection represents a connection to a database via [PDO](php.net/manual/en/book.pdo.php).
 * @author Harry Sun <sunguangjun@126.com>
 */
class Connection
{
    /**
     * @var string the Data Source Name, or DSN, contains the information required to connect to the database.
     * Please refer to the [PHP manual](http://www.php.net/manual/en/function.PDO-construct.php) on
     * the format of the DSN string.
     * @see charset
     */
    public $dsn;

    /**
     * @var string the username for establishing DB connection. Defaults to `null` meaning no username to use.
     */
    public $username;

    /**
     * @var string the password for establishing DB connection. Defaults to `null` meaning no password to use.
     */
    public $password;

    /**
     * @var array PDO attributes (name => value)
     * to establish a DB connection. Please refer to the
     * [PHP manual](http://www.php.net/manual/en/function.PDO-setAttribute.php) for
     * details about available attributes.
     */
    public $attributes;

    public function getDb()
    {
        return new PDO($this->dsn, $this->username, $this->password, $this->attributes);
    }
}

就算不出示注解dsn/username/password和attributes属性也是可行的,但本人觉得依然证明出来比较好,那样大家收看这些类的时候,会知晓有哪些属性。

Model类中的getDb方法改成如下代码:

    public static function getDb()
    {
        if (empty(static::$pdo)) {
            static::$pdo = Sf::createObject('db')->getDb();
            static::$pdo->exec("set names 'utf8'");
        }

        return static::$pdo;
    }

绝不遗忘须求use一下Sf。

config中的db.php也要随着修改,代码如下:

<?php
return [
    'class' => '\sf\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=sf',
    'username' => 'jun',
    'password' => 'jun',
    'attributes' => [
        \PDO::ATTR_EMULATE_PREPARES => false,
        \PDO::ATTR_STRINGIFY_FETCHES => false,
    ],
];

本人默默的将options换到了attributes,终归在PDO的文书档案里,写的是attribute。

好了,后天就先到此地。项目内容和博客内容也都会安置Github上,欢迎大家提指出。

code:https://github.com/CraryPrimitiveMan/simple-framework/tree/0.8

blog
project:https://github.com/CraryPrimitiveMan/create-your-own-php-framework

相关文章