您当前的位置: 首页  >  博文日记

用php写一个简单的框架

作者:总管理员 时间:2023-03-31 22:23:47 阅读数:862人阅读

用习惯了laravel框架的优雅便利,是否也想写一个自己的框架呢?今天我们来写一个最简单的php框架,以便于理解框架的原理。

首先,创建一个称为“myframework”的文件夹,并在其中创建以下文件:

index.php:框架的入口文件

core.php:包含框架的核心代码

config.php:包含框架的基本配置

在index.php文件中,将载入核心和配置文件:

<?php

require_once 'core.php';
require_once 'config.php';

$app = new App();
$app->run();

在config.php文件中,定义一些基本的配置:

<?php

$config = array(
    'db_host' => 'localhost',
    'db_user' => 'root',
    'db_pass' => '',
    'db_name' => 'mydb'
);

在core.php文件中,定义框架的核心类:

<?php

class App {
    private $db;

    public function __construct() {
        global $config;

        // 连接数据库
        $this->db = new mysqli($config['db_host'], $config['db_user'], $config['db_pass'], $config['db_name']);

        if ($this->db->connect_error) {
            die('连接数据库失败:' . $this->db->connect_error);
        }
    }

    public function run() {
        // 处理请求
    }

    public function __destruct() {
        $this->db->close();
    }
}

在run()方法中,可以处理请求。例如,如果需要处理“/hello”路由,可以添加以下代码:

<?php

public function run() {
    switch ($_SERVER['REQUEST_URI']) {
        case '/hello':
            echo 'Hello, world!';
            break;
        default:
            echo 'Error 404';
            break;
    }
}

最后,访问http://localhost/myframework/hello即可看到输出“Hello,world!”。

这只是一个简单的示例框架,可以根据需求进行扩展和优化。

比如,我们要加入路由和controller的处理,可以这样修改。

首先config.php中这样写:

<?php

$config = array(
    'db_host' => 'localhost',
    'db_user' => 'root',
    'db_pass' => '',
    'db_name' => 'mydb',
    'routes' => array(
        '/' => 'HomeController@index',
        '/about' => 'AboutController@index',
        '/contact' => 'ContactController@index'
    )
);

在run()方法中处理路由:

<?php

public function run() {
    global $config;

    $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

    foreach ($config['routes'] as $route => $handler) {
        if ($uri == $route) {
            $parts = explode('@', $handler);
            $controller = $parts[0];
            $method = $parts[1];

            require_once 'controllers/' . $controller . '.php';
            $instance = new $controller();
            $instance->$method();
            return;
        }
    }

    echo 'Error 404';
}

在controller文件夹中创建控制器:

<?php

class HomeController {
    public function index() {
        echo 'Hello, world!';
    }
}

class AboutController {
    public function index() {
        echo 'About us';
    }
}

class ContactController {
    public function index() {
        echo 'Contact us';
    }
}

这样就可以通过路由访问不同的控制器和方法了,例如访问/about,会输出“About us”,访问/index时,输出"Contact us"等。

web程序离不开数据库,接下来我们还可以加入db类的处理。

在core.php中添加db类:

<?php

class DB {
    private $conn;

    public function __construct() {
        global $config;

        // 连接数据库
        $this->conn = new mysqli($config['db_host'], $config['db_user'], $config['db_pass'], $config['db_name']);

        if ($this->conn->connect_error) {
            die('连接数据库失败:' . $this->conn->connect_error);
        }
    }

    public function query($sql) {
        $result = $this->conn->query($sql);

        if (!$result) {
            die('SQL执行失败:' . $this->conn->error);
        }

        return $result;
    }

    public function __destruct() {
        $this->conn->close();
    }
}

在控制器中使用db类:

<?php

class HomeController {
    public function index() {
        $db = new DB();
        $result = $db->query('SELECT * FROM users');

        while ($row = $result->fetch_assoc()) {
            echo $row['name'] . '<br>';
        }
    }
}

这样就可以通过db类处理数据库了,例如在HomeController的index方法中,通过$db->query()方法执行SQL语句查询users表并输出其中的name字段。

不过,这样的db类也太low,用习惯了的laravel的db觉得这样太难用了。我们可仿照laravel改善一下db类,连接方式也改用主流的pdo方式。

修改core.php中的代码:

<?php

class DB {
    private $pdo;
    private $table;
    private $columns = array('*');
    private $wheres = array();

    public function __construct() {
        global $config;

        $dsn = 'mysql:host=' . $config['db_host'] . ';dbname=' . $config['db_name'];
        $user = $config['db_user'];
        $pass = $config['db_pass'];

        try {
            $this->pdo = new PDO($dsn, $user, $pass);
        } catch (PDOException $e) {
            die('连接数据库失败:' . $e->getMessage());
        }
    }

    public function table($table) {
        $this->table = $table;

        return $this;
    }

    public function select($columns = array('*')) {
        $this->columns = $columns;

        return $this;
    }

    public function where($column, $operator, $value) {
        $this->wheres[] = array(
            'type' => 'basic',
            'column' => $column,
            'operator' => $operator,
            'value' => $value,
            'boolean' => 'and'
        );

        return $this;
    }

    public function get() {
        $sql = $this->compileSelect();

        return $this->query($sql);
    }

    private function compileSelect() {
        $sql = 'SELECT ' . implode(',', $this->columns) . ' FROM ' . $this->table;

        if (!empty($this->wheres)) {
            $sql .= ' WHERE ' . $this->compileWheres();
        }

        return $sql;
    }

    private function compileWheres() {
        $wheres = array();

        foreach ($this->wheres as $where) {
            $type = $where['type'];
            $column = $where['column'];
            $operator = $where['operator'];
            $value = $where['value'];
            $boolean = $where['boolean'];

            switch ($type) {
                case 'basic':
                    $wheres[] = $column . ' ' . $operator . ' ?';
                    break;
            }
        }

        return implode(' ' . $boolean . ' ', $wheres);
    }

  private function query($sql = '')
    {
        $stmt = $this->handler->query($sql);
        $stmt->setFetchMode(\PDO::FETCH_NUM);
        $list = $stmt->fetchAll();
        return $list;
    }
   
}

注意,为了安全和便捷操作,我们建议安装laravel的查询构造器:

composer require illuminate/database

创建一个实例:

use Illuminate\Database\Capsule\Manager as Capsule;

// 初始化 Eloquent ORM
$capsule = new Capsule;
$capsule->addConnection([
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'database_name',
    'username'  => 'database_user',
    'password'  => 'database_password',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
]);

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

// 创建查询构造器实例
$queryBuilder = $capsule->getConnection()->table('table_name');

在index.php文件中可进行查询操作:

<?php 
date_default_timezone_set("PRC");
 
require 'vendor/autoload.php';
require 'database.php';
 
use Illuminate\Database\Capsule\Manager as DB;
 
$article = DB::table('article')->where('author', '月光光')->first();
echo $article->title;

总结:编写一个MVC架构的PHP框架,需要以下几个步骤:

  1. 定义项目文件结构:将不同的代码放在不同的目录中,如控制器、模型、视图等。
  2. 编写路由类:处理URL请求并将其分配给相应的控制器和方法。
  3. 编写控制器类:用于处理业务逻辑和与模型交互从而提供数据给视图呈现。
  4. 编写模型类:用于与数据库进行交互,执行增删改查操作。可以使用MySQLi或PDO等扩展来连接MySQL8.0数据库。
  5. 编写视图类:负责显示输出数据到用户界面。

在处理路由时,通常会将URL映射到相应的控制器和动作方法。以下是一些常见的处理路由的方法:

1. 基于文件路径:PHP可以使用文件路径来处理路由。例如,如果请求URL为"/products/view/123",则可以将其映射到"/products/view.php"文件,并将"123"作为参数传递给该文件中的控制器。

2. 基于正则表达式:PHP还可以使用正则表达式来匹配URL并将其映射到相应的控制器和动作方法。例如,可以使用类似"^/products/(\d+)$"的正则表达式来匹配"/products/123"这样的URL,并将"123"作为参数传递给相应的控制器和动作方法。

3. 基于框架:许多PHP框架都提供了自己的路由系统,例如Laravel、Symfony等。这些框架通常使用配置文件或注释来定义路由规则,并将URL映射到相应的控制器和动作方法。

4. 手动处理:有些开发者选择手动处理路由,即在代码中编写条件语句来检查请求URL并调用相应的控制器和动作方法。虽然这种方法灵活性较高,但也需要更多的工作量和时间。

在简单的系统中,可使用下面的方法:

function handleRequest($requestMethod, $requestPath) {
    switch($requestMethod) {
        case 'GET':
            switch($requestPath) {
                case '/':
                    echo "Hello, World!";
                    break;
                case '/about':
                    echo "This is the about page.";
                    break;
                default:
                    http_response_code(404);
                    echo "Page not found";
            }
            break;
        case 'POST':
            // Handle POST requests here
            break;
        default:
            http_response_code(405);
            echo "Method not allowed";
    }
}

记录完毕。

本站所有文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱: 2554509967@qq.com

标签: php

需要 登录 才能发表评论
热门评论
0条评论

暂时没有评论!