首頁 後端開發 php教程 用Composer建構屬於你的PHP框架

用Composer建構屬於你的PHP框架

May 02, 2020 am 10:09 AM
php 框架

为什么要构建自己的 PHP 框架?

现在的 PHP 框架很多,当然不止 PHP ,即使是其他编程语言也有很多框架,这篇文章讲 PHP 框架构建是因为我对 PHP 的生态最为熟悉,但这个方法同样也适用于其他编程语言框架的构建。

框架是为了提升我们的应用开发效率,市面上有很多开源免费的框架给我们使用,我们尽可以拿来用,为什么还要自己构建一个自己的框架呢?原因就在于市面上的开源框架,是给大部分人用的,给通用项目用的,作为框架的开发者是不知道自己的框架使用者的具体业务的,所以开源框架一定是满足大部分人的需求,而且力求能够为开发者提供所有可能用到的功能。

但是对于一个商业项目或者是一个你自己要做的项目也许只能用到框架的很少一部分功能,或者是框架给你提供的东西并不是最符合你自己的需求的,你使用了框架的一部分功能,另一部分根本没用,这样使用框架首先是性能上的损失,一些你根本用不到的功能却要降低你应用的性能显然不合适的。再就是也许框架提供的功能不是你想要的,或者这个功能这个框架提供的并不是符合你需求的,又或者要使用这部分功能必须按照框架开发者制定的规范来使用,这个规范并符合你的开发哲学。

从哪开始?

各种现代编程语言都有自己的包管理工具,PHP 就是 composer ,利用它我们就可以构建属于自己的框架了,并能很好的组织我们的框架。

怎么开始?

我们该怎么开始构建我们自己的框架呢?从零开始吗?这个问题没有标准答案,如果你要做的项目要求很严格,从底层开始就要保证项目架构的最稳定可控,那么建议你从零开始。如果要求不是非常严格那么我们就从那些开发一个应用最基本需要的功能开始,这样的功能谁提供呢?PHP 有很多微框架,这些框架提供开发一个应用最基础的功能,我们可以从这里开始。

首先我们通过 composer init 初始化一个项目:

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

复制代码这就是我得到的一个 composer.json 的描述文件,现在我们就从这里开始。我的目标是构建一个最符合我开发习惯的框架,让我的开发效率最高。

我选择 Slim 框架作为我的框架基础框架,这是一个微框架,我喜欢它,它足够简单,提供了 web 开发 和 API 开发最基础的功能,而且还有一个原因开发这个框架的作者写了一本名为《Modern PHP》的书,这本书颠覆了我对 PHP 这个语言的认知,开始喜欢并乐于使用它。

在引入这个框架之前我还要对 PHP 版本做个限制,从我使用 PHP 从 5.2 开始到现在,PHP 已经发展到 PHP 7.2 了,但是我不想再去使用低版本的 PHP,一个是 PHP 低版本马上将失去官方的支付,另一个是一些 PHP 的新特性我不能使用,而且低版本的性能也是不好的。所以我要将我的框架限制在 PHP 7.0 以上,同时我希望我的框架对中文有更好的支持。

那么我将更新我的框架 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"
    }
}
登入後複製

复制代码这样我就获得了一个最基础的我的框架版本,但是我还没完成,因为我们没有定义我的框架目录结构。我觉得 laravel 框架的目录划分是挺让我喜欢的,但我又不完全喜欢 laravel 的目录结构,我需要对它进行改造。

├── app

│ ├── Helpers.php

│ ├── Http

│ │ └── Controllers

│ └── Models

├── composer.json

└── tests复制代码我这样设置我的目录结构,并更新我的 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/"
        }
    }
}
登入後複製

复制代码这样的框架可以访问吗,显然是不行的,我们还要加一些东西让我们的框架真正可以跑起来,然后在来迭代它。

├── app

│ ├── Helpers.php

│ ├── Http

│ │ └── Controllers

│ └── Models

├── bootstrap

│ ├── app.php

│ └── autoload.php

├── composer.json

├── config

├── public

│ └── index.php

├── routers

└── tests复制代码我们将目录结构改造成这样,并编写一些启动框架的代码到相应的文件

// public/index.php

<?php
require __DIR__.&#39;/../bootstrap/autoload.php&#39;;
$app = require_once __DIR__.&#39;/../bootstrap/app.php&#39;;
$app->run();
// bootstrap/app.php
<?php
$app = new \Slim\App;
return $app;
// bootstrap/autoload.php
<?php
define(&#39;M2EZ_START&#39;, microtime(true));
require __DIR__.&#39;/../vendor/autoload.php&#39;;
登入後複製

复制代码然后运行 composer install 安装框架的依赖包,安装完成后我们的目录中就会多出一个 vendor 的目录和 composer.lock 的文件,此时运行 php -S 0.0.0.0:8080 -t public public/index.php 利用 PHP 自带的 web 服务器进行测试,为了这个命令更简单使用,我们可以将这个命令加到 composer.json 的 script 中。

此时访问 127.0.0.1:8080 或 localhost:8080 就可以看到如下的页面:

file

这说明框架正确启动了,那么我们怎么确定框架工作正常呢,这里有个简单方法:

<?php
use Slim\Http\Request;
use Slim\Http\Response;
require __DIR__.&#39;/../bootstrap/autoload.php&#39;;
$app = require_once __DIR__.&#39;/../bootstrap/app.php&#39;;
$app->get(&#39;/hello/{name}&#39;, function (Request $request, Response $response) {
    $name = $request->getAttribute(&#39;name&#39;);
    $response->getBody()->write("Hello, $name");
    return $response;
});
$app->run();
登入後複製

复制代码对 public/index.php 的代码进行修改,此时访问 http://localhost:8080/hello/dongm2ez,那么我们就会看到:

file

测试是成功了,但是我们不能把路由和逻辑都写到 index.php 文件里,因此我们需要代码更好的组织。要让我们的目录规划发挥正在的作用。

为了单独管理路由,我将路由单独写在 routers 文件夹中,在文件夹中我们新建两个 PHP 脚本文件,然后在 public/index.php 中加入两行代码:

<?php
require __DIR__ . &#39;/../bootstrap/autoload.php&#39;;
$app = require_once __DIR__ . &#39;/../bootstrap/app.php&#39;;
require __DIR__ . &#39;/../routers/web.php&#39;;
require __DIR__ . &#39;/../routers/api.php&#39;;
$app->run();
登入後複製

复制代码变成这样,这样我就可以单独管理 API 和 WEB 项目的路由了,如果有其他路由就也可以 require 更多路由。

<?php
$app->get(&#39;/&#39;, &#39;\App\Http\Controllers\WelcomeController:index&#39;);复制代码而我们的控制器长什么样呢,是这个样子的:
<?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;
    }
}
登入後複製

复制代码我们知道在现代化的框架中,容器会让我们很方便,我们的基础框架 Slim 提供一个容器的实现,当然你也可以使用其他的第三方的,那么这显然是我们想要的结果,不是只能使用框架提供的,我们可以随时换掉框架的功能,换成我们想要的同样功能组件。

使用也很简单,在 app.php 文件中初始化 Slim 框架时将容器实例传递给它就可以了。

<?php
$container = new \Slim\Container;
$app = new \Slim\App($container);
return $app;
登入後複製

复制代码还记得上面那个控制器继承的基类控制器吗,那也是我自己写的,里面可以做一些所有控制器都有可能用的的操作封装。比如我为了更方便的使用容器,我在基类里初始化了一个容器实例。

<?php
namespace App\Http\Controllers;
use Interop\Container\ContainerInterface;
abstract class Controller
{
    protected $ci;
    public function __construct(ContainerInterface $ci)
    {
        $this->ci = $ci;
    }
}
登入後複製

复制代码现在我已经有了 路由功能,有了控制器功能,还有请求响应的操作,那么作为一个完整的框架那么必须有访问数据库的方法。

我很喜欢 Laravel 提供的数据库 ORM 组件,那么我就决定使用它了,执行 composer require illuminate/database "~5.5",我选择了最新的 Laravel 长期支持版 ORM 。

我们需要此时在 config 文件夹中新添加一个文件 databases.php 文件:

<?php
return [
    &#39;settings&#39; => [
        &#39;db&#39; => [
            &#39;driver&#39; => &#39;mysql&#39;,
            &#39;host&#39; => &#39;localhost&#39;,
            &#39;database&#39; => &#39;database&#39;,
            &#39;username&#39; => &#39;user&#39;,
            &#39;password&#39; => &#39;password&#39;,
            &#39;charset&#39;   => &#39;utf8&#39;,
            &#39;collation&#39; => &#39;utf8_unicode_ci&#39;,
            &#39;prefix&#39;    => &#39;&#39;,
        ]
    ],
];
登入後複製

复制代码然后修改 public/index.php:

<?php
require __DIR__ . &#39;/../bootstrap/autoload.php&#39;;
$config = require __DIR__ . &#39;/../config/databases.php&#39;;
$app = require_once __DIR__ . &#39;/../bootstrap/app.php&#39;;
require __DIR__ . &#39;/../routers/web.php&#39;;
require __DIR__ . &#39;/../routers/api.php&#39;;
$app->run();
登入後複製

复制代码修改 bootstrap/app.php:

<?php
$container = new \Slim\Container($config);
$app = new \Slim\App($container);
// Service factory for the ORM
$container[&#39;db&#39;] = function ($container) {
    $capsule = new \Illuminate\Database\Capsule\Manager;
    $capsule->addConnection($container[&#39;settings&#39;][&#39;db&#39;]);
    $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(&#39;db&#39;);
        $user = $db->table("user")->first();
        var_dump($user);
        $response->getBody()->write("Hello, world");
        return $response;
    }
}
登入後複製

复制代码那么此时这个框架已经是一个可以开发 API 功能的框架了,如果要开发 Web 站我可能还需要加入渲染模板组件,无论是 twig、Smarty、Haml 还是 Blade,全都看你的喜好了。当然我觉得我做到这里就可以了,够我用了,因为对于前端我更喜欢用 React 或者是 Vue 去实现它。

需要更简便的操作 session、cookie 那么我们也可以添加相应的组件,各种已经有的框架了都提供这样的组件,看看你更喜欢哪一个了,现在你的框架你做主,你想添加什么就可以添加什么组件,经过这样的定制的框架一定是最符合你开发需求的。

我这里只是对已有的组件进行了配置组装,一旦哪天你发现所有的开源组件都满足不了你的需求的时候,因为你对你的框架了解,你可以自己造个轮子给自己的框架用,如果你写的好那么你也会创造出一个极好用的框架,现在最流行的 PHP 框架,你可以看看它的 composer.json 文件,它就是在前人的基础上进行开发维护的,已经有的功能他拿来直接用,觉得别人做的不完善的地方自己造一个轮子给大家用。

而且我这里也没有用到太多的设计模式,你还可以改造你的框架,利用PHP的魔术方法,反射,SPL 等等让你的框架更好,更容易扩展,更容易配置。

总结

框架很神秘吗?看过这篇文章我相信你不会这样觉得了。

造一个框架很难吗,是的很难,因为从 0 到 1 任何事都难,但是我们现在还需要从 0 到 1 吗,基本不需要了!站在巨人身上做事更容易,而且要记住,任何事只有行动起来你就会发现尝试比踌躇不前更好,从小处开始,做小事,有一天这个小事就变成了大事。不积跬步无以至千里。

Laravel 為什麼流行,因為作者本是一名.net 開發者,在使用CI 框架時萌生了想法要做一個更簡潔、靈活的框架,他的思想真的很先進嗎,不一定的,其他開發語言早就有了Laravel 中的功能,它只是在PHP 實現了它們。

以上例子其實告訴我們,不要給自己貼標籤,人生不設限,你不是PHP 程式設計師,你就是開發者,任何開發相關的東西我們都該去了解、掌握,標籤只能別人給你貼,不要自己貼。

推薦教學:《PHP教學

以上是用Composer建構屬於你的PHP框架的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

我後悔之前不知道的 7 個 PHP 函數 我後悔之前不知道的 7 個 PHP 函數 Nov 13, 2024 am 09:42 AM

如果您是經驗豐富的PHP 開發人員,您可能會感覺您已經在那裡並且已經完成了。操作

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

See all articles