溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用 Composer 開(kāi)源組件構(gòu)建自己的 PHP 框架

發(fā)布時(shí)間:2020-07-16 14:24:38 來(lái)源:億速云 閱讀:283 作者:Leah 欄目:編程語(yǔ)言

這篇文章將為大家詳細(xì)講解有關(guān)如何使用 Composer 開(kāi)源組件構(gòu)建自己的 PHP 框架,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。


現(xiàn)在的 PHP 框架很多,當(dāng)然不止 PHP ,即使是其他編程語(yǔ)言也有很多框架,這篇文章講 PHP 框架構(gòu)建是因?yàn)槲覍?duì) PHP 的生態(tài)最為熟悉,但這個(gè)方法同樣也適用于其他編程語(yǔ)言框架的構(gòu)建。

框架是為了提升我們的應(yīng)用開(kāi)發(fā)效率,市面上有很多開(kāi)源免費(fèi)的框架給我們使用,我們盡可以拿來(lái)用,為什么還要自己構(gòu)建一個(gè)自己的框架呢?原因就在于市面上的開(kāi)源框架,是給大部分人用的,給通用項(xiàng)目用的,作為框架的開(kāi)發(fā)者是不知道自己的框架使用者的具體業(yè)務(wù)的,所以開(kāi)源框架一定是滿足大部分人的需求,而且力求能夠?yàn)殚_(kāi)發(fā)者提供所有可能用到的功能。

但是對(duì)于一個(gè)商業(yè)項(xiàng)目或者是一個(gè)你自己要做的項(xiàng)目也許只能用到框架的很少一部分功能,或者是框架給你提供的東西并不是最符合你自己的需求的,你使用了框架的一部分功能,另一部分根本沒(méi)用,這樣使用框架首先是性能上的損失,一些你根本用不到的功能卻要降低你應(yīng)用的性能顯然不合適的。再就是也許框架提供的功能不是你想要的,或者這個(gè)功能這個(gè)框架提供的并不是符合你需求的,又或者要使用這部分功能必須按照框架開(kāi)發(fā)者制定的規(guī)范來(lái)使用,這個(gè)規(guī)范并符合你的開(kāi)發(fā)哲學(xué)。

從哪開(kāi)始?

各種現(xiàn)代編程語(yǔ)言都有自己的包管理工具,PHP 就是 composer ,利用它我們就可以構(gòu)建屬于自己的框架了,并能很好的組織我們的框架。

怎么開(kāi)始?

我們?cè)撛趺撮_(kāi)始構(gòu)建我們自己的框架呢?從零開(kāi)始嗎?這個(gè)問(wèn)題沒(méi)有標(biāo)準(zhǔn)答案,如果你要做的項(xiàng)目要求很?chē)?yán)格,從底層開(kāi)始就要保證項(xiàng)目架構(gòu)的最穩(wěn)定可控,那么建議你從零開(kāi)始。如果要求不是非常嚴(yán)格那么我們就從那些開(kāi)發(fā)一個(gè)應(yīng)用最基本需要的功能開(kāi)始,這樣的功能誰(shuí)提供呢?PHP 有很多微框架,這些框架提供開(kāi)發(fā)一個(gè)應(yīng)用最基礎(chǔ)的功能,我們可以從這里開(kāi)始。

首先我們通過(guò) composer init 初始化一個(gè)項(xiàng)目:

{
    "name": "dongm2ez/m2ez-framework",
    "description": "a dongm2ez's framework",
    "keywords": ["framework", "m2ez-framework"],
    "license": "MIT",
    "authors": [
        {
            "name": "dongm2ez",
            "email": "dongm2ez@163.com"
        }
    ],
    "require": {}
}

這就是我得到的一個(gè) composer.json 的描述文件,現(xiàn)在我們就從這里開(kāi)始。我的目標(biāo)是構(gòu)建一個(gè)最符合我開(kāi)發(fā)習(xí)慣的框架,讓我的開(kāi)發(fā)效率最高。

我選擇 Slim 框架作為我的框架基礎(chǔ)框架,這是一個(gè)微框架,我喜歡它,它足夠簡(jiǎn)單,提供了 web 開(kāi)發(fā) 和 API 開(kāi)發(fā)最基礎(chǔ)的功能,而且還有一個(gè)原因開(kāi)發(fā)這個(gè)框架的作者寫(xiě)了一本名為《Modern PHP》的書(shū),這本書(shū)顛覆了我對(duì) PHP 這個(gè)語(yǔ)言的認(rèn)知,開(kāi)始喜歡并樂(lè)于使用它。

在引入這個(gè)框架之前我還要對(duì) PHP 版本做個(gè)限制,從我使用 PHP 從 5.2 開(kāi)始到現(xiàn)在,PHP 已經(jīng)發(fā)展到 PHP 7.2 了,但是我不想再去使用低版本的 PHP,一個(gè)是 PHP 低版本馬上將失去官方的支付,另一個(gè)是一些 PHP 的新特性我不能使用,而且低版本的性能也是不好的。所以我要將我的框架限制在 PHP 7.0 以上,同時(shí)我希望我的框架對(duì)中文有更好的支持。

那么我將更新我的框架 composer.json 文件:

{
    "name": "dongm2ez/m2ez-framework",
    "description": "a dongm2ez's framework",
    "keywords": ["framework", "m2ez-framework"],
    "license": "MIT",
    "authors": [
        {
            "name": "dongm2ez",
            "email": "dongm2ez@163.com"
        }
    ],
    "require": {
        "php": ">=7.0.0",
        "ext-mbstring": "*",
        "slim/slim": "^3.0"
    }
}

這樣我就獲得了一個(gè)最基礎(chǔ)的我的框架版本,但是我還沒(méi)完成,因?yàn)槲覀儧](méi)有定義我的框架目錄結(jié)構(gòu)。我覺(jué)得 laravel 框架的目錄劃分是挺讓我喜歡的,但我又不完全喜歡 laravel 的目錄結(jié)構(gòu),我需要對(duì)它進(jìn)行改造。

├── app
│   ├── Helpers.php
│   ├── Http
│   │   └── Controllers
│   └── Models
├── composer.json
└── tests

我這樣設(shè)置我的目錄結(jié)構(gòu),并更新我的 composer.json:

{
    "name": "dongm2ez/m2ez-framework",
    "description": "a dongm2ez's framework",
    "keywords": ["framework", "m2ez-framework"],
    "license": "MIT",
    "type": "project",
    "authors": [
        {
            "name": "dongm2ez",
            "email": "dongm2ez@163.com"
        }
    ],
    "require": {
        "php": ">=7.0.0",
        "slim/slim": "^3.0"
    },
    "require-dev": {
        "phpunit/phpunit": "~6.0"
    },
    "autoload": {
        "classmap": [
            "app/Models"
        ],
        "psr-4": {
            "App\\": "app/"
        },
        "files": [
            "app/Helpers.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    }
}

這樣的框架可以訪問(wèn)嗎,顯然是不行的,我們還要加一些東西讓我們的框架真正可以跑起來(lái),然后在來(lái)迭代它。

├── app
│   ├── Helpers.php
│   ├── Http
│   │   └── Controllers
│   └── Models
├── bootstrap
│   ├── app.php
│   └── autoload.php
├── composer.json
├── config
├── public
│   └── index.php
├── routers
└── tests

我們將目錄結(jié)構(gòu)改造成這樣,并編寫(xiě)一些啟動(dòng)框架的代碼到相應(yīng)的文件

// public/index.php
<?php

require __DIR__.'/../bootstrap/autoload.php';

$app = require_once __DIR__.'/../bootstrap/app.php';

$app->run();

// bootstrap/app.php

<?php

$app = new \Slim\App;

return $app;

// bootstrap/autoload.php

<?php

define('M2EZ_START', microtime(true));

require __DIR__.'/../vendor/autoload.php';

然后運(yùn)行 composer install 安裝框架的依賴包,安裝完成后我們的目錄中就會(huì)多出一個(gè) vendor 的目錄和 composer.lock 的文件,此時(shí)運(yùn)行 php -S 0.0.0.0:8080 -t public public/index.php 利用 PHP 自帶的 web 服務(wù)器進(jìn)行測(cè)試,為了這個(gè)命令更簡(jiǎn)單使用,我們可以將這個(gè)命令加到 composer.jsonscript 中。

此時(shí)訪問(wèn) 127.0.0.1:8080localhost:8080 就可以看到如下的頁(yè)面:

如何使用 Composer 開(kāi)源組件構(gòu)建自己的 PHP 框架

這說(shuō)明框架正確啟動(dòng)了,那么我們?cè)趺创_定框架工作正常呢,這里有個(gè)簡(jiǎn)單方法:

<?php

use Slim\Http\Request;
use Slim\Http\Response;

require __DIR__.'/../bootstrap/autoload.php';

$app = require_once __DIR__.'/../bootstrap/app.php';

$app->get('/hello/{name}', function (Request $request, Response $response) {
    $name = $request->getAttribute('name');
    $response->getBody()->write("Hello, $name");

    return $response;
});

$app->run();

對(duì) public/index.php 的代碼進(jìn)行修改,此時(shí)訪問(wèn) http://localhost:8080/hello/dongm2ez,那么我們就會(huì)看到:

如何使用 Composer 開(kāi)源組件構(gòu)建自己的 PHP 框架

測(cè)試是成功了,但是我們不能把路由和邏輯都寫(xiě)到 index.php 文件里,因此我們需要代碼更好的組織。要讓我們的目錄規(guī)劃發(fā)揮正在的作用。

為了單獨(dú)管理路由,我將路由單獨(dú)寫(xiě)在 routers 文件夾中,在文件夾中我們新建兩個(gè) PHP 腳本文件,然后在 public/index.php 中加入兩行代碼:

<?php
require __DIR__ . '/../bootstrap/autoload.php';

$app = require_once __DIR__ . '/../bootstrap/app.php';

require __DIR__ . '/../routers/web.php';
require __DIR__ . '/../routers/api.php';

$app->run();

變成這樣,這樣我就可以單獨(dú)管理 API 和 WEB 項(xiàng)目的路由了,如果有其他路由就也可以 require 更多路由。

<?php

$app->get('/', '\App\Http\Controllers\WelcomeController:index');

而我們的控制器長(zhǎng)什么樣呢,是這個(gè)樣子的:

<?php

namespace App\Http\Controllers;

use Slim\Http\Request;
use Slim\Http\Response;

class WelcomeController extends Controller
{

    public function index(Request $request, Response $response)
    {
        $response->getBody()->write("Hello, world");

        return $response;

    }

}

我們知道在現(xiàn)代化的框架中,容器會(huì)讓我們很方便,我們的基礎(chǔ)框架 Slim 提供一個(gè)容器的實(shí)現(xiàn),當(dāng)然你也可以使用其他的第三方的,那么這顯然是我們想要的結(jié)果,不是只能使用框架提供的,我們可以隨時(shí)換掉框架的功能,換成我們想要的同樣功能組件。

使用也很簡(jiǎn)單,在 app.php 文件中初始化 Slim 框架時(shí)將容器實(shí)例傳遞給它就可以了。

<?php

$container = new \Slim\Container;
$app = new \Slim\App($container);

return $app;

還記得上面那個(gè)控制器繼承的基類(lèi)控制器嗎,那也是我自己寫(xiě)的,里面可以做一些所有控制器都有可能用的的操作封裝。比如我為了更方便的使用容器,我在基類(lèi)里初始化了一個(gè)容器實(shí)例。

<?php

namespace App\Http\Controllers;

use Interop\Container\ContainerInterface;

abstract class Controller
{
    protected $ci;

    public function __construct(ContainerInterface $ci)
    {
        $this->ci = $ci;
    }

}

現(xiàn)在我已經(jīng)有了 路由功能,有了控制器功能,還有請(qǐng)求響應(yīng)的操作,那么作為一個(gè)完整的框架那么必須有訪問(wèn)數(shù)據(jù)庫(kù)的方法。

我很喜歡 Laravel 提供的數(shù)據(jù)庫(kù) ORM 組件,那么我就決定使用它了,執(zhí)行 composer require illuminate/database "~5.5",我選擇了最新的 Laravel 長(zhǎng)期支持版 ORM 。

我們需要此時(shí)在 config 文件夾中新添加一個(gè)文件 databases.php 文件:

<?php
return [
    'settings' => [
        'db' => [
            'driver' => 'mysql',
            'host' => 'localhost',
            'database' => 'database',
            'username' => 'user',
            'password' => 'password',
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
        ]
    ],
];

然后修改 public/index.php

<?php
require __DIR__ . '/../bootstrap/autoload.php';

$config = require __DIR__ . '/../config/databases.php';

$app = require_once __DIR__ . '/../bootstrap/app.php';

require __DIR__ . '/../routers/web.php';
require __DIR__ . '/../routers/api.php';

$app->run();

修改 bootstrap/app.php

<?php

$container = new \Slim\Container($config);
$app = new \Slim\App($container);

// Service factory for the ORM
$container['db'] = function ($container) {
    $capsule = new \Illuminate\Database\Capsule\Manager;
    $capsule->addConnection($container['settings']['db']);

    $capsule->setAsGlobal();
    $capsule->bootEloquent();

    return $capsule;
};

return $app;

然后我們就可以在控制器中使用 ORM 功能了。

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Facades\DB;
use Interop\Container\ContainerInterface;
use Slim\Http\Request;
use Slim\Http\Response;

class WelcomeController extends Controller
{

    public function index(Request $request, Response $response)
    {
        /** @var DatabaseManager $db */
        $db = $this->ci->get('db');
        $user = $db->table("user")->first();
        var_dump($user);
        $response->getBody()->write("Hello, world");

        return $response;

    }

}

那么此時(shí)這個(gè)框架已經(jīng)是一個(gè)可以開(kāi)發(fā) API 功能的框架了,如果要開(kāi)發(fā) Web 站我可能還需要加入渲染模板組件,無(wú)論是 twig、Smarty、Haml 還是 Blade,全都看你的喜好了。當(dāng)然我覺(jué)得我做到這里就可以了,夠我用了,因?yàn)閷?duì)于前端我更喜歡用 React 或者是 Vue 去實(shí)現(xiàn)它。

需要更簡(jiǎn)便的操作 session、cookie 那么我們也可以添加相應(yīng)的組件,各種已經(jīng)有的框架了都提供這樣的組件,看看你更喜歡哪一個(gè)了,現(xiàn)在你的框架你做主,你想添加什么就可以添加什么組件,經(jīng)過(guò)這樣的定制的框架一定是最符合你開(kāi)發(fā)需求的。

我這里只是對(duì)已有的組件進(jìn)行了配置組裝,一旦哪天你發(fā)現(xiàn)所有的開(kāi)源組件都滿足不了你的需求的時(shí)候,因?yàn)槟銓?duì)你的框架了解,你可以自己造個(gè)輪子給自己的框架用,如果你寫(xiě)的好那么你也會(huì)創(chuàng)造出一個(gè)極好用的框架,現(xiàn)在最流行的 PHP 框架,你可以看看它的 composer.json 文件,它就是在前人的基礎(chǔ)上進(jìn)行開(kāi)發(fā)維護(hù)的,已經(jīng)有的功能他拿來(lái)直接用,覺(jué)得別人做的不完善的地方自己造一個(gè)輪子給大家用。

而且我這里也沒(méi)有用到太多的設(shè)計(jì)模式,你還可以改造你的框架,利用PHP的魔術(shù)方法,反射,SPL 等等讓你的框架更好,更容易擴(kuò)展,更容易配置。

總結(jié)

框架很神秘嗎?看過(guò)這篇文章我相信你不會(huì)這樣覺(jué)得了。

造一個(gè)框架很難嗎,是的很難,因?yàn)閺?0 到 1 任何事都難,但是我們現(xiàn)在還需要從 0 到 1 嗎,基本不需要了!站在巨人身上做事更容易,而且要記住,任何事只有行動(dòng)起來(lái)你就會(huì)發(fā)現(xiàn)嘗試比躊躇不前更好,從小處開(kāi)始,做小事,有一天這個(gè)小事就變成了大事。不積跬步無(wú)以至千里。

Laravel 為什么流行,因?yàn)樽髡弑臼且幻?.net 開(kāi)發(fā)者,在使用 CI 框架時(shí)萌生了想法要做一個(gè)更簡(jiǎn)潔、靈活的框架,他的思想真的很先進(jìn)嗎,不一定的,其他開(kāi)發(fā)語(yǔ)言早就有了 Laravel 中的功能,它只是在 PHP 中實(shí)現(xiàn)了它們。

以上例子其實(shí)告訴我們,不要給自己貼標(biāo)簽,人生不設(shè)限,你不是 PHP 程序員,你就是開(kāi)發(fā)者,任何開(kāi)發(fā)相關(guān)的東西我們都該去了解和掌握,標(biāo)簽只能別人給你貼,不要自己給自己貼。

關(guān)于如何使用 Composer 開(kāi)源組件構(gòu)建自己的 PHP 框架就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI