步驟
組件項目的基本目錄
lixiyong
└─lshop-laravel
├─src
| ├─wap
| | ├─Goods 商品模塊
| | | ├─composer.json
| | | └─ ... 更多類庫目錄
| | ├─Order 訂單模塊
| | └─member 用戶模塊
| └─ ... 更多類庫目錄
|
├─composer.json 過
└─README.md README 文件
1.創建基本的文件,在lixiyong目錄下執行cmd命令:
D:\phpstudy_pro\WWW\lixiyong>package-builder build lshop-laravel
'git' is not recognized as an internal or external command,
operable program or batch file.
Name of package (example: foo/bar): lixiyong/lshop-laravel
Namespace of package [Lixiyong\LshopLaravel]:
Description of package:
Author name of package [lixiyong]:
Author email of [email protected]
License of package [MIT]:
Do you want to test this package ? [Y/n]:
Do you want to use php-cs-fixer format your code ? [Y/n]:
Standard name of php-cs-fixer [symfony]:
Package lixiyong/lshop-laravel created in: ./lshop-laravel
D:\phpstudy_pro\WWW\lixiyong>cd ./lshop-laravel/src
D:\phpstudy_pro\WWW\lixiyong\lshop-laravel\src>package-builder build Wap/Member
'git' is not recognized as an internal or external command,
operable program or batch file.
Name of package (example: foo/bar): lixiyong/lshop-laravel-wap-member
Namespace of package [Lixiyong\LshopLaravelWapMember]: Lixiyong\LshopLaravel\Wap\Member
Description of package:
Author name of package [lixiyong]:
Author email of [email protected]
License of package [MIT]:
Do you want to test this package ? [Y/n]: n
Do you want to use php-cs-fixer format your code ? [Y/n]:n
Package lixiyong/lshop-laravel-wap-member created in: ./Wap/Member
D:\phpstudy_pro\WWW\lixiyong\lshop-laravel\src>
2.刪掉一些不必要的文件,如member裏面的src文件夾
完善一下lixiyong\lshop-laravel\composer.json中的內容
{
"name": "lixiyong\/lshop-laravel",
"description": "Package description here.",
"license": "MIT",
"authors": [
{
"name": "lixiyong",
"email": "[email protected]"
}
],
"require": {},
"replace": {
"lixiyong/lshop-laravel-wap-member": "self.version"
},
"autoload": {
"psr-4": {
"Lixiyong\\LshopLaravel\\": "src"
}
}
}
完善一下lixiyong\lshop-laravel\src\Wap\Member\composer.json中的內容
{
"name": "lixiyong\/lshop-laravel-wap-member",
"description": "Package description here.",
"license": "MIT",
"authors": [
{
"name": "lixiyong",
"email": "[email protected]"
}
],
"require": {},
"autoload": {
"psr-4": {
"Lixiyong\\LshopLaravel\\Wap\\Member\\": ""
}
}
}
添加一個測試類Test.php
<?php
namespace Lixiyong\LshopLaravel\Wap\Member;
class Test
{
public function index()
{
return '這是一個測試類';
}
}
3.在laravelnew項目中加載本地的lshop-laravel組件
laravelnew是一個laravel5.8版本的項目,自行下載即可
D:\phpstudy_pro\WWW\lixiyong\laravelnew>composer config repositories.lixiyong path ../lshop-laravel
D:\phpstudy_pro\WWW\lixiyong\laravelnew>composer require lixiyong/lshop-laravel:dev-master
用上一個博客寫好的單元測試組件來測試一下,如果沒下載的可以運行以下命令加載即可
composer require "lixiyong/lunit-laravel"
瀏覽器輸入 http://127.0.0.1/lixiyong/laravelnew/public/lunit,如果填入相關參數
如果出現下面效果,說明測試成功
4.創建一些組件基本的文件夾
5.通過中間件快速實現微信授權 laravel+easywechat
安裝easywechat組件,組件地址:https://github.com/overtrue/laravel-wechat
laravel框架中的實現簡單實現微信網頁授權登入,首先引入基於laravel的easywechat的組件,laravel版本5.8
$ cd laravelnew
$ composer require "overtrue/laravel-wechat:~5.0"
$routeMiddleware:路由中間件,有些個別的請求,我們需要執行特別的中間件時,就適合定義在這屬性裏面
根據官方提供的測試代碼在routes/web.php中定義這個參數
注意還有一個動作要做就是發佈配置文件
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
修改應用根目錄下的 config/wechat.php 中對應的參數即可;我們可以把信息放到.env中
這些信息就是你在 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index 這個頁面顯示的信息
然後開啓natapp 再訪問在routes/web.php中定義的user路由
6.組件實現微信網頁授權登入
1.基礎流程
寫一個基本的控制器lshop-laravel\src\Wap\Member\Http\Controllers\Controller.php
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
其實就是基本的實現這個功能的業務先實現好lshop-laravel\src\Wap\Member\Http\Controllers\AuthorizationsController.php
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Http\Controllers;
use Illuminate\Http\Request;
use Lixiyong\LshopLaravel\Wap\Member\Models\User;
use Illuminate\support\Facades\Auth;
class AuthorizationsController extends Controller
{
public function wechatStore(Request $request)
{
//獲取微信的用戶信息
$wechatUser = session('wechat.oauth_user.default');
$user = User::where('weixin_openid',$wechatUser->id)->first();
if(!$user){
//不存在記錄用戶信息
$user = User::create([
"nickname" => $wechatUser->name,
"weixin_openid"=>$wechatUser->id,
"image_head"=>$wechatUser->avatar
]);
}
//登入狀態->改變
//遷移性的問
//改變用戶的狀態設置登入
//難的點
return "通過";
//return redirect()->route('wap.member.index');
}
}
模型 lshop-laravel\src\Wap\Member\Models\User.php
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table="sys_user";
protected $fillable=[
'nickname','weixin_openid','image_head',
];
}
路由lshop-laravel\src\Wap\Member\Http\routes.php
<?php
Route::get("/wechatStore", "AuthorizationsController@wechatStore")->middleware("wechat.oauth");
?>
服務提供者lshop-laravel\src\Wap\Member\Providers\MemberServiceProvider.php
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Route;
class MemberServiceProvider extends ServiceProvider
{
//模仿
public function register()
{
//註冊組件路由
$this->registerRoutes();
}
//參考別人的寫法
//對於源碼熟悉更好一些
private function registerRoutes()
{
Route::group($this->routeConfiguration(),function(){
$this->loadRoutesFrom(__DIR__.'/../Http/routes.php');
});
}
private function routeConfiguration()
{
return [
//定義訪問路由的域名
//'domain'=>config('telescope.domain',null),
//是定義路由的命名空間
'namespace'=>'Lixiyong\LshopLaravel\Wap\Member\Http\Controllers',
//這是前綴
'prefix'=>'wap/member',
'middleware'=>'web',
];
}
}
修改lshop-laravel文件夾中的composer.json,添加服務提供者的加載,以及引用easywechat組件
{
"name": "lixiyong\/lshop-laravel",
"description": "Package description here.",
"license": "MIT",
"authors": [
{
"name": "lixiyong",
"email": "[email protected]"
}
],
"require": {
"overtrue/laravel-wechat": "~5.0"
},
"replace": {
"lixiyong/lshop-laravel-wap-member": "self.version"
},
"autoload": {
"psr-4": {
"Lixiyong\\LshopLaravel\\": "src"
}
},
"extra":{
"laravel":{
"providers":[
"Lixiyong\\LshopLaravel\\Wap\\Member\\Providers\\MemberServiceProvider"
]
}
}
}
讓laravelnew項目加載本地的lshop-laravel組件,在laravelnew中執行
composer config repositories.lixiyong path ../lshop-laravel
composer require lixiyong/lshop-laravel:dev-master
執行php artisan route:list查看效果
2.自定義組件的認證模型
目前是實現了微信網頁授權登入,但是呢這個過程可能我們還有一個操作需要處理一下那就是,用戶的狀態需要更改,改爲登入狀態;在laravel中提供了一個方式那就是通過auth用戶認證.修改
lshop-laravel\src\Wap\Member\Models\User.php讓它支持auth操作
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $table = "sys_user";
protected $fillable = [
'nickname', 'weixin_openid', 'image_head',
];
}
?>
修改文件lshop-laravel\src\Wap\Member\Config\member.php
<?php
return [
'auth'=>[
//事先的動作,爲了以後着想
'controller'=>Lixiyong\LshopLaravel\Wap\Member\Http\Controllers\AuthorizationsController::class,
//當前使用的守衛,只是定義
'guard'=>'wap-member',
//定義守衛組
'guards'=>[
'wap-member'=>[
'driver'=>'session',
'provider'=>'member',
],
],
'providers'=>[
'member-user'=>[
'driver'=>'eloquent',
'model'=>Lixiyong\LshopLaravel\Wap\Member\Models\User::class,
]
],
]
];
修改控制器Lixiyong\LshopLaravel\Wap\Member\Http\Controllers\AuthorizationsController.php
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Http\Controllers;
use Illuminate\Http\Request;
use Lixiyong\LshopLaravel\Wap\Member\Models\User;
use Illuminate\support\Facades\Auth;
class AuthorizationsController extends Controller
{
public function wechatStore(Request $request)
{
//獲取微信的用戶信息
$wechatUser = session('wechat.oauth_user.default');
$user = User::where('weixin_openid',$wechatUser->id)->first();
if(!$user){
//不存在記錄用戶信息
$user = User::create([
"nickname" => $wechatUser->name,
"weixin_openid"=>$wechatUser->id,
"image_head"=>$wechatUser->avatar
]);
}
//登入狀態->改變
//遷移性的問
//改變用戶的狀態設置登入
//難的點
Auth::guard('member')->login($user);
var_dump(Auth::check());
return "通過";
//return redirect()->route('wap.member.index');
}
}
修改服務提供者laravel-shop\src\Wap\Member\Providers\MemberServiceProvider.php
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Arr;
class MemberServiceProvider extends ServiceProvider
{
protected $commands = [
\Lixiyong\LshopLaravel\Wap\Member\Console\Commands\InstallCommand::class,
];
//member組件需要注入的中間件
protected $routeMiddleware=[
'wechat.oauth'=>\Overtrue\LaravelWeChat\Middleware\OAuthAuthenticate::class,
];
protected $middlewareGroups=[];
//模仿
public function register()
{
//註冊組件路由
$this->registerRoutes();
//怎麼加載config配置文件
$this->mergeConfigFrom(__DIR__.'/../Config/member.php',"wap.member");
//怎麼根據配置文件去加載auth信息
$this->registerRouteMiddleware();
}
public function boot()
{
$this->loadMemberConfig();
}
protected function loadMemberConfig()
{
config(Arr::dot(config('wap.member.wechat',[]),'wechat.'));
config(Arr::dot(config('wap.member.auth',[]),'auth.'));
}
protected function registerRouteMiddleware()
{
foreach ($this->middlewareGroups as $key=>$middleware){
$this->app['router']->middlewareGroup($key,$middleware);
}
foreach ($this->routeMiddleware as $key=>$middleware){
$this->app['router']->aliasMiddleware($key,$middleware);
}
}
//參考別人的寫法
//對於源碼熟悉更好一些
private function registerRoutes()
{
Route::group($this->routeConfiguration(),function(){
$this->loadRoutesFrom(__DIR__.'/../Http/routes.php');
});
}
private function routeConfiguration()
{
return [
//定義訪問路由的域名
//'domain'=>config('telescope.domain',null),
//是定義路由的命名空間
'namespace'=>'Lixiyong\LshopLaravel\Wap\Member\Http\Controllers',
//這是前綴
'prefix'=>'wap/member',
'middleware'=>'web',
];
}
}
演示可在laravelnew\app\routes/web.php中添加路由測試
<?php
use Illuminate\Support\Facades\Auth;
Route::get('/', function () {
dd(Auth::guard('member'));
// dd(config());
});
?>
7.通過組件命令發佈配置文件以及數據庫遷移文件
當然easywechat實際自己就自帶發佈配置文件的命令,但是對於組件來說通常還是自己用自己的最爲合適,顯得更加友好。不過在發佈之前我們首先需要在lshop-laravel/…/config/member.php中添加wechat.php的配置文件的信息;注意再把laravel項目中的config/wechat.php刪除掉 ~~ 是爲了與效果並且修改一下wechat的配置文件的默認值
<?php
return [
'wechat'=>[
'official_account' => [
'default' => [
'app_id' => env('WECHAT_OFFICIAL_ACCOUNT_APPID', 'your-app-id'), // AppID
'secret' => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', 'your-app-secret'), // AppSecret
'token' => env('WECHAT_OFFICIAL_ACCOUNT_TOKEN', 'your-token'), // Token
'aes_key' => env('WECHAT_OFFICIAL_ACCOUNT_AES_KEY', ''), // EncodingAESKey
/*
* OAuth 配置
*
* scopes:公衆平臺(snsapi_userinfo / snsapi_base),開放平臺:snsapi_login
* callback:OAuth授權完成後的回調頁地址(如果使用中間件,則隨便填寫。。。)
*/
'oauth' => [
'scopes' => array_map('trim', explode(',', env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_SCOPES', 'snsapi_userinfo'))),
'callback' => env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_CALLBACK', '/examples/oauth_callback.php'),
],
],
],
],
'auth'=>[
//事先的動作,爲了以後着想
'controller'=>Lixiyong\LshopLaravel\Wap\Member\Http\Controllers\AuthorizationsController::class,
//當前使用的守衛,只是定義
'guard'=>'wap-member',
//定義守衛組
'guards'=>[
'wap-member'=>[
'driver'=>'session',
'provider'=>'member',
],
],
'providers'=>[
'member-user'=>[
'driver'=>'eloquent',
'model'=>Lixiyong\LshopLaravel\Wap\Member\Models\User::class,
]
],
]
];
建議編輯的時候可以再寫一個路由看看laravel對於easywechat的配置信息的加載信息格式
<?php
Route::get('/', function () {
dd(config());
});
?>
用 Arr的dot()方法來對於wap.member.wechat的配置文件的信息與wechat的信息組合完成.修改一下服務提供者的方法
<?php
class MemberServiceProvide extends ServiceProvider
{
public function boot()
{
// ..
$this->loadMemberConfig();
}
// 吧這個組件的auth信息合併到config的auth
protected function loadMemberConfig()
{
// Arr 基礎操方法封裝
// 這個數組合並之後,一定要再此保持laravel項目中
config(Arr::dot(config('wap.member.wechat', []), 'wechat.'));
config(Arr::dot(config('wap.member.auth', []), 'auth.'));
}
}
?>
注意因爲loadMemberAuthConfig()方法本身就是加載member.php中的信息到auth.php中的,而我們的wechat也是如此因此可以直接把他們合在一起方法名改爲loadMemberConfig()然後我們在訪問路由看看效果
配置文件發佈
接下來我們要做的就是發佈配置文件,如下就是我們期望執行的命令
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
我們可以實際上就是運用的Illuminate\Support\ServiceProvider中的publishes()方法
<?php
class ServiceProvider
{
protected function publishes(array $paths, $groups = null)
{
$this->ensurePublishArrayInitialized($class = static::class);
static::$publishes[$class] = array_merge(static::$publishes[$class], $paths);
if (! is_null($groups)) {
foreach ((array) $groups as $group) {
$this->addPublishGroup($group, $paths);
}
}
}
}
?>
修改一下Lixiyong\LshopLaraver\Wap\Member\Providers\MemberServiceProvider
<?php
use Illuminate\Support\ServiceProvider;
class MemberServiceProvide extends ServiceProvider
{
public function register()
{
$this->registerPublishing();
}
public function registerPublishing()
{
if ($this->app->runningInConsole()) {
// [當前組件的配置文件路徑 =》 這個配置複製那個目錄] , 文件標識
// 1. 不填就是默認的地址 config_path 的路徑 發佈配置文件名不會改變
// 2. 不帶後綴就是一個文件夾
// 3. 如果是一個後綴就是一個文件
$this->publishes([__DIR__.'/../config'=>config_path('wap')],'lshop-laravel-wap-member-config');
}
}
}
?>
那麼我們執行發佈的命令就可以直接根據easywechat的方式修改即可
php artisan vendor:publish --provider="Lixiyong\LshopLaravel\Wap\Member\Providers\MemberServiceProvider"
執行效果
laravelnew> php artisan vendor:publish --provider="Lixiyong\LshopLaravel\Wap\Member\Providers\MemberServiceProvider"
Copied Directory [D:\phpstudy_pro\WWW\lixiyong\lshop-laravel\src\Wap\Member\Config] To [\config\wap]
Publishing complete.
數據庫遷移文件
組件中還有一個存在的點就是數據庫的遷移,先不談數據量的問題,至少這個遷移還是需要處理的,不然別人怎麼用你的組件呢是吧…(✪ω✪),
php artisan make:migration create_sys_user_table
完善內容
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSysUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('sys_user', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('nick_name',90);
$table->char('weixin_openid',90)->nullable();
$table->string('image_head',255);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('sys_user');
}
}
然後我們把該文件移動到組件中lixiyong\lshop-laravel\src\Wap\Member\Database\migrations\2019_08_06_131424_create_sys_user_table.php
可以實運用Illuminate\Support\ServiceProvider中的loadMigrationsFrom()方法
<?php
class ServiceProvider
{
protected function loadMigrationsFrom($paths)
{
$this->app->afterResolving('migrator', function ($migrator) use ($paths) {
foreach ((array) $paths as $path) {
$migrator->path($path);
}
});
}
}
?>
修改一下Lixiyong\LshopLaravel\Wap\Member\Providers\MemberServiceProvider
<?php
use Illuminate\Support\ServiceProvider;
class MemberServiceProvide extends ServiceProvider
{
public function register()
{
$this->registerPublishing();
}
public function loadMigrations()
{
if ($this->app->runningInConsole()) {
$this->loadMigrationsFrom(__DIR__.'/../Database/migrations');
}
}
}
?>
組件加載console
首先通過php artisan make:command InstallCommand 創建一個命令類當然這個類位於laravelnew\app\Console\Commands\InstallCommand.php
然後把這個命令類移動到lshop-laravel\src\Wap\Member\Console\Commands\InstallCommand.php注意修改文件中的命名空間以及相關的其他信息 ~ 爲了與方便刪除了基本的註釋
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Console\Commands;
use Illuminate\Console\Command;
class InstallCommand extends Command
{
protected $signature = 'wap-member:install';
protected $description = 'Install the wap-member package';
public function __construct()
{
parent::__construct();
}
public function handle()
{
}
}
組件console與laravel集成
在服務提供者中提供了添加組件console的方法
<?php
namespace Illuminate\Support;
class ServiceProvider {
// ...
public function commands($commands)
{
$commands = is_array($commands) ? $commands : func_get_args();
Artisan::starting(function ($artisan) use ($commands) {
$artisan->resolveCommands($commands);
});
}
// ...
}
?>
修改一下服務提供者Lixiyong\LshopLaravel\Wap\Member\Providers\MemberServiceProvider
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Arr;
class MemberServiceProvide extends ServiceProvider {
protected $commands = [
\Lixiyong\LshopLaravel\Wap\Member\Console\Commands\InstallCommand::class,
];
public function boot(){
$this->commands($this->commands);
}
}
?>
然後測試在laravel項目中執行php artisan查看命令是否加載
完善InstallCommand
那麼在Lixiyong\LshopLaravel\Wap\Member\Console\Commands\InstallCommand中的實現其實就是執行數據庫的遷移命令和數據填充命令即可php artisan migrate以及文件發佈命令
我們可以通過執行Illuminate\Console\Command 中的call()方法調用我們所需要執行的命令
<?php
class Command extends SymfonyCommand
{
public function call($command, array $arguments = [])
{
$arguments['command'] = $command;
return $this->getApplication()->find($command)->run(
$this->createInputFromArguments($arguments), $this->output
);
}
}
?>
那麼對應的InstallCommand代碼
<?php
namespace Lixiyong\LshopLaravel\Wap\Member\Console\Commands;
use Illuminate\Console\Command;
class InstallCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'wap-member:install';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Install the wap-member package';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
//call
$this->call('migrate');
$this->call('vendor:publish',[
//參數表示=>參數值
"--provider"=>"Lixiyong\LshopLaravel\Wap\Member\Providers\MemberServiceProvider"
]);
}
}
效果演示,通過組件的自定義命令就能創建數據庫,以及發佈組件的配置文件
D:\phpstudy_pro\WWW\lixiyong\laravelnew>php artisan wap-member:install
Migrating: 2019_11_13_214221_create_sys_user_table
Migrated: 2019_11_13_214221_create_sys_user_table (0.01 seconds)
Copied Directory [D:\phpstudy_pro\WWW\lixiyong\lshop-laravel\src\Wap\Member\Config] To [\config\wap]
Publishing complete.