用php写一个简单的框架
用习惯了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框架,需要以下几个步骤:
- 定义项目文件结构:将不同的代码放在不同的目录中,如控制器、模型、视图等。
- 编写路由类:处理URL请求并将其分配给相应的控制器和方法。
- 编写控制器类:用于处理业务逻辑和与模型交互从而提供数据给视图呈现。
- 编写模型类:用于与数据库进行交互,执行增删改查操作。可以使用MySQLi或PDO等扩展来连接MySQL8.0数据库。
- 编写视图类:负责显示输出数据到用户界面。
在处理路由时,通常会将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