ThinkPHP插件扩展库的安装
在实际开发过程中,网上有很多的第三方扩展包,大家可以拿来直接用。
本套课程中也使用第三方扩展,关于think-addons的扩展,大家可以到composer
软件仓库(https://packagist.org)中查找。
在这里咱们以:5ini99/think-addons
以这个为例。
1. 安装
在这里使用composer
进行安装。在composer软件创库中都会给出安装命令
composer require 5ini99/think-addons
在这里我在上面扩展的基础上,重新发布了一个扩展,主要是增加了两个功能函数。主要用于本套课程。更多的功能,大家可以自行扩展
//主要用于本套课程
composer require jingyifeng/think-addons
2. think-addons的引入与简单的使用
在这里先按照扩展中给出的实例快速的开发一个插件,以便熟悉开发插件的流程。
插件列表
由于咱们的插件并未存入数据库,所以在所获插件时,要通过遍历插件目录来获取。
效果:
在获取插件列表时的注意事项(知识点)
在5ini99/think-addons
扩展包中,并未提供获取插件目录的方法或函数。所以需要种们自己处理。
- 遍历插件目录(可以使用 php内置函数
scandir
) - 获取有效插件(所谓有效插件即符合开发者制定的一套开发规范)
- 将获取插件列表封装成方法或函数,放到公共文件中。在这里咱们直接将其封装到插件库的函数库中,以便后期的使用。
具体实现代码如下:
封装到插件库的函数文件common.php
中
/**
* 获取插件列表
*/
function get_addon_list(){
$addons=scandir(ADDON_PATH);
$arr=[];
foreach ($addons as $v){
if($v=="." || $v==".."){
continue;
}
if(is_file(ADDON_PATH.DS.$v)){
continue;
}
if(is_dir(ADDON_PATH.DS.$v)){
//判断插件是否为有效插件
//1. 判断是否存在插件类
if(!is_file(ADDON_PATH.DS.$v.DS.ucfirst($v).'.php')){
continue;
}
$class=get_addon_class($v);
$info=(new $class)->info;
//判断插件的基本信息是否有效
if(!(new $class)->checkInfo()){
continue;
}
$arr[]=$info;
}
}
return $arr;
}
在这里大家要明白,在判断是否为有效插件时,要根据咱们制定的插件规范进行判断,这里只是举了两个例子。
插件的安装与卸载
插件的安装与卸载,这是插件中的核心。也正是因为插件的安装与卸载,才能使插件技术在系统功能扩展上十分的灵活。
每一个插件都至少有两个状态安装
和未安装
,所以咱们在使用时,需要去标记插件的安装状态,在标记时,方式有多种,可以根据自己的需求灵活处理。
插件状态的标记方式:
- 直接将插件状态写入数据库
思路1:将安装成功的插件信息写入数据库,如未安装的不写入
思路2:将所有的插件写入数据库,插件状态使用一个字段进行标识
- 不使用数据库-通过文件进行标记
思路1:将安装成功的插件信息写入到该插件目录下的一个文件中,也可以使用一个文件进行标记。
思路2:直接在插件基本信息中进行标记(灵活度不高,不建义这样使用)。
通过文件进行标记
在这里,咱们直接在安装成功的插件目录下,生成一个配置文件,里面含有插件的基本信息,还有咱们需要的其它的配置信息(如:插件菜单等)
在这里,就直接通过写入文件的方式来实现。由于原插件扩展包中,没有生成文件的方法,所以在这里,同样在扩展包函数文件中,新增一个创建文件的函数。
创建文件的函数:
/**
* 生成插件配置文件
* @param array $config 配置信息
* @param string $name 配置文件名
* @return array
*/
function create_config($config,$name="config.php"){
$config_file=ADDON_PATH.$config['name'].DS.$name;
if(is_file($config_file) && file_exists($config_file)){
return false;
}
$config=var_export($config, true);
$content =<<<EOT
<?php
return {$config}
EOT;
$result=file_put_contents($config_file,$content);
if($result===false){
return false;
}
return true;
}
插件安装
插件安装其实就是生成标识文件,在这里咱们直接在安装插件的根目录下生成一个配置文件,文件内容咱们根据需求,自行定义。
在这要注意,安装插件可能不仅仅是生成配置文件,还要处理一些其它的业务逻辑。比如生成数据表、向表中添加字段等等。这个主要是根据咱们的插件功能和需求来定。
插件卸载
插件卸载,就是要删除标识文件,同时还要移除其它的业务逻辑。但是在实际开发过程中,在删除插件时,为了避免风险,部分内容可能需要手动删除(如:数据库)。
留言插件的开发
通过前几节对插件以及创建扩展的学习,已经对插件有了基本的认识,在这里咱就来开发一个在线留言
插件。
插件功能
1. 在博文详情页添加上在线留言功能
2. 留言给博文对应有作者
3. 个人博客后台可以查看自己的博客留言信息
本插件不但需要在前台进行展示,同时博文作者可以通过个人博客后台查看留言
知识点
1. 留言表的创建(sql创建)
2. 插件中静态资源文件的引入方式
第一部分:创建留言插件
按照前几节课制定的插件开发规范,创建留言插件message
,由于在个人博客后台需要添加查看留言的菜单项,所以在插件基本信息中,直接加上菜单项的配置。另外,需要在钩子方法设置留言表单的模板。
第二部分:数据表的创建
在创建留言表时,需要在安装插件时直接创建,所以需要使用建表语句来创建。
留言表-建表语句(根据需要自行调整)
CREATE TABLE `td_message` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT '0' COMMENT '姓名',
`phone` VARCHAR(11) NOT NULL DEFAULT '0' COMMENT '手机号',
`content` VARCHAR(200) NOT NULL DEFAULT '0' COMMENT '留言内容',
`create_time` INT(10) NOT NULL DEFAULT '0',
`update_time` INT(10) NOT NULL DEFAULT '0',
`touid` INT(10) NOT NULL DEFAULT '0' COMMENT '留言对象',
PRIMARY KEY (`id`)
)
COMMENT='留言表'
ENGINE=MyISAM
;
在这里要注意,建表语句的存放位置,一般情况下可以放到一个文件里比如,课程中是直接放到了留言插件目录下的install.sql
。另外,由于一个插件对于数据库的操作可能有多个,所以在安装时需要执行的sql语句并不一定只有一个,也就是install.sql中存放的sql
语句可能有多个,那么这里就要分开来执行,所以需要对install.sql中的语句进行分解,即把sql
语句拆分。折分后,再循环执行。
创建数据表的注意事项
1. install.sql文件中,结尾不要有空行
2. 在进行拆分sql语句时,要进行空数据的过滤
3. 要进行数据表的存在性判断
数据表创建代码片段
//创建留言数据表
$sql_content=file_get_contents(ADDON_PATH .'message/install.sql');//获取sql脚本
$arr_sql=array_filter(explode(";",$sql_content));//对sql进行拆分,并过滤空数据
foreach ($arr_sql as $v){//循环执行sql
Db::execute($v);
}
第三部分 创建钩子模板(留言表单)
要实现留言功能,首先需要添加留言表单。通过钩子模板来实现。在这里要注意表单样式,由于钩子模板会做为所在页面的一部分,所以会继承当前页面的样式。具体效果可以自行进行设置。
第四部分 实现留言功能
留言表单处理好后,接下来要做的就是将用户的留言数据通过表单提交到后端处理并写入数据表(td_message)。
在这里重点看一下处理表单提交业的数据处理如何实现。在这里插件扩展也遵循TP5的MVC模式。所以对于留言数据的处理,也要通过控制器模型的方式来实现(也可以不使用模型层)。
1. 在插件目录下创建控制器目录controller和模型目录model
2. 创建控制器Index.php和数据处理的方法save
在这里的控制器名称和方法名称可是自定义的。
注意事项
1. 控制器的命名空间要注意addons\message\controller
2. 控制器要继承插件扩展中think\addons\Controller并不是think\Controller
<?php
namespace addons\message\controller;
use think\addons\Controller;
use addons\message\model\Message;
class Index extends Controller
{
/**
* 在线留言数据处理
*/
public function save(){
$data=input('post.');
$result=Message::store($data);
if($result){
$this->success("留言成功");
}else{
$this->error("留言失败");
}
}
}
3. 模型的创建
在创建模型时,和TP中的模式的使用方法是完一样的,也同样需要继承Think的Model基类。
[danger]要注意的是和数据表的对应(确认表前辍是否和系统默认配相同)。
<?php
namespace addons\message\model;
use think\Model;
class Message extends Model
{
protected $table = 'td_message';
protected $autoWriteTimestamp = true;
public static function store($data){
if(!is_array($data)){
return false;
}
//获取博文发布的id
$touid=db("blogcate")->where('cid',$data['cid'])->value('uid');
$data['touid']=$touid;
$result=self::create($data);
if($result){
return true;
}
return fase;
}
}
由于要指定留言的对像,所以在留言时需要获取到博文发布着的用户id。在这里要注意一点,前台博文详情页中的模板变量,在插件模板中是不能直接使用的。所以在这里需要在调用插件时,通过参数的方式进行传递。
所以博文详情页中调用留言插件时,如下调用
{:hook("messagehook",['cid'=>$article.cid])}
第五部分 个人博客管理后台查看留言功能的实现
在这里开发MVC的模式和application下的模人开发是一样的。但是要注意以下几 。
注意事项:
- 插件中的 控制器方法的访问方式不同
- 模板拆分中的路径设置问题(相对路径)
- 插件和application中共用模板时的路径设置
- 做后台插件时,要注意插件的访问权限(判断用户是否登录)
插件中静态资源文件的处理
在很多场景下,插件下是需要静态资源文件的,如js、css、imgage等。像这些在访问时,需要在站点根目录下(public)下才可以访问。所以在安装插件时,需要对静态资源文件进行处理。
通常情况下会将静态资源文件
移动到public目录下。具体的规则需要规范化。比如,约定插件的资源文件安装后,会移入public\static\addons
目录下
插件的离线安装
关于插件的安装,在实际项目中常见的安装方式有手动安装
、离线安装
、在线安装
。前几节讲的插件的安装要主要手动安装
,这里咱们重点讲一下离线安装
。
安装方式
手动安装
前几节所讲的安装是将插件的所有文件(解压后)上传到插件目录来实现的安装。这里的上传方式是一般是通过FTP等直接上传。
离线安装
离线安装是指将安装包下载到本地(不需要进行解压),然后通过后台上传来实现的安装方式。
在线安装
是指将远程插件仓库中的插件通过远程的方式获取并直接安装。这里的插件仓库一般是开发者提供的。
离线安装的实现
知识点
1. 插件离线包的制作
2. 文件上传
3. 在线解压
离线包的制作
在这里要制定套规范。在这里咱们直接把插件目录打包成*.zip格式的。
例留言插件打包后:message.zip
文件名自定义,重要的是包里的内容。
在线解压的实现
<?php
//解压缩
$zip = new \ZipArchive;
//要解压的文件
$zipfile = "./test.zip";
$res = $zip->open($zipfile);
if($res!==true){
return "操作异常";
}
//要解压到的目录
$toDir = "./test";
if(!file_exists($toDir)) {
mkdir($toDir,755);
}
//获取压缩包中的文件数(含目录)
$docnum = $zip->numFiles;
//遍历压缩包中的文件
for($i = 0; $i < $docnum; $i++) {
$statInfo = $zip->statIndex($i);
if($statInfo['crc'] == 0) {
//新建目录
mkdir($toDir.'/'.substr($statInfo['name'], 0,-1));
} else {
//拷贝文件
copy('zip://'.$zipfile.'#'.$statInfo['name'], $toDir.'/'.$statInfo['name']);
}
}
复制
上传并解压完成后,可以直接执行安装操作