Laravel 5.3框架-多项目公用框架-架构设计方案

来源:互联网 发布:聊城关键词优化 编辑:程序博客网 时间:2024/06/14 04:51

前言

该文章内容仅限于互相探讨与学习。希望为普及LaravelPHP编程思想出一份力!

正题

由于最近一些朋友在使用laravel框架的时候碰到了一个非必须解决的问题,可能也是有存在一部分强迫症的原因吧。

具体需求是这样的。

Laravel框架是基于Composer设计的,项目所依赖的文件非常的多,同时在web根目录下会有着一箩筐的文件,单单vendor文件夹里有着5000+的文件。看起来不美观的同时,每一次新建一个项目,都必须重新导入laravel框架放在根目录下。对于项目的建立管理也是不方便的。于是朋友们提出了一个需求,希望laravel的框架独立,多项目共用框架,目录结构干净等等。

虽然这个需求多多少少是偏离了laravel本身的设计思路和结构,但是用过CodeIgniter,ThinkPHP的开发者一定还是受不了这样的结构方式吧。有种一进门就眼花缭乱的感觉。(当然,题外话。用了那么多的PHP框架,个人还是觉得TP框架更适合新手,成本更低,更加适合创业型公司。同时,看了ThinkPHP7新的结构,特别期待它的完善)

虽然我在两年前碰过laravel,但是那时候并非比较主流的框架,就随便看了看。所以,我用laravel最新的5.3做个结构改变的方案供大家学习。有什么不对的地方可以留言,欢迎探讨。

我也在业余时间帮朋友把Laravel框架重新进行了调整,以适应他们的需求。

有兴趣的朋友可以去github下载来看看。

https://github.com/lynk-coder/lynk-public-laravel/

教程

那么我们先看看最终改成的目录结构会变成什么样子:



这么做的目的,是将我们可爱的laravel框架彻底分割出去,同时根据自己的需求去切换自己项目所需求的框架。那么我们开始进行一步步的修改和调整。

首先我们要保证PHP在5.6及以上的版本。

我们先从项目基本结构先改,然后再修改框架。

1、<project>/public/index.php

我们在public文件夹里,把index.php进行一些修改。

我们在代码里面加入一些内容,这三段代码放在最开头的位置

define('APPLICATION_WEB_ROOT',__DIR__."/../"); define('LARAVEL_FRAMEWORK_DIR',APPLICATION_WEB_ROOT.'/../framework/laravel5.3');require APPLICATION_WEB_ROOT.'/../vendor/autoload.php';


其次,我们将原来的

require __DIR__.'/../bootstrap/autoload.php';$app = require_once __DIR__.'/../bootstrap/app.php';

改成

require LARAVEL_FRAMEWORK_DIR.'/bootstrap/autoload.php';$app = require_once LARAVEL_FRAMEWORK_DIR.'/bootstrap/app.php';

这样,我们的index.php改好了。


2、我们在< project >的同级目录下,新建framework,在framework下面建立laravel5.3目录,将bootstrap,vendor(框架文件),.env移动到laravel5.3目录里面,同时新建目录common


 

3、我们在< project >下面建立目录vendor,将config,database,resources,storage移动到vendor目录下面。



4、修改framwork/laravel5.3/vendor/laravel/framework/src/Illuminate/Foundation/Application.php的内容。这个文件是项目初始化用的,其中包含大多数路径信息。

在文件头部定义一个受保护的变量。

/** * 自定义web目录变量 * * @var string */protected $webPath;


在文件方法中定义getter和setter

/** * 设置web目录路径 * * @param $webPath * @return $this */public function setWebPath($webPath){    $this->webPath = rtrim($webPath, '\/');    return $this;}/** * 获取web目录路径 * @return string */public function webPath(){    return $this->webPath;}


将__construct方法改成

public function __construct($webPath = null,$basePath=null){    $this->registerBaseBindings();    $this->registerBaseServiceProviders();    $this->registerCoreContainerAliases();    if ($webPath) {        $this->setWebPath($webPath);    }    if ($basePath) {        $this->setBasePath($basePath);    }}


将方法bindPathsInContainer改成

protected function bindPathsInContainer(){    $this->instance('path', $this->path());    $this->instance('path.base', $this->basePath());    $this->instance('path.lang', $this->langPath());    $this->instance('path.config', $this->configPath());    $this->instance('path.public', $this->publicPath());    $this->instance('path.storage', $this->storagePath());    $this->instance('path.database', $this->databasePath());    $this->instance('path.bootstrap', $this->bootstrapPath());    $this->instance('path.web', $this->webPath());}


将方法path改成

public function path(){    return $this->webPath.DIRECTORY_SEPARATOR.'app';}

将方法 configPath改成

public function configPath(){    return $this->webPath.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'config';}


将databasepath改成

public function databasePath(){    return $this->databasePath ?: $this->webPath.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'database';}

将langPath改成

public function langPath(){    return $this->webPath.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'lang';}

将publicPath改成

public function publicPath(){    return $this->webPath.DIRECTORY_SEPARATOR.'public';}

将storagePath改成

public function storagePath(){    return $this->storagePath ?: $this->webPath.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'storage';}

将getNamespace改成

public function getNamespace(){    if (! is_null($this->namespace)) {        return $this->namespace;    }    $composer = json_decode(file_get_contents(web_path('composer.json')), true);    foreach ((array) data_get($composer, 'autoload.psr-4') as $namespace => $path) {        foreach ((array) $path as $pathChoice) {            if (realpath(app_path()) == realpath(web_path().'/'.$pathChoice)) {                return $this->namespace = $namespace;            }        }    }    throw new RuntimeException('Unable to detect application namespace.');}


这时候我们的Application.php改好了。


5、修改framwork/laravel5.3/vendor/laravel/framework/src/Illuminate/Foundation/helper.php

新增方法

if (! function_exists('web_path')) {    /**     * Get the path to the base of the install.     *     * @param  string  $path     * @return string     */    function web_path($path = '')    {        return app()->webPath().($path ? DIRECTORY_SEPARATOR.$path : $path);    }}


6、对framwork/laravel5.3/bootstrap/app.php进行修改


$app = new Illuminate\Foundation\Application(    realpath(__DIR__.'/../'));

改成
if(!defined('APPLICATION_WEB_ROOT')){    exit("未定义 ‘APPLICATION_WEB_ROOT’ 常量");}$app = new Illuminate\Foundation\Application(    realpath(APPLICATION_WEB_ROOT),    realpath(__DIR__."/../"));

7、framwork/laravel5.3/bootstrap/autoload.php文件不需要修改,因为已经指向了对应的框架加载的目录


8、修改framwork/laravel5.3/vendor/laravel/framework/src/Illuminate/Auth/Console/MakeAuthCommand.php


public function fire(){    $this->createDirectories();    $this->exportViews();    if (! $this->option('views')) {        file_put_contents(            app_path('Http/Controllers/HomeController.php'),            $this->compileControllerStub()        );        file_put_contents(            base_path('routes/web.php'),            file_get_contents(__DIR__.'/stubs/make/routes.stub'),            FILE_APPEND        );    }    $this->info('Authentication scaffolding generated successfully.');}

改为

public function fire(){    $this->createDirectories();    $this->exportViews();    if (! $this->option('views')) {        file_put_contents(            app_path('Http/Controllers/HomeController.php'),            $this->compileControllerStub()        );        file_put_contents(            web_path('routes/web.php'),            file_get_contents(__DIR__.'/stubs/make/routes.stub'),            FILE_APPEND        );    }    $this->info('Authentication scaffolding generated successfully.');}


protected function createDirectories(){    if (! is_dir(base_path('resources/views/layouts'))) {        mkdir(base _path('resources/views/layouts'), 0755, true);    }    if (! is_dir(base _path('resources/views/auth/passwords'))) {        mkdir(base _path('resources/views/auth/passwords'), 0755, true);    }}


改为

protected function createDirectories(){    if (! is_dir(web_path('resources/views/layouts'))) {        mkdir(web_path('resources/views/layouts'), 0755, true);    }    if (! is_dir(web_path('resources/views/auth/passwords'))) {        mkdir(web_path('resources/views/auth/passwords'), 0755, true);    }}


protected function exportViews(){    foreach ($this->views as $key => $value) {        copy(            __DIR__.'/stubs/make/views/'.$key,            base_path('resources/views/'.$value)        );    }}

改为

protected function exportViews(){    foreach ($this->views as $key => $value) {        copy(            __DIR__.'/stubs/make/views/'.$key,            web_path('resources/views/'.$value)        );    }}



9、修改<project>/app/Console/Kernel.php

protected function commands(){    require base_path('routes/console.php');}

改为

protected function commands(){    require web_path('routes/console.php');}

10、修改<project>/app/Providers/RouteServiceProviders.php

protected function mapWebRoutes(){    Route::group([        'middleware' => 'web',        'namespace' => $this->namespace,    ], function ($router) {        require base_path('routes/web.php');    });}



改为

protected function mapWebRoutes(){    Route::group([        'middleware' => 'web',        'namespace' => $this->namespace,    ], function ($router) {        require web_path('routes/web.php');    });}


protected function mapApiRoutes(){    Route::group([        'middleware' => 'api',        'namespace' => $this->namespace,        'prefix' => 'api',    ], function ($router) {        require base_path('routes/api.php');    });}

改成

protected function mapApiRoutes(){    Route::group([        'middleware' => 'api',        'namespace' => $this->namespace,        'prefix' => 'api',    ], function ($router) {        require web_path('routes/api.php');    });}


11、修改<project>/vendor/config/view.php

'paths' => [    realpath(base_path('/resources/views')),]

改成

'paths' => [    realpath(web_path('vendor/resources/views')),]


以上的11部操作只是纯粹的对文件的内容进行了修改,接下来我们来一个最核心的修改,composer!!!!


1、我们要在<project>目录下新建文件composer.json

       加入如下内容 :

{    "name": "lynk-public-laravel",    "description": "public laravel framework project",    "keywords": ["framework", "laravel"],    "license": "MIT",    "type": "project",    "require": {        "php": ">=5.6.4",        "laravel/framework": "5.3.*",        "guzzlehttp/guzzle": "^6.2",        "firebase/php-jwt": "^4.0"    },    "require-dev": {        "fzaninotto/faker": "~1.4",        "mockery/mockery": "0.9.*",        "phpunit/phpunit": "~5.0",        "symfony/css-selector": "3.1.*",        "symfony/dom-crawler": "3.1.*"    },    "autoload": {        "classmap": [            "vendor/database"        ],        "psr-4": {            "App\\": "app/"        }    },    "autoload-dev": {        "classmap": [        ]    },    "scripts": {        "post-root-package-install": [            "php -r \"file_exists('.env') || copy('.env.example', '.env');\""        ],        "post-create-project-cmd": [            "php artisan key:generate"        ],        "post-install-cmd": [            "Illuminate\\Foundation\\ComposerScripts::postInstall",            "php artisan optimize"        ],        "post-update-cmd": [            "Illuminate\\Foundation\\ComposerScripts::postUpdate",            "php artisan optimize"        ]    },    "config": {        "preferred-install": "dist"    }}


2、我们在framework/laravel5.3目录下新建文件composer.json

加入如下内容:

{    "name": "laravel/laravel",    "description": "The Laravel Framework.",    "keywords": ["framework", "laravel"],    "license": "MIT",    "type": "project",    "require": {        "php": ">=5.6.4",        "laravel/framework": "5.3.*",        "guzzlehttp/guzzle": "^6.2",        "firebase/php-jwt": "^4.0"    },    "require-dev": {        "fzaninotto/faker": "~1.4",        "mockery/mockery": "0.9.*",        "phpunit/phpunit": "~5.0",        "symfony/css-selector": "3.1.*",        "symfony/dom-crawler": "3.1.*"    },    "autoload": {        "classmap": [        ],        "psr-4": {        }    },    "autoload-dev": {        "classmap": [        ]    },    "scripts": {        "post-root-package-install": [        ],        "post-create-project-cmd": [        ],        "post-install-cmd": [        ],        "post-update-cmd": [        ]    },    "config": {        "preferred-install": "dist"    }}



3、我们在<project>目录下执行:

composer dumpautoload

重新编译项目的注入文件

4、我们在framework/laravel5.3目录下执行:

composer dumpautoload –o

重新编译框架的注入文件


以上四部基本完成了改变lavavel框架特性的方法,但是还没完,我们最重要的artisan还没有调整呢!

我们将artisan移动到<project>目录下。然后修改artisan文件。

1、在文件开发加上三句语句

define('APPLICATION_WEB_ROOT',__DIR__);define('LARAVEL_FRAMEWORK_DIR',APPLICATION_WEB_ROOT.'/../framework/laravel5.3');require APPLICATION_WEB_ROOT.'/vendor/autoload.php';

2、将之前的内容改为

require LARAVEL_FRAMEWORK_DIR.'/bootstrap/autoload.php';$app = require_once LARAVEL_FRAMEWORK_DIR.'/bootstrap/app.php';

之后,我们就可以使用artisan了




扩展


最后,可能有些人需要在框架里面写入一些公用方法。

这时候我们可以在framework/laravel5.3/下面建立一个common文件夹,





然后我们修改framework/laravel5.3/composer.json文件

"autoload": {    "classmap": [    ],    "psr-4": {    }},

改为

"autoload": {    "classmap": [    ],    "psr-4": {        "Common\\": "common/"    }},


到framework/laravel5.3/目录下执行

composer dumpautoload -o 

重新编译注入文件。

这时候,我们将framework/laravel5.3/common注入到了整个框架之中,自行定义好common里的文件的命名空间,就可以直接使用我们自己的自定义方法了。当然,common文件夹里的所有文件都可以被注入到项目,跟文件名无关。

假如,你的common文件夹有 func1.php,func2.php,func3.php三个文件,那么这些文件都会被自动注入到项目中的。

 

 

以上内容就是对我们laravel框架的修改方法。将laravel打造成公用的框架,同时相对原始的版本会更加简洁和干净。


如有疑问可以下方留言哦~
















0 0