PHP MVC框架开发(上)

实践学习php,thinkphp,Redis,vue,uni-app等技术,推荐开源电商系统likeshop,可以借鉴思路,可去版权免费商用,gitee下载地址:
点击进项目地址

定义入口文件

  • 定义常量
  • 引入库函数
  • 引入核心模块

image-20210401161012543

完成自动加载

入口文件 index.php

<?php

// door file

// define system const
define('LSPHP', __DIR__ . "/");
define('APP', __DIR__ . "/app");
define('CORE', __DIR__ . "/core");


//define debug
define('APP_DEBUG',true);

if (APP_DEBUG) {
    ini_set('display_errors', 'On');
} else {
    ini_set('display_errors','Off');
}


// include core func file
include CORE . '/common/function.php';
// test
// p("1234");


// include core class file
include CORE . "/lsphp.php";
// test
// \core\lsphp::run();


// 实现类加载,注册加载函数
spl_autoload_register('\core\lsphp::load');

\core\lsphp::run();

自动加载 lsphp.php

<?php
    
namespace core;

class lsphp
{

    public static $classMap = [];

    public static function run()
    {
        $route = new \core\route();
    }

    // 实现自动加载
    public static function load($class)
    {
        if (isset(self::$classMap[$class])) {
            return true;
        } else {
            $filepath=str_replace('\\','/',$class);
            $filepath=LSPHP.$filepath.'.php';
            if(is_file($filepath))
            {
                require $filepath;
                self::$classMap=$filepath;
            }else{
                return false;
            }
        }
    }
}

route.php

<?php
namespace core;

class route
{
    public function __construct()
    {
        echo 'route';
    }
}

路由类

.htaccess

.htaccess 文件是 apache 服务器中的一个配置文件,她负责相关目录下的网站配置,通过 htaccess 文件,可以实现:

  • 网页301重定向
  • 自定义404错误页面
  • 改变文件扩展名
  • 允许/阻止特定的用户或者目录的访问
  • 禁止目录列表
  • 配置默认文档等功能
<IfModule mod_rewrite.c>
    # 打开Rerite功能
    RewriteEngine On

    # 如果请求的是真实存在的文件或目录,直接访问
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    # 如果访问的文件或目录不是真事存在,分发请求至 index.php
    RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>
explode

explode — 使用一个字符串分割另一个字符串

explode ( string $delimiter , string $string [, int $limit ] ) : array

此函数返回由字符串组成的数组,每个元素都是 string 的一个子串,它们被字符串 delimiter 作为边界点分割出来

和 python 的 split 函数功能相同

trim

trim — 去除字符串首尾处的空白字符(或者其他字符)

trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] ) : string

此函数返回字符串 str 去除首尾空白字符后的结果。如果不指定第二个参数,trim() 将去除这些字符:

  • " " (ASCII 32 (0x20)),普通空格符
  • “\t” (ASCII 9 (0x09)),制表符
  • “\n” (ASCII 10 (0x0A)),换行符
  • “\r” (ASCII 13 (0x0D)),回车符
  • “\0” (ASCII 0 (0x00)),空字节符
  • “\x0B” (ASCII 11 (0x0B)),垂直制表符

和 python 的 strip 函数功能相同

array_slice

array_slice — 从数组中取出一段

array_slice ( array $array , int $offset [, int $length = NULL [, bool $preserve_keys = false ]] ) : array

array_slice() 返回根据 offsetlength 参数所指定的 array 数组中的一段序列

<?php
$input = array("a", "b", "c", "d", "e");

$output = array_slice($input, 2);      // returns "c", "d", and "e"
$output = array_slice($input, -2, 1);  // returns "d"
$output = array_slice($input, 0, 3);   // returns "a", "b", and "c"
实现

实现类似于 think PHP 那样的效果,将 url 中的参数分别取出

index.php/模块/控制器/操作/参数/#index.php 作为入口文件,所以后端要将传来的 url 进行分割取值

因为没有设置路由映射,我的网站 url 为:

http://localhost/demo/develop/index.php

# $_SERVER['REQUEST_URI'] = "/demo/develop/index.php"

数组下标从 0 开始

# route.php

<?php

namespace core\lib;

class route
{
    // 默认控制器和操作
    public $ctrl = "index";
    public $action = "index";
    public $param = [];

    public function __construct()
    {
        if (isset($_SERVER['REQUEST_URI'])) {
            $pathString = $_SERVER['REQUEST_URI'];
            $path_arr = explode('/', trim($pathString, '/'));
            // $path_arr='/demo/develop/index.php/index/index/param/222'
        }

        if (isset($path_arr[2]) && ($path_arr[2]) == "index.php") {
            $path_arr = array_slice($path_arr, 3, count($path_arr) - 2);
             p($path_arr);
            // $path_arr='index/index/param/222'
        }

        if (isset($path_arr[0])) {
            // 取控制器
            if (isset($path_arr[0])) {
                $this->ctrl = $path_arr[0];
            }
        }

        // 取操作
        if (isset($path_arr[1])) ;
        {
            $this->action = $path_arr[1];
        }

        // 取参数,因为参数是在数组下标 2 开始
        $i = 2;
        $count = count($path_arr);
        while ($i < $count) {
            if (isset($path_arr[$i + 1])) {
                $this->param[$path_arr[$i]] = $path_arr[$i + 1];
            }
            $i=$i+2;
        }

        p($this->ctrl);
        p($this->action);
        p($this->param);
    }
}

image-20210402150320504

控制器

加载控制器

定义好控制器文件

image-20210402194510725

# indexController.php<?php

namespace app\controller;

class IndexController
{
    public function index()
    {
        echo 'hello index';
    }
}

在 lsphp.php 文件中去定义加载功能

......    
	public static function run()
    {
        $route = new \core\lib\route();

        // 加载控制器
        $ctrl = $route->ctrl;
        $action = $route->action;

        $controllerFile = APP . "/controller/" . $ctrl . "Controller.php";
        $controllerClass="\\app\\controller\\".$ctrl."Controller";
        // 命名空间 \\ $ctrl(index)Controller

        if (is_file($controllerFile)) {
            require $controllerFile;
            $controller = new $controllerClass;
            $controller->$action();

        } else {
            throw new \Exception("controller not found!");
        }
    }
......

image-20210402194808127

数据库

新建数据库,表

image-20210402200220261

初始化连接

image-20210402200437526

db.php

使用 pdo 来实现,数据库配置连接

<?php

namespace core\common;

class db extends \PDO
{
    public function __construct()
    {
        $dsn = 'mysql:host=localhost;dbname=lsphp';
        $username = 'root';
        $password = 'root';
        try {
            parent::__construct($dsn, $username, $password);
        } catch (\Exception $e) {
            echo $e->getMessage();
        }
    }
}
数据查询函数
# indexController.php  
......
	public function query()
    {
        $db = new \core\common\db();
        $sql = "select * from ls_user";
        $data = $db->query($sql);
        p($data);
        p($data->fetchAll());
    }
......

index控制器 query操作

image-20210402202044746

视图

extract

(PHP 4, PHP 5, PHP 7)

extract — 从数组中将变量导入到当前的符号表

extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] ) : int

本函数用来将变量从数组中导入到当前的符号表中

检查每个键名看是否可以作为一个合法的变量名,同时也检查和符号表中已有的变量名的冲突

就是把一个键值对作为一个变量,键名为变量名,键值为变量值

image-20210403103510105

# render.php

<?php

namespace core;

class render
{
    public $param = [];

    // 传参数函数
    public function assign($name, $value)
    {
        $this->param[$name] = $value;
    }

    // 控制传到那个视图中去
    public function display($view)
    {
        $viewPath=APP."/view/".$view.".html";

        if(is_file($viewPath))
        {
            extract($this->param);
            include $viewPath;
        }else{
            echo "view is not found";
            exit();
        }
    }
}

# indexController.php
<?php

namespace app\controller;

class IndexController extends \core\render
    # 需要继承 render
{
    public function render()
    {
        $this->assign("title","ocean");
        $this->assign("content",'test');
        $this->display("index");
    }
}
# index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>

<h2>
    <?php echo $title ?>
</h2>
<p>
    <?php echo $content ?>
</p>
</body>
</html>

效果如下

image-20210403103643467

其他类

配置类

为了实现代码简介,将代码按功能进行划分,将配置文件单独存放,也方便修改

image-20210403203300498

两个配置文件作为示例

# db_config.php
<?php
return array (
    "dsn" => 'mysql:host=localhost;dbname=lsphp',
    "username" => 'root',
    "password" => 'root',
);
# route_config.php
<?php
return array(
    "1"=>"one",
    "2"=>"two",
    "3"=>"three"
);

\core\conf.php 去加载配置类

# \core\conf.php
<?php
// 获取加载配置config信息的函数
namespace core;

class conf
{
    # 获取一条信息
    public static function get($name, $file)
    {
        $fileName = CONFIG . "/$file" . ".php";
        if (is_file($fileName)) {
            $conf = include $fileName;
            if (isset($conf[$name])) {
                return $conf[$name];
            }else{
                throw new \Exception("not found config name!");
            }
        } else {
            throw new \Exception("not found file!");
        }
    }

    # 获取全部信息
    public static function all($file)
    {
        $fileName = CONFIG . "/$file" . ".php";
        if (is_file($fileName)) {
            $conf = include $fileName;
            return $conf;
        } else {
            throw new \Exception("not found file!");
        }
    }
}

因为使用了 CONFIG 常量,需要提前定义好

# index.php
define("CONFIG",__DIR__."/config");

这样的话就可以把数据库配置文件单独存放在 config 文件里

以下调用数据

# \core\common\db.php
class db extends \PDO
{
    public function __construct()
    {
        $db_config=\core\conf::all('db_config');
        $dsn=$db_config['dsn'];
        $username=$db_config['username'];
        $password=$db_config['password'];
        .....
            
# 单个调用            
    public function getroute(){
        $route= \core\conf::get("1",'route_config');
        p($route);            
日志类

记录操作步骤

添加 LOG 常量

# index.php
header("Content-type:text/html;charset=utf-8");
// 因为要返回中文,如果有乱码设置header头

define('LOG', __DIR__ . "/log");
# \core\log.php 日志记录文件

<?php
namespace core;

class log
{
    public function log($message)
    {
        ini_set('data.timezone', 'Asia/Beijing');
        $log_dir = LOG . '/' . date('Ymd');
        if (!is_dir($log_dir)) {
            if (mkdir($log_dir)) {

            } else {
                throw new \Exception("log file create error");
            }
        }

        $log_file = $log_dir . '/' . date('Hi');
        // H 表示 24小时,i 表示 60分钟
        if (!is_file($log_file)) {
            if(!file_put_contents($log_file,$message.PHP_EOL,FILE_APPEND)){
                // 文件名,文件内容.php换行(\n),写入方式:追加写入
            }else{
                throw new \Exception("log content write error");
            }
        }
    }
}

调用

# indexController.php
	public function log()
    {
        $log = new \core\log();
        $log->log("this is a test log");
        echo 'ok';
    }

会在 log 目录下生成文件

image-20210403215333629

}
}

    $log_file = $log_dir . '/' . date('Hi');
    // H 表示 24小时,i 表示 60分钟
    if (!is_file($log_file)) {
        if(!file_put_contents($log_file,$message.PHP_EOL,FILE_APPEND)){
            // 文件名,文件内容.php换行(\n),写入方式:追加写入
        }else{
            throw new \Exception("log content write error");
        }
    }
}

}


调用

```php
# indexController.php
	public function log()
    {
        $log = new \core\log();
        $log->log("this is a test log");
        echo 'ok';
    }

会在 log 目录下生成文件

[外链图片转存中…(img-cRCaGCrT-1617458110476)]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OceanSec

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值