基于laravel的微信商城组件之会员组件(1)


组件项目的基本目录

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值