• Welcome to Journal web site.

我是 PHP 程序员

- 开发无止境 -

没有了
Prev

第15章 0601-控制器类与视图类

Data: 2016-09-25 16:55:20Form: JournalClick: 1

admin.php 入口文件

<?php
// 后台入口

namespace core;

// 1. 获取到当前模块/应用的名称 , "admin"
define("APP_NAME", basename(__FILE__, '.php'));

// echo APP_NAME;

// 2. 加载MVC框架的核心类库
require __DIR__ . '/core/App.php';

// 3. 启动框架
App::run();


// echo(B::$a);


App.php

<?php

// 框架应用的基础类,用于启动框架

namespace core;

class App
{
    public static function run()
    {
        // 1. 启动会话
        session_start();

        // 2. 公共函数库
        // DIRECTORY_SEPARATOR: 目录分隔符常量, 可以自适应当前操作系统
        require __DIR__ . DIRECTORY_SEPARATOR. 'common.php';

        // 3. 设置常量
        self::setConst();

        // 4. 注册类的自动加载器
        spl_autoload_register([__CLASS__, 'autoloader']);

        // 5. 路由解析
        [$controller, $action, $params] = Router::parse();

        // 6. 实例化控制器
        // 框架中, 视图目录 与 控制器 对应 , 模板文件 与 方法 对应的
        // IndexController  ---> index 目录
        // hello -> hello.php 模板文件对应

        // 在实例化控制器类之前, 先要得到视图类的实例
        // 定义默认的视图路径的入口
        // $path = '/app/admin/view';
        $path = ROOT_APP_PATH . DIRECTORY_SEPARATOR . APP_NAME . DIRECTORY_SEPARATOR . 'view'. DIRECTORY_SEPARATOR;
        // echo $path;

        // 视图实例化
        $view =  new View($path, $controller, $action);


       
        // 首字母大写, 加上后缀: Controller
        $controller = ucfirst($controller) . 'Controller';

        $controller = 'app\\' . APP_NAME . '\\controller\\' . $controller;
        // 控制器实例化
        $controller =  new $controller($view);
        // dump($controller);

        // 调用控制器中的方法,并传入指定的参数,完成页面的渲染
        echo call_user_func_array([$controller, $action], $params);
    }

    // 设置常量
    private static function setConst()
    {
        // 1. 框架核心类库的路径常量
        define('CORE_PATH', __DIR__);

        // 2.根路径/项目路径常量: C:\Users\Administrator\Desktop\fram
        define('ROOT_PATH', dirname(__DIR__));
       
        // 3. 所有应用的入口: app/
        define('ROOT_APP_PATH', ROOT_PATH. DIRECTORY_SEPARATOR.'app');
       
        // 4. 配置常量
        // 二级配置: 项目/框架级(默认) < 应用级(自定义)
        $defaultConfig =  ROOT_PATH . DIRECTORY_SEPARATOR.'config.php';
        $appConfig =  ROOT_APP_PATH . DIRECTORY_SEPARATOR.'config.php';
        define('CONFIG', require file_exists($appConfig) ? $appConfig : $defaultConfig);

        // 5. 设置调试开关
        // php.ini
        ini_set('display_errors', CONFIG['app']['debug'] ? 'Off' : 'On');
    }

    //  自动加载器(类)
    private static function autoloader($class)
    {
        // 类文件的命名空间,应该与类文件所在的路径存在一一对应关系
        // core\Controller.php
        $file = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';

        file_exists($file) ?  require $file : die($class . ' 类文件找不到');
    }
}


common.php

<?php
// 公共函数库

namespace core;

// 快捷打印
function dump(...$data)
{
    foreach ($data as $item) {
        // true: 只返回不打印
        $result  =  var_export($item, true);
        // 自定义变量显示样式
        $style = 'border:1px solid #ccc;border-radius:5px;';
        $style .= 'background: #efefef; padding: 8px;';
        // 格化式打印
        printf('<pre style="%s">%s</pre>', $style, $result);
    }
}

// $a = 100;
// $a = 'hello';
// $a = ['hello', 'world', 'zhu'];
// dump($a);


Controller.php

<?php

// 控制器类的基类

namespace core;

class Controller
{
    // 视图对象
    protected View $view;

    // 构造器
    public function __construct(View $view)
    {
        $this->view = $view;
    }
}


Db.php

<?php

// 数据库操作入口类
namespace core;

use PDO;

class Db
{

    // 连接对象
    protected static PDO $db;

    // 连接数据库, 创建PDO对象
    protected static function connect(string $dsn, string $username, string $password)
    {
        self::$db =   new PDO($dsn, $username, $password);
    }

    public static function __callStatic(string $name, array $argc)
    {

        // 1. 连接数据库
        $dsn = CONFIG['database']['type']. ':dbname='. CONFIG['database']['dbname'] . '; host=' . CONFIG['database']['host'];
        dump($dsn);
        $username = CONFIG['database']['username'];
        $password = CONFIG['database']['password'];

        static::connect($dsn, $username, $password);

        // 2. 将数据库所有的操作, 全部重定义到别一个类: Query.php
        $query = new Query(static::$db);
        return  call_user_func_array([$query, $name], $argc);
    }
}


Query.php

<?php
//数据查询
namespace core;

use PDO;

class Query
{
    protected PDO $db;
    protected string $table;
    protected string $field;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    // 获取当前数据表名称
    public function table(string $table) : self
    {
        $this->table = $table;
        return $this;
    }

    // 设置字段
    public function field(string $field = '*') : self
    {
        $this->field = $field;
        return $this;
    }

    // 获取全部数据
    public function select()
    {
        $sql = 'SELECT ' . $this->field . ' FROM ' . $this->table;

        echo $sql;

        $stmt = $this->db->prepare($sql);
     
        if ($stmt->execute()) {
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } else {
            print_r($stmt->errorInfo());
        }
    }
}


Router.php

<?php
// 路由类

namespace core;

use function core\dump;

class Router
{
    public static function parse() :array
    {
        // 从URL中,解析出:控制器, 方法, 参数

        // 默认控制器,方法和参数
        $controller = CONFIG['app']['default_controller'];
        $action = CONFIG['app']['default_action'];
        $params = [];

        // 判断是否存在 pathinfo

        if (array_key_exists('PATH_INFO', $_SERVER) && $_SERVER['PATH_INFO'] !== '/') {
            // dump($_SERVER['PATH_INFO']);
            // dump(array_filter(explode('/', $_SERVER['PATH_INFO'])));
            $pathinfo = array_filter(explode('/', $_SERVER['PATH_INFO']));
            // dump($pathinfo);

            if (count($pathinfo) >= 2) {
                $controller = array_shift($pathinfo);
                $action = array_shift($pathinfo);
                $params = $pathinfo;
            } else {
                $controller = array_shift($pathinfo);
            }
        }

 
        // dump([$controller, $action, $params]);
        return [$controller, $action, $params];
    }
}


View.php

<?php

// 视图类的基类

namespace core;

class View
{
    // 视图默认目录
    protected string $defaultPath;

    // 当前控制器: 视图目录
    protected string $controller;

    // 当前控制器中的方法: 模板文件
    protected string $action;

    // 模板变量容器
    protected array $data = [];

    public function __construct(string $path, string $controller, string $action)
    {
        $this->defaultPath = $path;
        $this->controller = $controller;
        $this->action = $action;
    }

    // 模板赋值
    public function assign($key, $value)
    {
        if (is_array($value)) {
            $this->data = array_merge($data, $this->data) ;
        }
        $this->data[$key] = $value;
    }


    // 模板渲染
    public function render(string $path = null, array $data = null)
    {
        // 允许模板赋值与模板渲染同步完成
        // 考虑到原有模板变量数组中可能已有值,所以不能清空,只能合并
        $this->data =  $data ? array_merge($data, $this->data) : $this->data;

        // 如果没有传入自定义模板路径,就使用默认方法来生成: 控制器/视图.php
        $file = $path ?? $this->controller . DIRECTORY_SEPARATOR . $this->action;
        $file = $file . '.' . CONFIG['app']['default_view_suffix'];
        $file = $this->defaultPath . $file;
        // dump($file);

        // 模板赋值
        extract($this->data);

        // 渲染模板
        file_exists($file) ? include $file : die('模板不存在');
    }
}


Name:
<提交>