步骤
组件项目的基本目录
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 package?1204155766@qq.com
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 package?1204155766@qq.com
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": "1204155766@qq.com"
}
],
"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": "1204155766@qq.com"
}
],
"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": "1204155766@qq.com"
}
],
"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.