基於Composer的Laravel擴充套件包開發工作流 ,實現laravle專案的檔案管理(記錄成長)

meiyoufan發表於2022-04-12

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

相關文章