主要内容:
- 对象的三种加载类型
- composer的自动加载功能(通过json文件的映射等),也分三种
- composer安装并使用第三方组件或依赖库(一个验证码组件的使用)
- 自己搭建一个简单的框架(感觉没有看出来有啥用处,或者自己还不太懂吧)
1. 加载的三种类型
- 首选创建下引用对象,app目录下的controller目录下的User.php文件
<?php
namespace app\controller;
// 1. 类的命名空间与当前类文件的路径完全一致
// 2. 类名称与类文件的名称完全一致
// 4. 此时, 这个类就符合了PSR-4规范
class User
{
public static function hello()
{
return __METHOD__;
}
}
- 然后了解三种加载方式
1-1. 常规的传统加载
<?php
// 1. 传统方式: include / require
// 加载类文件
require 'app/controller/User.php';
// 注册类别名[可选]
use app\controller\User;
// 调用类成员
echo User::hello();
1-2. 自动注册加载(spl_autoload_register)
- 然后通过设置path,并将路径转化为字符串等来进行加载
<?php
// 2. 注册自动加载函数
// 加载类文件使用一个内置的函数来完成
spl_autoload_register(function($class){
// 获取类的路径名称
$path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
// 生成一个完整的类文件名
$classFile = __DIR__ . '/' . $path . '.php';
// 加载类文件
require $classFile;
});
// 注册类别名[可选]
use app\controller\User;
// 调用类成员
echo User::hello();
1-3. 用composer自动加载
- 这块的一些注意事项
- 创建json文件及vendor目录等
-> 在json文件中进行对象映射
-> 在文件中快捷使用。具体见整个第二部分
2. 用composer自动加载
2-1. 创建json文件及vendor目录等
- 快速创建的方式是建立一个composer.json空文件(里面就一个{})
- 然后用命令composer install即可创建verdor及下面的autoload.php文件
2-2. 在json文件中进行对象映射
- 这里有一个不断优化的过程,最后的方式是psr-4模式。
- 第一种:直接的files模式。例如所有的路径及文件名。
- 这种有一个缺点就是有多少文件就要列多少,哪怕路径是一样的。
{
"autoload": {
"files": [
"app/controller/User.php",
"lib/Order.php",
"lib/Goods.php"
]
}
}
- 第二种:classmap模式。到目录即可,里面不进行展开。
- 这种依然有缺点,但具体是什么也忘记了,后面慢慢琢磨吧,有无可能是一个类中有多个方法?
- composer.json: autoload: classmap: 类映射 , 实现类的批量注册
{
"autoload": {
"classmap": [
"app/controller",
"lib"
]
}
}
- 第三种:psr-4模式。
- autoload: psr-4: 类的命名空间: 类所在的路径目录 进行绑定。命名空间最后必须以”\“空间分隔符结尾。等于前面的部分显示命名空间,后面才是类所在的目录。
{
"autoload": {
"psr-4": {
"app\\controller\\": "app/controller",
"phpcn\\": "lib"
}
},
"require": {
"gregwar/captcha": "^1.1"
}
}
以上所有的三种方法中需要注意:
- composer.json: autoload: files: 可以加载任意位置的类文件
- 注册完成之后, 在终端执行命令(这点很关键关键): composer dump-autoload(中间的-可以省略掉), 使files字段生效
- 只要是composer.json中的”autoload”字段的内容发生变化, 就必须执行composer dumpautoload让它生效
2-3. 在文件中快捷使用
<?php
// 调用的是composer中的自动加载功能
require_once __DIR__ . '/vendor/autoload.php';
// 注册类别名[可选]
use app\controller\User;
use phpcn\Order;
// 调用类成员
echo User::hello();
echo '<hr>';
// 调用lib/Order::hello()
echo Order::hello();
3. 如何在项目中使用第三方的依赖库/组件
- 一个验证码组件的使用
<?php
// 1. composer require gregwar/captcha
// 2. 更新composer.json中的require字段
// 3. 下载包到vendor对应的目录下面
// 4. 剩下就看组件包的用户手册
// composer自动加载器
require_once __DIR__.'/vendor/autoload.php';
// 注册类
use Gregwar\Captcha\CaptchaBuilder;
// 创建验证器类实例/对象
$captcha = new CaptchaBuilder;
$captcha
->build()
->save('out.jpg')
;
// 服务器端获取到验证码
$_SESSION['phrase'] = $captcha->getPhrase();
// 查看验证码,这块查看的目的是跟图片中的进行对照,看是否一致。
// 后面要真实使用的话,肯定是需要进行验证码的匹对,然后是否允许通过:
echo '验证码是: ' , $_SESSION['phrase'];
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h3>用户登录</h3>
<div>
<label for="">邮箱:</label>
<input type="email" name="" id="">
</div>
<div>
<label for="">密码:</label>
<input type="password" name="" id="">
</div>
<div>
<label for="">验证码:</label>
<img src="<?php echo $captcha->inline(); ?>" onclick="location.reload()" />
# 点击验证码就重新生成一个新的。
</div>
<div>
<button>提交</button>
</div>
</body>
</html>
4. 依赖composer搭建一个php框架
- 老师列的一些基本流程:自制 php 开发框架
4-1. 架构
- M: Model, 使用第三方包实现
- V: View, 使用第三方实现
- C: Controller:业务逻辑主要是写到控制器中
4-2. 第三方包
- Model:
composer require catfan/medoo
- View:
composer require league/plates
4-3. 流程
- 创建自己的框架核心代码, Model, View,分别继承第三方的包(放在core文件夹下,两个php文件)
- 创建自己的应用,按 MVC 框架,并创建属于这个应用的 model, view, controller(放在app文件夹下,分别三个文件夹。因为每个里面可能不限于1个)
- 更新 composer.json 中的类的自动的映射关系
创建入口文件(index.php), 使用 composer 自动加载器进行测试
core下面的model.php文件
<?php
// 模型类
namespace core;
use Medoo\Medoo;
// 继承自第三方包:catfan/medoo
class Model extends Medoo
{
// 构造方法: 连接数据库
public function __construct()
{
$options = [
'database_type' => 'mysql',
'database_name' => 'phpedu',
'server' => 'localhost',
'username' => 'root',
'password' => 'root'
];
parent::__construct($options);
}
// 自己可以封装一些方法,创建自己的模型方法库
// 获取满足条件的集合中的第一条数据
public function first()
{
}
}
- core下面的view.php文件
<?php
// 视图类
namespace core;
use League\Plates\Engine;
class View extends Engine
{
public $templates;
public function __construct($path)
{
$this->templates = parent::__construct($path);
}
}
- app/models下的UsersModel.php文件
<?php
namespace models;
use core\Model;
// 用户自定义模型通常与一张数据表对应
class UsersModel extends Model
{
public function __construct()
{
parent::__construct();
}
}
- app/views/users下的list.php文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户信息</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
}
table {
border-collapse: collapse;
border: 1px solid;
width: 50%;
text-align: center;
}
th,
td {
border: 1px solid;
padding: 5px;
}
tr:first-child {
background-color: #eee;
}
</style>
</head>
<body>
<h3>用户管理系统</h3>
<table>
<tr>
<th>id</th>
<th>姓名</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<?php foreach ($users as $user): ?>
<tr>
<td><?=$this->e($user['id'])?></td>
<td><?=$this->e($user['name'])?></td>
<td><?=$this->e($user['email'])?></td>
<td><button>编辑</button><button>删除</button></td>
</tr>
<?php endforeach ?>
</table>
<p>
<a href="">1</a>
<a href="">2</a>
<a href="">3</a>
<a href="">4</a>
<a href="">5</a>
<a href="">6</a>
</p>
</body>
</html>
- app/controllers下面的UserController.php内容
<?php
namespace controllers;
class UsersController
{
// 将依赖的外对模型对象和视图对象,使用依赖注入到构造方法中,使它在控制器中共享
public $model = null;
public $view = null;
//构造方法
public function __construct($model, $view)
{
$this->model = $model;
$this->view = $view;
}
// 用于测试
public function index()
{
return __METHOD__;
}
// 这个相当于自己也可以创建一些东西
public function select()
{
// 通过模型获取数据
$users = $this->model->select('users', ['id', 'name','email'], ['id[>=]'=>5, 'LIMIT'=>5]);
// return $users;
// 将数据渲染到模板上(模板赋值同步完成)
return $this->view->render('users/list', ['users'=> $users]);
}
}
- 更新 composer.json 中的类的自动的映射关系
{
"require": {
"catfan/medoo": "^1.7",
"league/plates": "^3.3"
},
"autoload": {
"psr-4": {
"models\\": "app/models",
"views\\": "app/views",
"controllers\\": "app/controllers",
"core\\": "core"
}
}
}
- 入口文件index.html中去实现
<?php
// composer加载器
use controllers\UsersController;
use models\UsersModel;
use core\View;
require_once __DIR__ . '/vendor/autoload.php';
// 测试模型
$model =new UsersModel();
// var_dump($model);
// 测试视图
$view = new View('app/views');
// var_dump($view);
// 测试控制器
$controller = new UsersController($model, $view);
// var_dump($controller);
// echo $controller->index();
print_r($controller->select());
5. 作业与实战
- 实例演示comoser.json的autoload字段的files, classmap, psr-4的意义;
- 选做, 参考课堂案例,使用composer快速实现一个迷你的php开发框架
整体实现了一边,创建目录如下图:
后面还需要多联系,感觉很多精髓,尤其是多个文件,多个class以及多方法情况下,到底不同方法的差异、好处还没体会到(应该是越向后的方法越简单):