PHP Composer包开发

基于Composer的Laravel扩展包开发工作流

实现laravle项目的文件管理,添加文件/文件夹,删除文件,查看代码/文件(代码支持缩进,支持语法高亮)

composer 项目地址:https://packagist.org/packages/wuqb/laravel-codeview

github 项目地址: https://github.com/wuxiumu/code-management

1、在项目下执行

mkdir packages // 创建packages 目录
cd packages // 进入 packages 目录
mkdir code-management // 创建code-management 目录,准备开发laravle文件管理

项目目录结构

- code-management
--config
--codemirror-5.31.0 [前端文件包]
--codeview.php [配置名称,路由,登录密码的]
--routes
--codevew.php [codeview 路由地址]
--src [开发包]
--Faceds
--CodeView.php
--CodeView.php
--CodeViewProvider.php
--composer.json

2、修改composer.json 文件

"autoload-dev": {
"psr-4": {
"App\\": "app/"
}
},

修改后

"autoload-dev": {
"psr-4": {
"App\\": "app/",
"Wqb\\CodeView\\": "packages/code-management/src"
}
},

3、执行 composer命令

composer dump_autoload

4、添加包的ServiceProvider

由于laravel的 package:discover 是读取 vendor/composer/installed.json 这个文件中安装的包,而我们的包是手动添加,所以无法自动添加ServiceProvider,手动在app.php中添加


'providers' => [
Wqb\CodeView\CodeViewProvider::class
],
'aliases' => [
'CodeView' => Wqb\CodeView\Facades\CodeView::class
],

上代码

code-management/composer.json

{
"name": "wuqb/laravel-codeview",
"description": "laravel codeview",
"license": "MIT",
"authors": [
{
"name": "wuqb",
"email": "824543976@qq.com"
}
],
"autoload": {
"psr-4": {
"Wqb\\CodeView\\": "src"
}
},
"require": {}
}

code-management/config/codeview.php

<?php

return   [
'name' => '简单的线上代码管理工具',
'password' => 'tk12',
'route' => '/codeview',
];

code-management/routes/codeview.php

<?php

Route::any('codeview','\Wqb\CodeView\CodeView@index');

code-management/src/Faceds/CodeView.php

<?php
namespace Wqb\CodeView\Facades;
use Illuminate\Support\Facades\Facade;
class CodeView extends Facade
{
protected static function getFacadeAccessor()
{
return 'codeview';
}
}

code-management/src/CodeView.php

<?php

namespace Wqb\CodeView;

use Illuminate\Config\Repository;
use Illuminate\Http\Request; class CodeView
{ protected $config; /**
* 构造方法
*/
public function __construct(Repository $config)
{
$this->config = $config->get('codeview');
} /**
* 展示页
*/
public function index(Request $request)
{
$this->head();
$this->viewAction($request);
$this->foot();
} /**
* 展示处理
*/
public function viewAction($request)
{
$password = $this->config['password'];
$n = $this->config['route'];
$csrf_token = csrf_token();
if (isset($_COOKIE['filehelper_login_password_123456789']) && $_COOKIE['filehelper_login_password_123456789'] == md5($password)) {
$c = $request->input('c');
$v = $request->input('v');
$a = $request->input('a');
$b = $request->input('b');
$v1 = './' . $v;
$va = $v1 . $a;
echo '<h3>' . $this->config['name'] . '</h3>';
switch ($c) {
case 'del':
if (is_file($va) == true) {
unlink($va);
echo "成功删除" . $a . "!";
} else {
echo "文件已经被删除!";
}
break;
case 'up':
if ($_FILES["file"]["error"] > 0) {
echo "上传失败! 错误码:" . $_FILES["file"]["error"] . "<br>";
} else {
if (file_exists($v1 . $_FILES["file"]["name"])) {
echo "文件已经存在。 ";
} else {
move_uploaded_file($_FILES["file"]["tmp_name"], $v1 . $_FILES["file"]["name"]);
echo "上传成功!";
}
}
break;
case 'md':
if ($a != "") {
if (is_dir($va)) {
echo "文件夹已存在!";
} else {
mkdir($va);
echo '文件夹创建成功!';
}
} else {
echo "文件夹名不能为空!";
}
break;
case 'ed':
if ($request->input('s') == "1") {
$eded = fopen($va, 'w');
fwrite($eded, $_POST['fs']);
fclose($eded);
echo '<h3>保存成功!</h3>';
} else {
echo '<a href="' . $n . '?v=' . $v . '">返回</a><br>
<form action="' . $n . '?v=' . $v . '&a=' . $a . '&c=ed&s=1" method="post" enctype="multipart/form-data">
<textarea type="text" name="fs" id="ed">' . str_replace('</textarea>', '</ t e xtarea>', file_get_contents($va)) . '</textarea></br>
<input type="hidden" name="_token" value="'.$csrf_token.'">
<button type="submit">保存</button></form>';
}
break;
default:
# code...
break;
} // 编辑页面是否展示列表
if ($b == "1") { } else {
echo '<a href="' . $n . '?v=' . dirname($v) . '/">返回</a><br>
<table><tr>
<th>名称&emsp;&emsp;&emsp;&emsp;</th>
<th>类型&emsp;&emsp;&emsp;&emsp;</th>
<th>大小&emsp;&emsp;&emsp;&emsp;</th>
<th>操作&emsp;&emsp;&emsp;&emsp;</th>
</tr>
'; if (is_dir($v1) == true) {
$fs = scandir($v1);
$i = 2;
while ($i <= count($fs) - 1) {
if ($fs[$i] != $n) {
echo "<tr><td>" . $fs[$i] . "</td>";
if (is_dir($v1 . $fs[$i]) == true) {
echo "<td>文件夹</td>";
echo "<td>-</td>";
echo '<td><a href=' . $n . '?v=' . $v . $fs[$i] . '/>打开</a></td>';
}
if (is_file($v1 . $fs[$i]) == true) {
echo "<td>文件</td>";
echo "<td>" . number_format(filesize($v1 . $fs[$i]) / 1024 / 1024, 4, ".", "") . "MB</td>";
if (substr(strrchr($fs[$i], '.'), 1) !== 'php' && substr(strrchr($fs[$i], '.'), 1) !== 'asp' && substr(strrchr($fs[$i], '.'), 1) !== 'aspx' && substr(strrchr($fs[$i], '.'), 1) !== 'do') {
echo '<td><a href="' . $v . $fs[$i] . '">下载</a>';
} else {
echo '<td><a href="' . $v . $fs[$i] . '">打开</a>';
}
echo '&nbsp;<a href="' . $n . '?c=del&a=' . $fs[$i] . '&v=' . $v . '">删除</a>';
$ihzm = substr(strrchr($fs[$i], '.'), 1);
if ($ihzm !== 'png' && $ihzm !== 'doc' && $ihzm !== 'docx' && $ihzm !== 'jpg' && $ihzm !== 'gif' && $ihzm !== 'zip' && $ihzm !== 'apk' && $ihzm !== 'webp' && $ihzm !== 'ppt' && $ihzm !== 'pptx' && $ihzm !== 'exe' && $ihzm !== 'xls') {
echo '&nbsp;<a href="' . $n . '?c=ed&v=' . $v . '&a=' . $fs[$i] . '&b=1">编辑</a>';
}
echo '</td>';
} echo "</tr>";
}
$i++;
}
} echo '</table><hr>
<form action="' . $n . '?v=' . $v . '&c=up" method="post" enctype="multipart/form-data">
上传文件:<input type="file" name="file">
<input type="hidden" name="_token" value="'.$csrf_token.'">
<input type="submit" value="上传">
</form>
<form action="' . $n . '" method="get" enctype="multipart/form-data">
<input type="hidden" name="_token" value="'.$csrf_token.'">
新建文件夹:<input type="text" name="a"><input type="hidden" name="c" value="md"><input type="hidden" name="v" value="' . $v . '">
<input type="submit" value="新建">
</form>';
}
} else {
if ($request->input('password') == $password) {
setcookie("filehelper_login_password_123456789", md5($password), time() + 3600);
header("location:" . $n);
} else {
$this->form();
}
}
} /**
* 登录文件管理验证
*/
public function form()
{
$csrf_token=csrf_token();
echo <<<EOF
<form action="" method="post" enctype="multipart/form-data">
请输入密码
<input type="hidden" name="_token" value="$csrf_token">
<input type="password" name="password">
<input type="submit" value="登录">
</form>
EOF;
} /**
* 头部
* 引入必要的js,css
*/
public function head()
{
echo <<<EOF
<!DOCTYPE html>
<html lang="en">
<!--begin code mirror -->
<!--下面两个是使用Code Mirror必须引入的-->
<link rel="stylesheet" href="/src/codemirror-5.31.0/lib/codemirror.css" />
<script src="/src/codemirror-5.31.0/lib/codemirror.js"></script>
<!--Java代码高亮必须引入-->
<script src="/src/codemirror-5.31.0/clike.js"></script>
<!--groovy代码高亮-->
<script src="/src/codemirror-5.31.0/mode/groovy/groovy.js"></script>
<!--引入css文件,用以支持主题-->
<link rel="stylesheet" href="/src/codemirror-5.31.0/theme/dracula.css" /> <!--支持代码折叠-->
<link rel="stylesheet" href="/src/codemirror-5.31.0/addon/fold/foldgutter.css" />
<script src="/src/codemirror-5.31.0/addon/fold/foldcode.js"></script>
<script src="/src/codemirror-5.31.0/addon/fold/foldgutter.js"></script>
<script src="/src/codemirror-5.31.0/addon/fold/brace-fold.js"></script>
<script src="/src/codemirror-5.31.0/addon/fold/comment-fold.js"></script>
<!--括号匹配-->
<script src="/src/codemirror-5.31.0/addon/edit/matchbrackets.js"></script>
<!--end Code Mirror --> <head>
<meta charset="utf-8" />
<title>文件管理</title>
</head>
EOF;
} /**
* 脚部
* js 配置:代码折叠 | 设置主题 | 代码高亮| 设置代码框的长宽
*/
public function foot()
{
echo <<<EOF
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("ed"), {
mode: "text/groovy", //实现groovy代码高亮
mode: "text/x-java", //实现Java代码高亮
lineNumbers: true, //显示行号
theme: "dracula", //设置主题
lineWrapping: true, //代码折叠
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
matchBrackets: true, //括号匹配
//readOnly: true, //只读
});
editor.setSize('100%', '400px'); //设置代码框的长宽
</script>
</body>
</html>
EOF;
} }

code-management/src/CodeViewProvider.php

<?php
namespace Wqb\CodeView;
use Illuminate\Support\ServiceProvider;
class CodeViewProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
$this->loadRoutesFrom(__DIR__.'/../routes/codeview.php');
$this->publishes([
__DIR__.'/../config/codemirror-5.31.0' => base_path('public/src/codemirror-5.31.0'),
]);
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
$this->app->singleton('codeview', function ($app) {
return new CodeView($app['config']);
});
}
}

5、访问项目地址/codeview

登录页

密码:

tk12

列表页

查看编辑页

文件上传,新建目录

6、提交推送到git仓库

不懂可以百度,如何提交代码到github仓库

7、发布到packagist

  1. 注册登录Packagist(https://packagist.org/

  2. 点击右上角Submit

  3. 将你的Github地址贴进去,点Check

8、可能遇到的问题

1、Could not find a version of package matching your minimum-stability (stable).

git tag v1.0
git push origin v1.0

2、Could not find package

// 不要使用国内镜像,设置回 https://packagist.org
// 然后别忘了打开你的梯子
composer config -g repo.packagist composer https://packagist.org

基于Composer的Laravel扩展包开发工作流 ,实现laravle项目的文件管理(记录成长)的更多相关文章

  1. 基于Composer的Laravel扩展包开发工作流

    使用场景 在引用第三方包的时候,对第三方包有改动需求,需要将代码放在自己的仓库:并且自己的其他项目也有需求引用自定义的第三方包:甚至自己会发布修改后的第三方包: 读完本文你讲获得: Git Submo ...

  2. 使用 Composer 安装Laravel扩展包的几种方法

    使用 Composer 安装Laravel扩展包的几种方法 以下的三种方法都是需要你在项目的根目录运行 第一种:composer install 如有 composer.lock 文件,直接安装,否则 ...

  3. 如何正确使用 Composer 安装 Laravel 扩展包

    我们经常要往现有的项目中添加扩展包,有时候因为文档的错误引导,如下图来自 这个文档 的: composer update 这个命令在我们现在的逻辑中,可能会对项目造成巨大伤害. 因为 composer ...

  4. laravel扩展包开发步骤总结

    1. 创建包 php artisan workbench vendor/package --resources     注:  vendor:开发商名   package:包名   2.修改下包里co ...

  5. 如何开发、本地测试、发布 Laravel 扩展包?

    如何开发.本地测试.发布 Laravel 扩展包?  Laravel/ 1年前/  4022 /  11   现在已经有了很多,关于如何开发 Laravel 扩展包的文章.但是大多文章写的太过片面,不 ...

  6. 如何开发 Laravel 扩展包并发布到 Composer

    如何开发 Laravel 扩展包并发布到 Composer  发布于 2019-01-22 cxp1539  1074 Vie   开发扩展包 我们来做一个根据第一个字符或者汉字生成头像的larave ...

  7. laravel composer 扩展包开发(超详细)

    laravel composer 扩展包开发(超详细) 置顶 2018年02月05日 11:09:16 Simael__Aex 阅读数:10396    版权声明:转载请注明出处:http://blo ...

  8. 【转】下载量最高的 100 个 Laravel 扩展包推荐

    说明 Laravel 另一个令人喜欢的地方,是拥有活跃的开发者社区,而活跃的开发者社区带来的,是繁华的扩展包生态. 本文对 Packagist 上打了 Laravel 标签 的扩展包进行整理,截止到现 ...

  9. laravel 安装 Laravel 扩展包

    问题说明 我们经常要往现有的项目中添加扩展包,有时候因为文档的错误引导,如下图来自这个文档 的: composer update 这个命令在我们现在的逻辑中,可能会对项目造成巨大伤害. 因为 comp ...

随机推荐

  1. Oneops运维系统

      背景:公司对接其他系统时都会将业务分为几大模块由不同的人员去开发部署.那么部署方式为传统方式登录服务器,然后操作.所以每次上线我们可能都需要等待别的同事操作完才能操作自己所负责的业务系统.针对以上 ...

  2. Linux上后台保持Terminal交互运行的三种方式:nohub、screen和tmux

    镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 后台运行 Linux上,如果一个进程需要保持后台运行,尤其是在Linux服务器上,后台运行程序.避免因为SSH连接断开而导致进程停止运行时,该怎么 ...

  3. kubernetes资源使用glusterfs卷进行数据持久化

    1.GlusterFS部署 安装GlusterFS集群的主要目的是为k8s集群提供分布式持久化存储. GlusterFS部署使用2台服务器,服务名称与IP如下: 1 db-storagea 10.1. ...

  4. ubuntu 16.04 设置root用户初始密码

    安装ubuntu成功后,都是普通用户权限,并没有最高root权限,如果需要使用root权限的时候,通常都会在命令前面加上 sudo .有的时候感觉很麻烦- 我们一般使用su命令来直接切换到root用户 ...

  5. Python 的排序方法 sort 和 sorted 的区别

    使用 sort() 或内建函数 sorted() 对列表进行排序.它们之间的区别有两点: sort() 方法是对原列表进行操作,而 sorted() 方法会返回一个新列表,不是在原来的基础上进行操作. ...

  6. Mycat 数据切分 看这一篇就够了

    数据切分 ​ 数据切分指的是通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库上面,以达到分散单台设备负载的效果. ​ 数据的切分根据其切分规则的类型,可以分为两种切分模式.一种 ...

  7. java面向对象思想之封装

    一.什么是封装 菜鸟教程对封装的解释是"在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装.隐藏起来的方法.".简单来说就 ...

  8. PHP--腾讯云服务器上部署LNMP环境

    本文参考 云服务器上部署Laravel的实例教程 腾讯云 创建 Laravel5.4 项目 阿里云服务器部署php的laravel项目,在阿里云买ECS 搭建 Linux+Nginx+Mysql+PH ...

  9. 如何规划一台 Linux 主机,步骤是怎样?

    1.确定机器是做什么用的,比如是做 WEB .DB.还是游戏服务器.不同的用途,机器的配置会有所不同.    2.确定好之后,就要定系统需要怎么安装,默认安装哪些系统.分区怎么做.    3.需要优化 ...

  10. Mysql之B+树索引实战

    索引代价 空间上的代价 一个索引都对应一棵B+树,树中每一个节点都是一个数据页,一个页默认会占用16KB的存储空间,所以一个索引也是会占用磁盘空间的. 时间上的代价 索引是对数据的排序,那么当对表中的 ...