Compoer 手撸一个 MVC框架

August 29, 2019 · PHP · 35次阅读

今天呢,小弟用Composer手撸一个MVC框架

随着PHP标准和Composer包管理工具的面世,普通开发者撸一个框架已经不再是什么难事了。
无论是路由管理、ORM管理、还是视图渲染都有许许多多优秀的包可以使用。我们就像堆积木一样把这些包用composer一个个堆积起来。
接下来我们便是简单地实现一个MVC框架,来加深我们对框架的理解。
不过MVC都已经被人玩烂了,现在大点的项目都是 5层模型,在MVC层加了 Repositories(数据仓库层)、Services(服务层)。这些东西呢,我会在以后的找个时间写写吧。

下面我们就按步骤来开始撸,Composer要是不懂的话,建议在去学一学

    1. 首先找个空白目录,你有两种选择

      -第一种运行下面的命令生成composer.json的文件

      composer init

      -第二种手动创建一个 composer.json的文件把我下面的代码复制上去

      {

    "name": "xiaowang/zhang",
    "description": "this my dd",
    "authors": [{

           "name": "zhangsan",
           "email": "123@qq.com"
       }],

    "require": {}
    }

    1. 整好上面这一步之后呢,我先来第一个包
      安装第一个包

    我们接下来安装一个管理路由的包: noahbuscher/macaw。 功能比这个更加强大的路由包有很多,但是为了简单起见,我们选择安装这个包。

    1. require noahbuscher/macaw

    安装之后当前目录结构为:

    ➜ demo tree
    .
    ├── composer.json
    ├── composer.lock
    └── vendor

    ├── autoload.php
    ├── composer
    │   ├── ClassLoader.php
    │   ├── LICENSE
    │   ├── autoload_classmap.php
    │   ├── autoload_namespaces.php
    │   ├── autoload_psr4.php
    │   ├── autoload_real.php
    │   ├── autoload_static.php
    │   └── installed.json
    └── noahbuscher
        └── macaw
            ├── LICENSE.mddeepin 鉴定故障
            ├── Macaw.php
            ├── README.md
            ├── composer.json
            ├── composer.lock
            └── config
                ├── Web.config
                └── nginx.conf
    

    public/index.php (创建入口文件)
    我们在根目录下新建一个public文件夹,并在该文件夹下新建 index.php。index.php 文件类似于一个大厦的入口,我们所有的请求都运行 index.php。
    下面是 index.php 文件的代码:

    // 自动加载vendor目录下的包require '../vendor/autoload.php';

    web.php (创建路由文件)
    此时我们观察 index.php,除了把vendor下面的包都 require 进来了外,其他啥都没干。那么如何响应各种各样的请求呢?
    我们需要定义路由。路由就有点像快递分拣站,把写着不同地址的请求分拨给不同的控制器处理。
    那么我们在根目录下创建一个 routes 文件夹,并在该文件夹下创建 web.php 文件。文件内容:

    <?php
    //引入路由类
    use NoahBuscher\Macaw\Macaw;
    //创建第一条路由 
    Macaw::get('hello', function () {
        echo "hello world";    
    });
    Macaw::dispatch();
    

    之后到public/index.php 引入路由文件上加上这句代码:

        require_once '../routes/web.php';
    

    然后我们启动php内置的开发服务器:

    cd public
    php -S localhost:8001

    我们访问 http://localhost:8001/hello 就能看到我们预期的 "hello world".

    MVC

    上面我们仅仅实现了访问一个地址,返回一个字符串。下面我们来真正搭建MVC框架。MVC其实就是Model、View、Controller三个的简称。
    不管怎么样,我们先在根目录新建app文件之后再建三个文件夹再说,即 views、models、controllers。
    新建 controllers/HomeController.php 文件,代码如下:

    <?php
    namespace AppControllers;
    use AppModelsArticle;
    class HomeController {

    public function home()
    {
      echo "<h1>This is Home Page</h1>";
    }

    }

    另外我们在 routes/web.php 中添加一条路由:
    Macaw::get('', 'App\Controllers\HomeController@home');

    整体代码为:
    <?php
    use NoahBuscherMacawMacaw;

    Macaw::get('hello', function () {

    echo "hello world";

    });

    Macaw::get('', 'App\Controllers\HomeController@home');

    Macaw::dispatch();

    此时已经绑定了一个路由至我们一个控制器的方法,但是我们去访问 http://localhost:8001 会出现 Uncaught Error: Class 'AppControllersHomeController' not found in 的错误。
    为什么呢?
    因为此时我们还并没有将控制器加载进来,程序并不知道控制器在哪儿。我们可以用 composer 的 classmap 方法加载进来。修改 composer.json 中添加:

    "autoload": {

    "classmap": [
      "app/controllers",
      "app/models"
    ]

    }

    我们顺便把models也加载进来。运行以下

    composer dump-autoload
    刷新自动加载

    View

    这时候我们来整V层吧,也就是视图层,因为你HTML代码不可能都写到控制器里吧。我这里就简单实现一下,如果老哥们做的话可以用上模板引擎。

    下面我们先在view 目录新建一个home.php 的文件。
    代码如下:
    <?php

    echo "<h1>".$aa."</h1>";
    

    然后在控制器里引入视图文件代码如下:
    <?php
    namespace AppControllers;

    use AppModelsArticle;
    class HomeController {

    
    public function home()
    {
      echo "<h1>This is Home Page</h1>";
      
      $aa = "我是帅哥";
      require dirname(__FILE__).'/../views/home.php';
    }
    

    }
    这样我们的视图层就做好了,之后呢,就差M层了,M层的话要对数据哭相对复杂的操作,所以,我们用orm

    ORM

    我们一路从一个空文件夹开始,打造一个自己的一个框架,感觉并没有写多少代码,唯一感觉比较麻烦的就是连接数据库来查询数据了。我们我们有很多 Model,要实现 增删改查的话,我们岂不是要重复 连接,查询、插入、删除、更新,然后关闭连接?我们应该把这些功能分装一下。
    怎么封装?有其他人写好的包了,直接拿来用吧~ 当然如果你想自己造轮子的话,也可以自己实现一下。
    我们这里使用 illuminate/database:

    composer require illuminate/database

    然后我们在 public/index.php 中引入:

    <?php

    use Illuminate\Database\Capsule\Manager as Capsule;
    require '../vendor/autoload.php';
    // Eloquent ORM
    $capsule = new Capsule();
    $capsule->addConnection(require '../config/database.php');
    $capsule->bootEloquent();
    //路由配置require '../routes/web.php';
    

    我们在连接数据的时候,使用了根目录新建 config/database.php 的数据库配置文件。

    <?php
    return [

    'driver' => 'mysql',
    'host' => 'localhost', //地址
    'database' => 'demo_database', //库名
    'username' => 'root',//用户名
    'password' => 'secret',//密码
    'charset' => 'utf8',
    'collation' => 'utf8_general_ci',
    'prefix' => ''

    ];

    接下来我们就可以新建 models/User.php的模型类,而该类仅仅需要继承IlluminateDatabaseEloquentModel 来使用 Eloquent ORM 的功能:
    User 代码如下:

    <?php
    namespace AppModels;
    use IlluminateDatabaseEloquentModel;

    class User extends Model{

    public $timestamps = false;
    protected $table = 'user'; //表名

    }

    之后我在控制调用就好了控制器代码如下:

    <?php
    namespace AppControllers;
    use AppModelsUser;

    class HomeController {

    
    public function home()
    {
      echo "<h1>This is Home Page</h1>";
      //获取到User表的一条数据composer dump-autoload
      $user = User::first();
    
      var_dump($user->name);
      $aa = "我是帅哥";
      //引入视图
      require dirname(__FILE__).'/../views/home.php';
    }

    }

    如果报错说User类不存在的话运行下:,

    composer dump-autoload

    更多Eloquent ORM的功能,您也可以自己查阅文档。
    这样我们简单 MVC框架就整完了。

    总结

    好了,我们一个 MVC 框架基本上就搭建完了,我们回头看一下整个框架目录结构,是不是跟 Laravel 有点像呢?
    .
    ├── README.md
    ├── app
    │   ├── controllers
    │   │   └── HomeController.php
    │   ├── models
    │   │   └── Article.php
    │   └── views
    │   └── home.php
    ├── composer.json
    ├── composer.lock
    ├── config
    │   └── database.php
    ├── public
    │   └── index.php
    ├── routes
    │   └── web.php
    └── vendor ...

    其实,MVC也被玩烂了很老的东西啦,都9012年了,现在复杂的业务都是分5层的,分别是:

    1. M Models 模型层
    2. V Views 视图层
    3. C Controllers 控制器层
    4. R Repositorys 数据仓库层
    5. S Servers 服务层

    这东西的话,可能会在另外一篇博客里写出来吧

    喝杯水

    标签:PHP

    最后编辑于:2019/09/01 23:00

    添加新评论

    控制面板