Commit 4bf8ca9f authored by 朱招明's avatar 朱招明

init

parents
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
* text=auto
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
CHANGELOG.md export-ignore
/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
/.idea
/.vscode
/.vagrant
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
.env
/smg
/.php_cs.cache
/storage/api-docs/api-docs.json
/storage/api-docs/*.json
/composer.lock
/public/uploads
\ No newline at end of file
.DS_Store
phpunit.phar
/vendor
composer.phar
composer.lock
*.project
.idea/
.php_cs.cache
\ No newline at end of file
<?php
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
$rules = array(
'@PSR2' => true,
'array_syntax' => array(
'syntax' => 'short',
),
'binary_operator_spaces' => array(
'align_double_arrow' => false,
'align_equals' => false,
),
'blank_line_before_return' => true,
'cast_spaces' => true,
'concat_space' => array(
'spacing' => 'none',
),
'ereg_to_preg' => true,
'method_separation' => true,
'no_blank_lines_after_phpdoc' => true,
'no_extra_consecutive_blank_lines' => true,
'no_short_bool_cast' => true,
'no_unneeded_control_parentheses' => true,
'no_unused_imports' => true,
'no_whitespace_in_blank_line' => true,
'ordered_imports' => true,
'phpdoc_align' => true,
'phpdoc_indent' => true,
'phpdoc_inline_tag' => true,
'phpdoc_no_access' => true,
'phpdoc_no_alias_tag' => array(
'type' => 'var',
),
'phpdoc_no_package' => true,
'phpdoc_order' => true,
'phpdoc_scalar' => true,
'phpdoc_separation' => true,
'phpdoc_to_comment' => true,
'phpdoc_trim' => true,
'phpdoc_types' => true,
'phpdoc_var_without_name' => true,
'self_accessor' => true,
'single_quote' => true,
'space_after_semicolon' => true,
'standardize_not_equals' => true,
'ternary_operator_spaces' => true,
'trailing_comma_in_multiline_array' => true,
'trim_array_spaces' => true,
'unary_operator_spaces' => true,
'line_ending' => true,
'blank_line_after_namespace' => true,
'no_unused_imports' => true,
);
return Config::create()->setRules($rules)
->setFinder(
Finder::create()->in(__DIR__)
->exclude('api_annotations')
->exclude('Database')
->exclude('api_annotations')
->exclude('Tests')
)
->setUsingCache(true)
->setRiskyAllowed(true);
<?php
return [
'name' => 'Base',
];
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddExtInfoToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('avatar')->nullable()->comment('用户头像');
//$table->string('introduction')->nullable()->comment('用户说明');
$table->string('phone')->nullable()->unique()->after('name')->comment('用户手机号');
$table->string('email')->nullable()->change();
$table->string('name')->nullable()->change();
$table->tinyInteger('sex')->default(0)->comment('性别');
$table->unsignedInteger('level')->default(0)->comment('等级');
$table->boolean('is_blocked')->default(0)->comment('是否停用');
$table->dateTime('system_notice_lastest_read_at')->default("2019-12-06 00:00:00")->comment('系统消息最近查看时间');
$table->json('ext')->nullable()->comment('用户扩展信息');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('avatar');
//$table->dropColumn('introduction');
$table->dropColumn('phone');
$table->dropColumn('sex');
$table->string('email')->nullable(false)->change();
$table->string('name')->nullable(false)->change();
});
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFilesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('files', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->index()->comment('用户ID');
$table->string('type')->index()->comment('文件类型');
$table->string('path')->comment('文件路径');
$table->integer('size')->default(0)->comment('文件大小');
$table->string('mime')->enablenull()->comment('文件类型');
$table->string('name')->comment('文件名称');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('files');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateOpenidsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('openids', function (Blueprint $table) {
$table->increments('id');
$table->string('type')->index();
$table->string('openid')->index();
$table->string('unionid', 50)->index()->nullable()->comment('唯一ID');
$table->integer('user_id');
$table->unique(['type', 'openid']);
$table->json('extra')->nullable()->comment('额外信息');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('openids');
}
}
<?php
namespace Modules\Base\Database\Seeders;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Seeder;
class BaseDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
// $this->call("OthersTableSeeder");
}
}
<?php
namespace Modules\Base\Entities;
use Illuminate\Database\Eloquent\Model;
class BaseModel extends Model
{
protected $fillable = [];
}
<?php
namespace Modules\Base\Entities;
class File extends BaseModel
{
protected $fillable = ['user_id', 'type', 'path', 'size','mime', 'name'];
}
<?php
namespace Modules\Base\Entities;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use SMG\Support\Traits\HasHttpRequest;
class Openid extends Model
{
use HasHttpRequest;
protected $fillable = ['type', 'openid', 'user_id', 'unionid', 'extra'];
protected $casts = [
'extra' => 'json',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function getUserExt()
{
if ($this->type == 'wx_mini') {
$result = $this->extra;
$data = [];
$data['sex'] = $result['gender'] ?? 0;
$data['name'] = $result['nickName'] ?? null;
$data['avatar'] = isset($result['avatarUrl']) ? $this->downloadAvatar($result['avatarUrl']) : null;
return $data;
} elseif ($this->type == 'weixin') {
$result = $this->extra;
$data = [];
$data['sex'] = $result['sex'] ?? 0;
$data['name'] = $result['nickname'] ?? null;
$data['avatar'] = isset($result['headimgurl']) ? $this->downloadAvatar($result['headimgurl']) : null;
return $data;
}
return [];
}
public function downloadAvatar($avatar_url, $extension = 'png')
{
if (!$avatar_url) {
return null;
}
//微信换成大头像
if (strpos($avatar_url, 'qlogo.cn')) {
$info = explode('/', $avatar_url);
$last = count($info) - 1;
if (in_array($info[$last], ['46', '64', '96', '132'])) {
$info[$last] = '0';
$avatar_url = implode('/', $info);
}
}
$content = $this->httpGet($avatar_url);
if (!$content) {
return null;
}
$folder = config('upload.avatar.folder', 'avatar');
$folder_name = "{$folder}/".date('Ym', time()).'/'.date('d', time()).'/'.uniqid().'.'.$extension;
Storage::disk(config('upload.avatar.filesystem'))->put($folder_name, $content);
return $folder_name;
}
}
<?php
namespace Modules\Base\Entities;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Arr;
use SMG\Support\Traits\Macroable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use Notifiable, Macroable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password', 'avatar', 'ext', 'phone', 'sex',
];
protected $casts = [
'ext' => 'array',
'is_blocked' => 'boolean',
];
protected $appends = ['openid', 'display_name', 'admin_show_name'];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* @return array
*/
public function getJWTCustomClaims()
{
return [
'last_login_time'=> $this->getExt('last_login_time'),
];
}
public function apiLoginAndGetTokenInfo()
{
$auth = \Auth::guard('api');
$this->saveExt(['last_login_time'=> date("Y-m-d H:i:s")]);
return [
'access_token' => $auth->login($this),
'token_type' => 'Bearer',
'expires_in' => $auth->factory()->getTTL() * 60,
];
}
public function saveExt($ext = [])
{
$old = $this->ext ?? [];
$this->ext = array_merge($old, $ext);
$this->save();
}
public function getExt($key, $default = null)
{
$ext = $this->ext ?? [];
return Arr::get($ext, $key, $default);
}
public function getOpenidAttribute()
{
if (!is_array($this->ext)) {
return null;
}
$openid_type = request('openid_type', false);
if ($openid_type) {
return $this->ext[$openid_type.'_openid'] ?? null;
}
foreach ($this->ext as $key => $one) {
if (substr($key, -7) == '_openid') {
return $one;
}
}
return null;
}
public function getShowName2Attribute()
{
if ($this->name) {
return $this->name;
}
$phone = $this->phone;
return substr($phone, 0, 3).'****'.substr($phone, 7);
}
public function getShowNameAttribute()
{
return $this->name ?? $this->phone;
}
public function getAdminShowNameAttribute()
{
return $this->name ? $this->name.'('.$this->phone.')' : $this->phone;
}
public function getDisplayNameAttribute()
{
return $this->name ?? $this->phone;
}
}
<?php
namespace Modules\Base\Events;
use Illuminate\Queue\SerializesModels;
use Modules\Base\Entities\File;
class FileUploaded
{
use SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(File $file)
{
$this->file = $file;
}
/**
* Get the channels the event should be broadcast on.
*
* @return array
*/
public function broadcastOn()
{
return [];
}
}
<?php
namespace Modules\Base\Http\Controllers\Api;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Modules\Base\Http\Controllers\BaseController;
use Modules\Base\Transformers\CommonTransformer;
use Modules\Base\Transformers\BaseTransformer;
class ApiController extends BaseController
{
use \Dingo\Api\Routing\Helpers;
public function paginator(AbstractPaginator $list, BaseTransformer $transform)
{
if ($list instanceof LengthAwarePaginator) {
return $this->response->paginator($list, $transform);
}
return $this->response->collection($list->getCollection(), $transform)
->setMeta(['pagination' => ['per_page' => $list->perPage(), 'current_page' => $list->currentPage(), 'count' => $list->count()]]);
}
public function emptyObject()
{
return $this->response->array(['data' => new \stdClass()]);
}
public function emptyPageData()
{
return $this->response->paginator(new LengthAwarePaginator(collect(), 0, request('per_page', 20)), new CommonTransformer());
}
}
<?php
namespace Modules\Base\Http\Controllers\Api;
use Illuminate\Support\Facades\Auth;
use Modules\Base\Entities\User;
use Modules\Base\Http\Requests\AuthorizationRequest;
use Modules\Base\Http\Requests\OpenloginRequest;
use Modules\Base\Services\NewOpenloginService;
use Modules\Base\Transformers\AccessTokenTransformer;
class AuthorizationsController extends ApiController
{
/**
* 登陆
*
* @param AuthorizationRequest $request
*
* @return mixed
*
* @OA\Post(
* tags={"用户"},
* summary="用户登陆",
* path="/api/base/authorizations",
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"phone","password"},
* @OA\Property(
* property="phone",
* ref="#/components/schemas/phone"
* ),
* @OA\Property(
* property="password",
* ref="#/components/schemas/password"
* ),
* )
* )
* ),
* @OA\Response(
* response="201",
* description="登陆成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Token")
* )
* )
* )
* )
*/
public function store(AuthorizationRequest $request)
{
$user = User::query()->where('phone', $request->phone)->first();
if (!$user) {
throw \Illuminate\Validation\ValidationException::withMessages([
'phone' => ['验证失败,用户不存在'],
]);
}
if ($user->password != \Illuminate\Support\Facades\Hash::check($request->password, $user->password)) {
throw \Illuminate\Validation\ValidationException::withMessages([
'password' => ['密码错误'],
]);
}
return $this->response->item($user, new AccessTokenTransformer())->setStatusCode(201);
}
/**
* @param $type
* @param OpenloginRequest $request
* @param OpenloginService $openlogin
*
* @throws \Throwable
*
* @return \Dingo\Api\Http\Response
*
* @OA\Post(
* tags={"用户"},
* summary="第三方账号登陆",
* path="/api/base/authorizations/openlogin/{type}",
* @OA\Parameter(
* name="type",
* in="path",
* description="第三方登陆类型",
* required=true,
* @OA\Schema(
* type="string",
* )
* ),
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="code",
* type="string"
* ),
* @OA\Property(
* property="bind",
* type="string",
* description="是否是绑定操作,如果是传1,否则可不传"
* )
* )
* )
* ),
* @OA\Response(
* response="201",
* description="登陆成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Token")
* )
* )
* )
* )
*/
public function openlogin($type, OpenloginRequest $request, NewOpenloginService $openlogin)
{
if ($request->get('bind', false)) {
$user = auth('api')->user();
throw_if(!$user, '\Exception', '没有登陆');
} else {
$user = null;
}
$user = $openlogin->login($type, $request->all(), $user);
return $this->response->item($user, new AccessTokenTransformer())->setStatusCode(201);
}
/**
* 登陆
*
* @param SmsLoginRequest $request
*
* @return mixed
*
* @OA\Post(
* tags={"用户"},
* summary="短信登陆",
* path="/api/base/authorizations/sms",
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"phone","password"},
* @OA\Property(
* property="phone",
* ref="#/components/schemas/phone"
* ),
* @OA\Property(
* property="code",
* ref="#/components/schemas/phone_code"
* ),
* )
* )
* ),
* @OA\Response(
* response="201",
* description="登陆成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Token")
* )
* )
* )
* )
*/
public function smsLogin(SmsLoginRequest $request)
{
$user = User::where('phone', $request->phone)->first();
if (!$user) {
throw \Illuminate\Validation\ValidationException::withMessages([
'phone' => ['验证失败,手机号不存在'],
]);
}
abort_if($user->is_blocked, 500, '账户已经停用');
return $this->response->item($user, new AccessTokenTransformer())->setStatusCode(201);
}
/**
* @return mixed
*
* @OA\Put(
* tags={"用户"},
* summary="刷新TOKEN",
* path="/api/base/authorizations/current",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="刷新成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Token")
* )
* )
* )
* )
*/
public function update()
{
return $this->response->item(auth('api')->user(), new AccessTokenTransformer())->setStatusCode(201);
}
/**
* @return mixed
*
* @OA\Delete(
* tags={"用户"},
* summary="用户登出",
* path="/api/base/authorizations/current",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="204",
* description="登出成功"
* )
* )
*/
public function destroy()
{
\Auth::logout();
return $this->response->noContent()->setStatusCode(200);
}
}
<?php
namespace Modules\Base\Http\Controllers\Api;
use Modules\Base\Http\Requests\FileRequest;
use Modules\Base\Services\FileService;
use Modules\Base\Transformers\FileTransformer;
class FilesController extends ApiController
{
/**
* Store a newly created resource in storage.
*
* @param FileRequest $request
* @param FileService $file
*
* @return \Dingo\Api\Http\Response $response
*
* @OA\Post(
* tags={"基础接口"},
* summary="上传文件",
* path="/api/base/files",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* required=true,
* @OA\MediaType(
* mediaType="multipart/form-data",
* @OA\Schema(
* type="object",
* required={"type","file"},
* @OA\Property(
* property="type",
* type="string",
* enum={"avatar"}
* ),
* @OA\Property(
* property="file",
* type="string",
* format="binary"
* ),
* )
* )
* ),
* @OA\Response(
* response="201",
* description="成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/File")
* )
* )
* )
* )
*/
public function store(FileRequest $request, FileService $file)
{
$info = $file->process($request->file, $request->input('type'));
return $this->response->item($info, new FileTransformer())
->setStatusCode(201);
}
}
This diff is collapsed.
<?php
namespace Modules\Base\Http\Controllers\Api;
use Modules\Base\Http\Requests\SmsRequest;
use Modules\Base\Services\SmsService;
class SmsController extends ApiController
{
/**
* @OA\Post(
* tags={"基础接口"},
* summary="发送短信验证码",
* path="/api/base/sms",
* description="type:手机验证码类型:1:注册,2:找回密码,3:更换手机号, 4:添加银行卡, 5:设置支付密码",
* @OA\RequestBody(
* required=true,
* description="xxxyy",
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"captcha_key"},
* @OA\Property(
* property="captcha_key",
* type="string",
* description="验证码KEY",
* ),
* @OA\Property(
* property="captcha_code",
* type="string",
* ),
* @OA\Property(
* property="phone",
* type="string",
* ),
* @OA\Property(
* type="integer",
* property="type",
* description="手机短信类型",
* enum={1,2,3,4,5}
* ),
* )
* )
* ),
* @OA\Response(response="201", description="发送成功")
* )
*/
public function store(SmsRequest $request, SmsService $sms)
{
$sms->send($request->phone, $request->type);
return $this->response->noContent()->setStatusCode(201);
}
}
<?php
namespace Modules\Base\Http\Controllers\Api;
use Modules\Base\Entities\User;
use Modules\Base\Http\Requests\UserRequest;
use Modules\Base\Services\SmsService;
use Modules\Base\Services\UserService;
use Modules\Base\Transformers\UserTransformer;
use SMG\Support\Rules\Mobile;
class UsersController extends ApiController
{
/**
* Store a newly created resource in storage.
*
* @param UserRequest $request
* @param SmsService $sms
* @param UserService $userService
*
* @return \Dingo\Api\Http\Response $response
*
* @OA\Post(
* tags={"用户"},
* summary="用户注册接口",
* path="/api/base/users",
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* required={"phone","password", "code"},
* @OA\Property(
* property="phone",
* ref="#/components/schemas/phone"
* ),
* @OA\Property(
* property="code",
* ref="#/components/schemas/phone_code"
* ),
* @OA\Property(
* property="password",
* ref="#/components/schemas/password"
* ),
* )
* )
* ),
* @OA\Response(
* response="201",
* description="成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/User")
* )
* )
* )
* )
*/
public function store(UserRequest $request, SmsService $sms, UserService $userService)
{
$sms->verifyCode($request->code, $sms::REGISTER, $request->phone);
$request['password'] = \Hash::make($request->password);
$userService->create($request->all());
return $this->response->item($userService->getModel(), new UserTransformer())
->setStatusCode(201);
}
/**
* @return \Dingo\Api\Http\Response
*
* @OA\Get(
* tags={"用户"},
* summary="当前登陆用户信息",
* path="/api/base/user",
* security={
* {"jwt_auth": {}}
* },
* @OA\Response(
* response="200",
* description="成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/User")
* )
* )
* )
* )
*/
public function me()
{
return $this->response->item($this->user(), new UserTransformer());
}
/**
* @return \Dingo\Api\Http\Response
*
* @OA\Get(
* tags={"用户"},
* summary="根据手机号获取用户信息",
* path="/api/base/user_search/{phone}",
* security={
* {"jwt_auth": {}}
* },
* @OA\Parameter(
* name="phone",
* in="path",
* description="用户手机号",
* required=true,
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Response(
* response="200",
* description="成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/User")
* )
* )
* )
* )
*/
public function search($phone)
{
abort_unless((new Mobile())->passes('phone', $phone), 404, '手机号非法');
$user = User::where('phone', $phone)->first();
abort_unless($user, 404, '用户不存在');
return $this->response->item($user, new UserTransformer(true));
}
/**
* Update resource in storage.
*
* @param UserRequest $request
*
* @return \Dingo\Api\Http\Response
*
* @OA\Put(
* tags={"用户"},
* summary="更新用户信息",
* path="/api/base/user",
* security={
* {"jwt_auth": {}}
* },
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="name",
* type="string",
* ),
* @OA\Property(
* property="email",
* ref="#/components/schemas/email"
* ),
* @OA\Property(
* property="file_id",
* type="integer",
* description="文件ID"
* ),
* @OA\Property(
* property="password",
* ref="#/components/schemas/password"
* ),
* @OA\Property(
* property="old_password",
* ref="#/components/schemas/password",
* description="修改密码时才必须",
* ),
* @OA\Property(
* property="phone",
* ref="#/components/schemas/phone",
* description="手机号",
* ),
* @OA\Property(
* property="code",
* ref="#/components/schemas/phone_code",
* description="手机验证码,修改修改号时必须",
* ),
* )
* )
* ),
* @OA\Response(
* response="200",
* description="成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/User")
* )
* )
* )
* )
*/
public function update(UserRequest $request, UserService $user)
{
if ($request->phone) {
$sms = app(SmsService::class);
$sms->verifyCode($request->code, $sms::CHANGE_PHONE, $request->phone);
}
$user->update(\Auth::id(), $request->all());
return $this->response->item($user->getModel(), new UserTransformer());
}
/**
* Update resource in storage.
*
* @param UserRequest $request
*
* @return \Dingo\Api\Http\Response
*
* @OA\Put(
* tags={"用户"},
* summary="重设密码",
* path="/api/base/user/password",
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="phone",
* ref="#/components/schemas/phone"
* ),
* @OA\Property(
* property="code",
* ref="#/components/schemas/phone_code"
* ),
* @OA\Property(
* property="password",
* ref="#/components/schemas/password"
* ),
* )
* )
* ),
* @OA\Response(
* response="204",
* description="成功"
* )
* )
*/
public function password(UserRequest $request, UserService $userService, SmsService $sms)
{
$sms->verifyCode($request->code, $sms::FIND_PASSWORD, $request->phone);
$user = $userService->getModel()->where('phone', $request->phone)->firstOrFail();
$userService->update($user->id, $request->only('password'));
return $this->response->noContent();
}
/**
* Remove the specified resource from storage.
*
* @param int $id
*
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
}
}
<?php
namespace Modules\Base\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller;
class BaseController extends Controller
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/10
* Time: 16:01
*/
namespace Modules\Base\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\MessageBag;
class DownloadController
{
public function download()
{
$data = $this->responseData();
return view('base::download')->with($data);
}
public function upload()
{
$data = $this->responseData();
return view('base::upload')->with($data);
}
public function responseData(): array
{
return db_setting('apk', [
'update_msg' => '未更新过',
'update_time' => '',
'version' => '',
'download_url' => '/uploads/apk/latest.apk',
]);
}
public function saveApk(Request $request)
{
//dd($request->file);
$request->validate([
'file' => ['bail', 'required', 'file', function ($attribute, $value, $fail) {
if ($value->getClientOriginalExtension() != 'apk') {
$fail('不是一个有效的APK文件');
}
}],
'version' => ['required'],
'password' => ['required', 'in:123456'],
]);
$version = $request->get('version', false);
Storage::disk('admin')->putFileAs('apk', $request->file, 'latest_'.$version.'.apk');
if ($version && $version !='0.0.0') {
$setting = db_setting('apk', []);
db_setting_set('apk', array_merge($setting,
[
'version' => $version,
'update_msg' => $request->update_msg,
'update_time' => date("Y-m-d H:i:s"),
'download_url' => '/uploads/apk/latest_'.$version.'.apk',
]));
}
//abort_if(($request->file->getClientOriginalExtension() != $type), 500, '类型错误');
$message = new MessageBag(['type' => 'success', 'title' => '提示', 'message' => '上传成功']);
session()->flash('success', $message);
return back();
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/10
* Time: 16:01
*/
namespace Modules\Base\Http\Controllers;
class HelpController
{
public function showEnumList()
{
$class = request('class', false);
if (!$class) {
return 'CLASS参数缺少';
}
if (!class_exists($class)) {
return 'Class不存在';
}
if (!method_exists($class, 'toArray')) {
return '对应方法不存在';
}
return $class::toArray();
}
}
<?php
namespace Modules\Base\Http\Controllers;
use Illuminate\Routing\Controller;
use Modules\Base\Entities\User;
class UserAvatarController extends Controller
{
public function avatar($user)
{
$user = User::find($user);
$avatar = $user ? $user->avatar : null;
if (!$avatar) {
$avatar = '/image/default_avatar.jpg';
}
if (substr($avatar, 0, 1) != '/' && substr($avatar, 0, 4) != 'http') {
$avatar = config('upload.avatar.url').$avatar;
}
return redirect($avatar);
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/11/10
* Time: 16:01
*/
namespace Modules\Base\Http\Controllers;
use Modules\Base\Entities\User;
use Modules\Base\Services\NewOpenloginService;
use Modules\Base\Services\OpenloginService;
class UserController
{
/**
* 微信公众号登陆(如果已经登陆则绑定 )
*
* @param NewOpenloginService $openloginService
*
* @throws \Throwable
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function wechatLogin(NewOpenloginService $openloginService)
{
$info = session('wechat.oauth_user.default');
$user = auth('api')->user();
$user = $openloginService->login('weixin', $info->original, $user);
$token = \Auth::guard('api')->setTTL(1)->login($user); //安全起见,只一分钟有效
$url = request('back_url', '/h5/#/login_from_token?redirect=%2Fuser').'&token='.$token;
//清除SESSION,不然换账号登陆会是同一个
session()->forget('wechat.oauth_user.default');
return redirect($url);
}
/**
* @param NewOpenloginService $openloginService
*
* @throws \Throwable
*/
public function wechatTest(NewOpenloginService $openloginService)
{
$info = session('wechat.oauth_user.default');
dump($info->original);
try {
$user = $openloginService->login('weixin', $info->original);
dd($user);
} catch (\Exception $e) {
dd($e);
}
dd($info);
}
/**
* @param NewOpenloginService $openloginService
*
* @throws \Throwable
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function wechatBind(NewOpenloginService $openloginService)
{
$user = auth('api')->user();
$back_url = request('back_url', '/h5');
logger('开始绑定微信');
logger('当前用户');
logger($user);
if ($user && !$user->openid) {
$info = session('wechat.oauth_user.default');
logger('微信信息');
logger($info->original);
$user = $openloginService->login('weixin', $info->original, $user);
logger('绑定后用户信息');
logger($user);
}
return redirect($back_url);
}
/**
* @param NewOpenloginService $openloginService
*
* @throws \Throwable
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function wechatLoginTest(NewOpenloginService $openloginService)
{
$info = session('wechat.oauth_user.default');
dump($info);
$user = $openloginService->login('weixin', $info);
dd($user);
//dd($info);
//$info = (object) session('wechat.oauth_user.default');
$user = User::orderBy('id', 'DESC')->first();
$token = \Auth::guard('api')->setTTL(1)->login($user); //安全起见,只一分钟有效
$url = request('back_url', '/wap/#/login_from_token?redirect=%2Fuser').'&token='.$token;
return redirect($url);
}
public function clean()
{
session()->forget('wechat.oauth_user.default');
return 'success';
}
}
<?php
namespace Modules\Base\Http\Middleware;
use Closure;
use Illuminate\Contracts\Session\Session;
use Illuminate\Http\Request;
use Illuminate\Session\SessionManager;
use Illuminate\Support\Carbon;
use Symfony\Component\HttpFoundation\Response;
class StartSession
{
/**
* The session manager.
*
* @var \Illuminate\Session\SessionManager
*/
protected $manager;
/**
* Indicates if the session was handled for the current request.
*
* @var bool
*/
protected $sessionHandled = false;
/**
* Create a new session middleware.
*
* @param \Illuminate\Session\SessionManager $manager
*
* @return void
*/
public function __construct(SessionManager $manager)
{
$this->manager = $manager;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$this->sessionHandled = true;
// If a session driver has been configured, we will need to start the session here
// so that the data is ready for an application. Note that the Laravel sessions
// do not make use of PHP "native" sessions in any way since they are crappy.
if ($this->sessionConfigured() && auth('api')->user()) {
$request->setLaravelSession(
$session = $this->startSession($request)
);
$this->collectGarbage($session);
}
$response = $next($request);
// Again, if the session has been configured we will need to close out the session
// so that the attributes may be persisted to some storage medium. We will also
// add the session identifier cookie to the application response headers now.
if ($this->sessionConfigured()) {
$this->storeCurrentUrl($request, $session);
$this->addCookieToResponse($response, $session);
}
return $response;
}
/**
* Perform any final actions for the request lifecycle.
*
* @param \Illuminate\Http\Request $request
* @param \Symfony\Component\HttpFoundation\Response $response
*
* @return void
*/
public function terminate($request, $response)
{
if ($this->sessionHandled && $this->sessionConfigured() && auth('api')->user()) {
$this->manager->driver()->save();
}
}
/**
* Start the session for the given request.
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Contracts\Session\Session
*/
protected function startSession(Request $request)
{
return tap($this->getSession($request), function ($session) use ($request) {
$session->setRequestOnHandler($request);
$session->start();
});
}
/**
* Get the session implementation from the manager.
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Contracts\Session\Session
*/
public function getSession(Request $request)
{
return tap($this->manager->driver(), function ($session) {
$session_id = 'apiseesion'.auth('api')->id();
$session_id = str_pad($session_id, 40, '0', STR_PAD_LEFT);
$session->setId($session_id);
});
}
/**
* Remove the garbage from the session if necessary.
*
* @param \Illuminate\Contracts\Session\Session $session
*
* @return void
*/
protected function collectGarbage(Session $session)
{
$config = $this->manager->getSessionConfig();
// Here we will see if this request hits the garbage collection lottery by hitting
// the odds needed to perform garbage collection on any given request. If we do
// hit it, we'll call this handler to let it delete all the expired sessions.
if ($this->configHitsLottery($config)) {
$session->getHandler()->gc($this->getSessionLifetimeInSeconds());
}
}
/**
* Determine if the configuration odds hit the lottery.
*
* @param array $config
*
* @return bool
*/
protected function configHitsLottery(array $config)
{
return random_int(1, $config['lottery'][1]) <= $config['lottery'][0];
}
/**
* Store the current URL for the request if necessary.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Contracts\Session\Session $session
*
* @return void
*/
protected function storeCurrentUrl(Request $request, $session)
{
if ($request->method() === 'GET' && $request->route() && !$request->ajax()) {
$session->setPreviousUrl($request->fullUrl());
}
}
/**
* Add the session cookie to the application response.
*
* @param \Symfony\Component\HttpFoundation\Response $response
* @param \Illuminate\Contracts\Session\Session $session
*
* @return void
*/
protected function addCookieToResponse(Response $response, Session $session)
{
$this->manager->driver()->save();
}
/**
* Get the session lifetime in seconds.
*
* @return int
*/
protected function getSessionLifetimeInSeconds()
{
return ($this->manager->getSessionConfig()['lifetime'] ?? null) * 60;
}
/**
* Get the cookie lifetime in seconds.
*
* @return \DateTimeInterface
*/
protected function getCookieExpirationDate()
{
$config = $this->manager->getSessionConfig();
return $config['expire_on_close'] ? 0 : Carbon::now()->addMinutes($config['lifetime']);
}
/**
* Determine if a session driver has been configured.
*
* @return bool
*/
protected function sessionConfigured()
{
return !is_null($this->manager->getSessionConfig()['driver'] ?? null);
}
/**
* Determine if the configured session driver is persistent.
*
* @param array|null $config
*
* @return bool
*/
protected function sessionIsPersistent(?array $config = null)
{
$config = $config ?? $this->manager->getSessionConfig();
return !in_array($config['driver'], [null, 'array']);
}
/**
* Determine if the session is using cookie sessions.
*
* @return bool
*/
protected function usingCookieSessions()
{
return false;
}
}
<?php
namespace Modules\Base\Http\Requests;
class AuthorizationRequest extends BaseRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'phone' => 'bail|required|regex:/^1[3456789][0-9]{9}$/',
'password' => 'required|string|min:6',
];
}
}
<?php
namespace Modules\Base\Http\Requests;
use Dingo\Api\Http\FormRequest;
use Dingo\Api\Http\Request;
class BaseRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$method = strtolower($this->method()).'Rules';
$rules = $this->$method();
foreach ($rules as &$rule) {
if (is_string($rule) && strpos($rule, 'bail') === false) {
$rule = 'bail|'.$rule;
} elseif (is_array($rule) && !in_array('bail', $rule)) {
array_unshift($rule, 'bail');
}
}
return $rules;
}
protected function postRules()
{
return [];
}
protected function getRules()
{
return [];
}
protected function putRules()
{
return [];
}
protected function deleteRules()
{
return [];
}
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* @return bool
*/
public function isApi()
{
if ($this->container['request'] instanceof Request) {
return true;
}
return false;
}
}
<?php
namespace Modules\Base\Http\Requests;
class FileRequest extends BaseRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$upload = config('upload', []);
$types = implode(',', array_keys($upload));
$validate = isset($upload[$this->type]) ? 'required|file|'.$upload[$this->type]['validate'] : 'required|file';
return [
'type' => 'required|in:'.$types,
'file' => $validate,
];
}
public function messages()
{
return config('upload.'.$this->type.'.validate_msg', []);
}
}
<?php
namespace Modules\Base\Http\Requests;
class OpenloginRequest extends BaseRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$type = $this->route('type');
switch ($type) {
case 'test':
case 'wx_mini':
return [
'code' => 'bail|required',
];
}
return [];
}
}
<?php
namespace Modules\Base\Http\Requests;
use Modules\Base\Services\SmsService;
class SmsLoginRequest extends BaseRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'phone' => 'bail|required|regex:/^1[23456789][0-9]{9}$/',
'code' => 'required|string|check_sms:'.$this->phone.','. SmsService::LOGIN,
//'password' => 'required|string|min:6',
];
}
}
<?php
namespace Modules\Base\Http\Requests;
use Modules\Base\Services\Exception\PhoneNullException;
use Modules\Base\Services\SmsService;
class SmsRequest extends BaseRequest
{
/**
* @throws \Throwable
*
* @return array
*/
public function rules()
{
$types = SmsService::getConstantsValues();
$guard = $this->isApi() ? 'api' : null;
if (SmsService::needAuth($this->type)) {
abort_if(auth($guard)->guest(), 401, '需要登陆');
$user = auth($guard)->user();
if (SmsService::needUserPhone($this->type)) {
$phone = $user->phone;
throw_unless($phone, new PhoneNullException());
$this->request->add(['phone' => $phone]);
}
}
$rules = [
'type' => 'required|in:'.implode(',', $types),
'captcha_key' => 'required|string',
'captcha_code' => 'bail|required|captcha_api:'.$this->captcha_key,
//'phone' => 'bail|required|regex:/^1[345789][0-9]{9}$/',
];
if (!SmsService::needUserPhone($this->type)) {
$rules['phone'] = 'bail|required|regex:/^1[23456789][0-9]{9}$/'.SmsService::appendPhoneValidateRule($this->type);
}
return $rules;
}
public function attributes()
{
return [
'captcha_key' => '图片验证码 key',
'captcha_code' => '图片验证码',
'phone' => '手机号',
];
}
public function messages()
{
return [
'captcha_code.captcha_api' => '图片验证码错误或已过期',
];
}
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
}
<?php
namespace Modules\Base\Http\Requests;
use Modules\Base\Services\OpenloginService;
class UserRequest extends BaseRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function postRules()
{
return [
'phone' => 'bail|required|regex:/^1[3456789][0-9]{9}$/|unique:users',
'password' => 'required|string|min:6',
'code' => 'required|string',
];
}
protected function putRules()
{
//找回密码
if (strpos($this->path(), 'password') > 0) {
return [
'phone' => 'bail|required|regex:/^1[3456789][0-9]{9}$/|exists:users',
'password' => 'required|string|min:6',
'code' => 'required|string',
];
}
//更新资料
$user = \Auth::user();
$userId = $user->id;
$needVerifyPhone = $user->phone ? '|required_with:phone' : '';
//当用户手机号为空,且传了encryptedData 和 iv 参数 ,试图解析手机号
if (!$user->phone && $this->encryptedData && $this->iv) {
$data = app(OpenloginService::class)->decryptData($this->iv, $this->encryptedData, $userId);
if ($data && $data['purePhoneNumber']) {
//$this->request->add(['phone' => $data['purePhoneNumber']]);
$this['phone'] = $data['purePhoneNumber'];
}
}
return [
'name' => 'between:1,25',
'email' => 'email|unique:users,email,'.$userId,
//'introduction' => 'max:80',
'file_id' => 'exists:files,id,type,avatar,user_id,'.$userId,
'ext' => 'array',
'old_password' => 'bail|required_with:password|string|min:6|check_password:'.$user->getAuthPassword(),
'password' => 'string|min:6',
'phone' => 'bail|regex:/^1[3456789][0-9]{9}$/|unique:users',
'sex' => 'in:0,1,2',
'code' => 'nullable'.$needVerifyPhone.'|string',
];
}
public function attributes()
{
return [
'old_password' => '旧密码',
];
}
public function messages()
{
return [
'old_password.required_with' => '旧密码不能为空',
];
}
}
<?php
\Route::get('/help/enum', '\Modules\Base\Http\Controllers\HelpController@showEnumList');
\Route::get('/download', '\Modules\Base\Http\Controllers\DownloadController@download');
\Route::get('/upload_apk', '\Modules\Base\Http\Controllers\DownloadController@upload')->middleware('web');
\Route::post('/upload_apk', '\Modules\Base\Http\Controllers\DownloadController@saveApk')->middleware('web');
\Route::get('user/{user}/avatar', '\Modules\Base\Http\Controllers\UserAvatarController@avatar');
//使用微信网页登陆的路由
Route::group([
'prefix' => 'base',
//'middleware' => ['web'],
'middleware' => ['web', '\Overtrue\LaravelWeChat\Middleware\OAuthAuthenticate:snsapi_userinfo'],
'namespace' => 'Modules\Base\Http\Controllers',
], function ($router) {
//微信登陆并添加TOKEN后跳至返回页
$router->get('/user/wechat_login', 'UserController@wechatLogin');
$router->get('/user/wechat_bind', 'UserController@wechatBind');
});
\Route::get('/user/wechat_login_test', '\Modules\Base\Http\Controllers\UserController@wechatLoginTest');
$api = app('Dingo\Api\Routing\Router');
$api->version(
'v1',
array_merge(
[
'namespace' => 'Modules\Base\Http\Controllers\Api',
'prefix' => 'api/base',
],
config('api.defaultSetting', [])
),
function ($api) {
$api->get('/', 'ApiController@index')->name('api.base.home');
// 短信验证码
$api->post('sms', 'SmsController@store')
->name('api.base.sms.store');
// 用户注册
$api->post('users', 'UsersController@store')
->name('api.base.users.store');
// 登录
$api->post('authorizations', 'AuthorizationsController@store')
->name('api.base.authorizations.store');
// 短信登录
$api->post('authorizations/sms', 'AuthorizationsController@smsLogin')
->name('api.base.authorizations.sms');
// 第三方账号登录
$api->post('authorizations/openlogin/{type}', 'AuthorizationsController@openlogin')
->name('api.base.authorizations.openlogin');
//短信重置密码
$api->put('user/password', 'UsersController@password')
->name('api.base.user.password');
// 需要 token 验证的接口
$api->group(['middleware' => 'api.auth'], function ($api) {
// 刷新token
$api->put('authorizations/current', 'AuthorizationsController@update')
->name('api.base.authorizations.update');
// 删除token
$api->delete('authorizations/current', 'AuthorizationsController@destroy')
->name('api.base.authorizations.destroy');
// 文件上传
$api->post('files', 'FilesController@store')
->name('api.base.files.store');
// 当前登录用户信息
$api->get('user', 'UsersController@me')
->name('api.base.user.show');
// 编辑登录用户信息
$api->put('user', 'UsersController@update')
->name('api.base.user.update');
// 根据手机号搜索用户
$api->get('user_search/{phone}', 'UsersController@search')
->name('api.base.user.search');
// 通知列表
$api->get('user/notifications', 'NotificationsController@index')
->name('api.base.user.notifications.index');
// 查看某一条通知
$api->get('user/notifications/{notification_id}', 'NotificationsController@show')
->name('api.base.user.notifications.show');
//发送一个测试的通知消息
$api->post('user/notifications', 'NotificationsController@test')
->name('api.base.user.notifications.test');
// 通知统计
$api->get('user/notification_stats', 'NotificationsController@stats')
->name('api.base.user.notifications.stats');
// 标记消息通知为已读
$api->put('user/read/notifications', 'NotificationsController@read')
->name('api.base.user.notifications.read');
// 公告列表
$api->get('user/announcements', 'NotificationsController@announcement')
->name('api.base.user.notifications.announcement');
});
}
);
<?php
namespace Modules\Base\Listeners;
use \Illuminate\Auth\Events\Authenticated;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class AuthenticatedListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param Authenticated $event
* @return void
*/
public function handle(Authenticated $event)
{
if ($event->user->is_blocked == 1) {
auth()->logout(true);
//abort(500, '账户已经禁用');
}
}
}
<?php
namespace Modules\Base\Listeners;
class ProcessUploadImage
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
}
/**
* Handle the event.
*
* @param object $event
*
* @return void
*/
public function handle($event)
{
$file = $event->file;
$config = config('upload.'.$file->type, []);
if (!isset($config['image_processor']) || !$config['image_processor']) {
return;
}
$root = config('filesystems.disks.'.$config['filesystem'].'.root', false);
$img_file = $root ? $root.'/'.$file->path : get_file_url($file->path, $file->type);
$img = \Image::make($img_file);
$processors = explode('|', $config['image_processor']);
foreach ($processors as $processor) {
$this->process($img, $processor);
}
$img->save();
clearstatcache();
$file->size = filesize($img_file);
$file->save();
}
protected function process($img, $processor)
{
$info = explode(':', $processor);
list($method, $args) = count($info) > 1 ? [$info[0], explode(',', $info[1])] : [$info[0], []];
array_walk($args, function (&$val) {
if ($val == 'null') {
$val = null;
}
if (substr($val, 0, 11) === 'constraint=') {
$param = substr($val, 11);
$val = function ($constraint) use ($param) {
$funcs = explode('&', $param);
foreach ($funcs as $func) {
call_user_func([$constraint, $func]);
}
};
}
});
call_user_func_array([$img, $method], $args);
}
}
<?php
namespace Modules\Base\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class TestNotify extends Notification
{
use Queueable;
protected $info;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct($info)
{
$this->info = $info;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['database'];
//如果用数据库通知记得在.env里面配置好邮件相关参数
//return ['mail', 'database'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'id' => $this->info['id'],
'subject' => $this->info['subject'],
'content' => $this->info['content'],
];
}
}
<?php
namespace Modules\Base\Providers;
use Illuminate\Database\Eloquent\Factory;
use Illuminate\Support\ServiceProvider;
use Modules\Base\Events\FileUploaded;
use Modules\Base\Listeners\ProcessUploadImage;
use Modules\Base\Services\SmsService;
class BaseServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Boot the application events.
*
* @return void
*/
public function boot()
{
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->registerFactories();
$this->loadMigrationsFrom(__DIR__.'/../Database/Migrations');
//密码验证
\Validator::extend('check_password', function ($attribute, $value, $parameters, $validator) {
$hashed_password = blank($parameters) ? \Auth::user()->getAuthPassword() : $parameters[0];
return \Hash::check($value, $hashed_password);
});
\Validator::replacer('check_password', function ($message, $attribute, $rule, $parameters) {
return '密码验证失败';
});
//密码验证
\Validator::extend('check_sms', function ($attribute, $value, $parameters, $validator) {
$data = $validator->getData();
$phone = $parameters[0] ?? array_get($data, 'phone');
$type = $parameters[1] ?? array_get($data, 'type');
if (!$type || !$phone) {
return false;
}
return app(SmsService::class)->verifyCode($value, $type, $phone, true);
});
\Validator::replacer('check_sms', function ($message, $attribute, $rule, $parameters) {
return '手机验证码错误或已过期,请重试';
});
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
// API 模型找不到时返回404
\API::error(static function (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
abort(404);
});
//API没有权限返回403
\API::error(static function (\Illuminate\Auth\Access\AuthorizationException $exception) {
abort(403, $exception->getMessage());
});
//API请求验证错误
\API::error(static function (\Illuminate\Validation\ValidationException $exception) {
throw new \Dingo\Api\Exception\ValidationHttpException($exception->errors());
});
//图片上传事件
$this->app['events']->listen(FileUploaded::class, ProcessUploadImage::class);
$this->app['events']->listen("Illuminate\Auth\Events\Authenticated", "Modules\Base\Listeners\AuthenticatedListener");
}
/**
* Register config.
*
* @return void
*/
protected function registerConfig()
{
$this->publishes([
__DIR__.'/../Config/config.php' => config_path('base.php'),
], 'config');
$this->mergeConfigFrom(
__DIR__.'/../Config/config.php',
'base'
);
}
/**
* Register views.
*
* @return void
*/
public function registerViews()
{
$viewPath = resource_path('views/modules/base');
$sourcePath = __DIR__.'/../Resources/views';
$this->publishes([
$sourcePath => $viewPath,
], 'views');
$this->loadViewsFrom(array_merge(array_map(function ($path) {
return $path.'/modules/base';
}, \Config::get('view.paths')), [$sourcePath]), 'base');
}
/**
* Register translations.
*
* @return void
*/
public function registerTranslations()
{
$langPath = resource_path('lang/modules/base');
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, 'base');
} else {
$this->loadTranslationsFrom(__DIR__.'/../Resources/lang', 'base');
}
}
/**
* Register an additional directory of factories.
*
* @return void
*/
public function registerFactories()
{
if (!app()->environment('production')) {
app(Factory::class)->load(__DIR__.'/../Database/factories');
}
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [];
}
}
基础模块
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{$error->page_title}}</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css">
<!-- Styles -->
<style>
html, body {
background-color: #fff;
color: #636b6f;
font-family: 'Nunito', sans-serif;
font-weight: 100;
height: 100vh;
margin: 0;
}
.full-height {
height: 100vh;
}
.flex-center {
align-items: center;
display: flex;
justify-content: center;
}
.position-ref {
position: relative;
}
.content {
text-align: center;
}
.title {
font-size: 36px;
padding: 20px;
}
</style>
</head>
<body>
<div class="flex-center position-ref full-height">
<div class="content">
<div class="title">
{{$error->getMessage()}}
</div>
@if(!$error->disable_return)
<div><a href="/h5">返回首页</a></div>
@endif
</div>
</div>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
@extends('base::layouts.master')
@section('content')
<h1>Hello World</h1>
<p>
This view is loaded from module: {!! config('base.name') !!}
</p>
@stop
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Module Base</title>
{{-- Laravel Mix - CSS File --}}
{{-- <link rel="stylesheet" href="{{ mix('css/base.css') }}"> --}}
</head>
<body>
@yield('content')
{{-- Laravel Mix - JS File --}}
{{-- <script src="{{ mix('js/base.js') }}"></script> --}}
</body>
</html>
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<!-- Fonts -->
<link rel="dns-prefetch" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
<main class="py-4">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
@if($success = session()->get('success'))
<div class="alert alert-success alert-dismissable">
<h4><i class="icon fa fa-check"></i>{{ \Illuminate\Support\Arr::get($success->get('title'), 0) }}</h4>
<p>{!! \Illuminate\Support\Arr::get($success->get('message'), 0) !!}</p>
</div>
@endif
@if($update_msg)
<div class="alert alert-success alert-dismissable">
<h4><i class="icon fa fa-check"></i>更新时间:{!! $update_time !!}</h4>
@if($update_msg)<p>更新信息:{!! $update_msg !!}</p>@endif
@if($version)<p>版本:{!! $version !!}</p>@endif
</div>
@endif
<div class="card">
<div class="card-header">上传APK包</div>
<div class="card-body">
<form method="POST" action="/upload_apk" aria-label="{{ __('Login') }}" enctype="multipart/form-data">
@csrf
<div class="form-group row">
<label for="phone" class="col-sm-4 col-form-label text-md-right">APK文件</label>
<div class="col-md-6">
<input id="phone" type="file" class="form-control{{ $errors->has('file') ? ' is-invalid' : '' }}" name="file" value="{{ old('file') }}" required autofocus>
@if ($errors->has('file'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('file') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">上传密码</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>
@if ($errors->has('password'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row">
<label for="version" class="col-md-4 col-form-label text-md-right">版本</label>
<div class="col-md-6">
<input id="version" type="text" class="form-control{{ $errors->has('version') ? ' is-invalid' : '' }}" name="version" value="{{ old('version') }}" required>
@if ($errors->has('version'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('version') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row">
<label for="update_msg" class="col-md-4 col-form-label text-md-right">更新信息</label>
<div class="col-md-6">
<textarea id="update_msg" class="form-control{{ $errors->has('update_msg') ? ' is-invalid' : '' }}" name="update_msg" required>{{old('update_msg')}}</textarea>
@if ($errors->has('update_msg'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('update_msg') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('上传') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</body>
</html>
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2020/5/14
* Time: 18:56
*/
namespace Modules\Base\Services;
class ApiDataModifyService
{
public function __invoke($key, &$content) {
if ($key == 'change_shipment_info_key') {
$content = 'bbb';
}
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/13
* Time: 9:52
*/
namespace Modules\Base\Services;
class BaseService
{
protected $model;
public function create($data)
{
return $this->model = $this->model->create($data)->refresh();
}
public function update($id, $data)
{
$this->model = $this->model->find($id);
$this->model->fill($data);
return $this->model->save();
}
public function getModel()
{
return $this->model;
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/10/11
* Time: 12:01
*
* 使用方式,请在 AppServiceProvider 里面的 register 方法添加
$this->app->extend(\Illuminate\Config\Repository::class, function ($config){
return new \Modules\Base\Services\ConfigExtendService($config);
});
*/
namespace Modules\Base\Services;
use Illuminate\Config\Repository;
class ConfigExtendService extends Repository
{
protected $config;
public function __construct($config)
{
$this->config = $config;
}
public function has($key)
{
return $this->config->has($key);
}
public function get($key, $default = null)
{
if (is_array($key)) {
return $this->getMany($key);
}
//$keys = explode('.', $key);
/*
$maps = $this->config->get('config_from_setting', []);
if (isset($maps[$key])) {
return \SMG\Support\Setting\Setting::get($maps[$key], $default);
}
*/
/*
if (isset($maps[$keys[0]])) {
if (is_string($maps[$keys]))
$keys[0] = $maps[$keys[0]];
$key = implode('.', $maps);
return \SMG\Support\Setting\Setting::get($key, $default);
}
*/
if ($key == 'mall.product.use_score_percent.default') {
return nf(\SMG\Support\Setting\Setting::get('common.maximum_point_deduction_percentage', $default)/100, 4);
}
return $this->config->get($key, $default);
}
public function all()
{
return $this->config->all();
}
public function set($key, $value = null)
{
return $this->config->set($key, $value);
}
public function prepend($key, $value)
{
return $this->config->prepend($key, $value);
}
public function push($key, $value)
{
return $this->config->push($key, $value);
}
public function offsetExists($offset)
{
return $this->config->offsetExists($offset);
}
public function offsetGet($offset)
{
return $this->config->offsetGet($offset);
}
public function offsetSet($offset, $value)
{
return $this->config->offsetSet($offset, $value);
}
public function offsetUnset($offset)
{
return $this->config->offsetUnset($offset);
}
public function getMaps()
{
static $map;
if ($map === null) {
$map = $this->config->get('config_from_setting', []);
}
}
public function __call($name, $arguments)
{
return $this->config->$name(...$arguments);
}
}
<?php
namespace Modules\Base\Services;
class CustomQueryFilterService
{
public function customXXX($model, $query, $value = null)
{
$this->checkModel($model, 'xxx');
}
protected function checkModel($model, $class)
{
throw_if(get_class($model) != $class, '\Exception', '未定义的查询');
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/10/12
* Time: 10:33
*/
namespace Modules\Base\Services\Exception;
use Throwable;
class DisplayException extends \Exception
{
public $disable_return = false;
public $page_title = '错误';
public function __construct(string $message = "", int $code = 0, Throwable $previous = null, $disable_return = false, $title = '错误')
{
parent::__construct($message, $code, $previous);
$this->disable_return = $disable_return;
$this->page_title = $title;
}
public function render()
{
$agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
if (strpos($agent, 'okhttp')!==false || strpos($agent, 'bai bian shang cheng')!== false) {
$is_app = true;
} else {
$is_app = false;
}
return view('base::display_error', ['error'=>$this]);
}
public function report()
{
return null;
}
public static function throwIf($condition, $message, $disable_return = false, $title = '错误')
{
if ($condition) {
throw new static($message, 0, null, $disable_return, $title);
}
return true;
}
public static function throw($message, $disable_return = false, $title = '错误')
{
throw new static($message, 0, null, $disable_return, $title);
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/8/22
* Time: 10:42
*/
namespace Modules\Base\Services\Exception;
use Throwable;
class PhoneNullException extends \Exception
{
public function __construct(string $message = null, int $code = 0, ?Throwable $previous = null)
{
$message = $message ?? '您还没有设置手机号';
parent::__construct($message, 102, $previous);
}
public static function make($message = '')
{
return new static($message);
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/14
* Time: 14:47
*/
namespace Modules\Base\Services;
use Modules\Base\Entities\File;
use Modules\Base\Events\FileUploaded;
class FileService extends BaseService
{
public function __construct(File $file)
{
$this->model = $file;
}
public function process($file, $type)
{
$config = config('upload', []);
$folder = $config[$type]['folder'];
$folder_name = "$folder/".date('Ym', time()).'/'.date('d', time());
$path = $file->store($folder_name, $config[$type]['filesystem']);
$info = [];
$info['user_id'] = \Auth::id();
$info['type'] = $type;
$info['path'] = $path;
$info['size'] = $file->getSize();
$info['mime'] = $file->getMimeType();
$info['name'] = $file->getClientOriginalName();
$this->create($info);
event(new FileUploaded($this->model));
return $this->model;
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/13
* Time: 9:53
*/
namespace Modules\Base\Services;
use Illuminate\Support\Facades\Log;
use Modules\Base\Entities\Openid;
use Modules\Base\Entities\User;
use Modules\Base\Services\Exception\DisplayEexception;
use Modules\Base\Services\OpenLogin\Weixin;
use SMG\Support\Traits\HasHttpRequest;
class NewOpenloginService extends BaseService
{
use HasHttpRequest;
public function __construct(Openid $openid, UserService $userService)
{
//$this->model = $openid;
//$this->userService = $userService;
}
public static function getTypes()
{
return ['wx_mini', 'test', 'weixin', 'wx_app'];
}
/**
* @param $type
* @param $data
* @param null $assocUser
*
* @throws \Throwable
*
* @return null
*/
public function login($type, $data, $assocUser = null)
{
//获取在OPENID表中的信息,没有会新建一个
$openUser = $this->getOpenLogin($type, $data);
$binded = $assocUser && $openUser->user_id && $assocUser->id != $openUser->user_id;
if ($binded) {
$msg = '试图绑定的微信账号已经于另一个账号进行了绑定';
if (request()->is('*api*')) {
throw new \Exception($msg);
} else {
throw new DisplayEexception($msg.',你可以继续浏览,但支付时将会出现问题');
}
}
//如果没有传关联账号
if (!$assocUser) {
if ($openUser->user_id) {
$assocUser = User::find($openUser->user_id);
//原绑定用户已删除
if (!$assocUser) {
$assocUser = $this->createUser($openUser);
$openUser->user_id = $assocUser->id;
$openUser->save();
}
} else {
$assocUser = $this->createUser($openUser);
}
}
/*
* 更新用户信息
*/
if (!is_array($assocUser->ext) || !isset($assocUser->ext[$type.'_openid'])) {
$assocUser->saveExt([$type => $openUser->extra, $type.'_openid' => $openUser->openid]);
}
if (!$openUser->user_id) {
$openUser->user_id = $assocUser->id;
$openUser->save();
}
return $assocUser;
}
protected function createUser($openUser)
{
$type = $openUser->type;
$data = ['password' => 'temp', 'ext' => [$type => $openUser->extra, $type.'_openid' => $openUser->openid]] + $openUser->getUserExt();
$data['password'] = \Hash::make($data['password']);
return User::create($data);
}
/**
* @param $type
* @param $data
*
* @throws \Throwable
*
* @return mixed
*/
public function getOpenLogin($type, $data)
{
throw_unless(
in_array($type, self::getTypes()),
\Illuminate\Validation\ValidationException::withMessages([
'type' => ['错误的登陆类型'],
])
);
$info = $this->parseInfo($type, $data);
throw_if(!$info['openid'], '\Exception', '未获取到OPENID');
$openLogin = Openid::firstOrNew(['openid' => $info['openid']], $info);
if (!$openLogin->user_id && $openLogin->unionid) {
$same = Openid::where(['unionid' => $openLogin->unionid])->first();
if ($same) {
$openLogin->user_id = $same->user_id;
$openLogin->save();
}
}
return $openLogin;
}
protected function parseInfo($type, $data)
{
if ($type == 'wx_mini') {
$use_unionid = true;
$result = $this->getWxMini($data, $use_unionid);
if (!$use_unionid) {
return [
'type' => $type,
'openid' => $result['openid'],
'unionid' => $result['unionid'] ?? null,
'extra' => $result,
];
}
return [
'type' => $type,
'openid' => $result['openId'],
'unionid' => $result['unionId'] ?? null,
'extra' => $result,
];
} elseif ($type == 'weixin') {
//$info = Weixin::getAccessToken();
//$result = Weixin::getUserInfo($info['access_token'], $info['openid']);
//Log::channel('openlogin')->info('office_account');
//Log::channel('openlogin')->info($result);
$result = $data;
return [
'type' => $type,
'openid' => $result['openid'],
'unionid' => $result['unionid'] ?? null,
'extra' => $result,
];
} elseif ($type == 'wx_app') {
$info = Weixin::getAccessToken();
$result = Weixin::getUserInfo($info['access_token'], $info['openid']);
Log::channel('openlogin')->info('app_account');
Log::channel('openlogin')->info($result);
//$result = $data;
return [
'type' => $type,
'openid' => $result['openid'],
'unionid' => $result['unionid'] ?? null,
'extra' => $result,
];
} elseif ($type == 'test') {
return [
'type' => $type,
'openid' => $data['code'],
];
}
return [];
}
protected function getWxMini($data, $use_unionid = false)
{
if (!isset($data['code']) || !$data['code']) {
throw \Illuminate\Validation\ValidationException::withMessages([
'code' => ['code必须'],
]);
}
$app = app('wechat.mini_program');
$result = $app->auth->session($data['code']);
Log::channel('openlogin')->info('wx_mini');
Log::channel('openlogin')->info($result);
if (isset($result['errcode'])) {
throw \Illuminate\Validation\ValidationException::withMessages([
'code' => [$result['errmsg']],
]);
}
if (!$use_unionid) {
return $result;
}
if (!isset($data['encryptedData']) || !$data['encryptedData']) {
throw \Illuminate\Validation\ValidationException::withMessages([
'encryptedData' => ['encryptedData必须'],
]);
}
if (!isset($data['iv']) || !$data['iv']) {
throw \Illuminate\Validation\ValidationException::withMessages([
'iv' => ['iv必须'],
]);
}
$decryptedData = $app->encryptor->decryptData($result['session_key'], $data['iv'], $data['encryptedData']);
Log::channel('openlogin')->info($decryptedData);
return $decryptedData;
}
/**
* 小程序解密数据
*
* @param $iv
* @param $encryptData
* @param int $user_id
*
* @return bool|array
*/
public function decryptData($iv, $encryptData, $user_id = 0)
{
$user_id || $user_id = auth()->id();
if (!$user_id) {
return false;
}
$openid = $this->model->where('user_id', $user_id)->where('type', 'weixin')->first();
$session_key = array_get($openid, 'session_key');
if (!$session_key) {
return false;
}
$app = app('wechat.mini_program');
$decryptedData = $app->encryptor->decryptData($session_key, $iv, $encryptData);
if ($decryptedData && isset($decryptedData)) {
return $decryptedData;
}
return false;
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/12/28
* Time: 12:28
*/
namespace Modules\Base\Services\OpenLogin;
class Weixin
{
public static function getAccessToken($code = null)
{
if ($code == null) {
$code = request('code');
}
abort_unless($code, 500, 'code必须');
$url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.config('wechat.app.appid').'&secret='.config('wechat.app.secret').'&code='.$code.'&grant_type=authorization_code';
$info = file_get_contents($url);
abort_unless($info, 500, '获取TOKEN错误');
$data = @json_decode($info, true);
if (!$data || isset($data['errmsg'])) {
\Log::error('获取微信TOKEN返回信息错误');
\Log::error($info);
$msg = $data['errmsg'] ?? '';
abort(500, '获取微信TOKEN返回信息错误'.$msg);
}
return $data;
}
public static function getUserInfo($accessToken, $openId)
{
$url = 'https://api.weixin.qq.com/sns/userinfo?access_token='.$accessToken.'&openid='.$openId;
$info = file_get_contents($url);
abort_unless($info, 500, '获取用户信息错误');
$data = @json_decode($info, true);
if (!$data || isset($data['errmsg'])) {
\Log::error('获取微信TOKEN返回信息错误');
\Log::error($info);
$msg = $data['errmsg'] ?? '';
abort(500, '获取微信TOKEN返回信息错误'.$msg);
}
return $data;
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/12
* Time: 17:35
*/
namespace Modules\Base\Services;
use SMG\Support\Traits\ConstantInfo;
class SmsService extends BaseService
{
use ConstantInfo;
public const REGISTER = 1;
public const FIND_PASSWORD = 2;
public const CHANGE_PHONE = 3;
public const ADD_CARD = 4;
public const SET_PAY_PASSWORD = 5;
public const LOGIN = 6;
/**
* 检查要发送的类型是应该向新手机号发还是已经存在的手机号发
*
* @param $type
*
* @return bool
*/
public static function needNewPhone($type)
{
return in_array($type, [self::REGISTER, self::CHANGE_PHONE]);
}
/**
* 短信验证时附加检查规则
*
* @param $type
*
* @return string
*/
public static function appendPhoneValidateRule($type)
{
switch ($type) {
case self::REGISTER:
case self::CHANGE_PHONE:
return '|unique:users';
case self::FIND_PASSWORD:
case self::SET_PAY_PASSWORD:
return '|exists:users';
default:
return '';
}
}
/**
* 发送该类型短信是否需要登陆
*
* @param $type
*
* @return string
*/
public static function needAuth($type)
{
switch ($type) {
case self::CHANGE_PHONE:
case self::SET_PAY_PASSWORD:
return true;
default:
return false;
}
}
/**
* 发送该类型短信是否需要检查手机号信息
*
* @param $type
*
* @return string
*/
public static function needUserPhone($type)
{
return in_array($type, [self::SET_PAY_PASSWORD]);
}
public static function getTypes()
{
$oClass = new \ReflectionClass(static::class);
return array_values($oClass->getConstants());
}
public function send($phone, $type, $args = [])
{
$this->generateCode($phone, $type);
return true;
}
public function generateCode($phone, $type)
{
$code = '1234';
$key = 'sms_'.$type.'_'.$phone;
\Cache::put($key, $code, 5);
return $code;
}
/**
* @param $code
* @param $type
* @param $phone
* @param bool $return
*
* @return bool
*/
public function verifyCode($code, $type, $phone, $return = false)
{
if (env('IGNORE_SMS_CHECK', 'false') == 'true') {
return true;
}
if ($code == '88888888') {
return true;
}
$key = 'sms_'.$type.'_'.$phone;
if ($code != '' && \Cache::get($key) == $code) {
//\Cache::forget($key);
return true;
}
if ($return) {
return false;
}
$error = \Illuminate\Validation\ValidationException::withMessages([
'code' => ['手机验证码错误或已过期,请重试'],
]);
throw $error;
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/13
* Time: 9:53
*/
namespace Modules\Base\Services;
use Modules\Base\Entities\File;
use Modules\Base\Entities\User;
class UserService extends BaseService
{
public function __construct(User $user)
{
$this->model = $user;
}
public function update($id, $data)
{
if (isset($data['file_id'])) {
$file = File::find($data['file_id']);
$file && ($data['avatar'] = $file['path']);
}
if (isset($data['password'])) {
$data['password'] = \Hash::make($data['password']);
}
if (isset($data['ext'])) {
$old = auth()->user()->ext;
$data['ext'] = array_merge($old, $data['ext']);
}
return parent::update($id, $data);
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/15
* Time: 9:47
*/
namespace Modules\Base\Transformers;
use Illuminate\Support\Traits\Macroable;
class AccessTokenTransformer extends BaseTransformer
{
use Macroable;
protected $availableIncludes = ['user'];
/**
* @OA\Schema(
* description="Token信息",
* type="object",
* schema="Token",
* @OA\Property(property="access_token", type="string", description="Token"),
* @OA\Property(property="token_type", type="string", description="Token类型"),
* @OA\Property(property="expires_in", type="integer", description="过期时间"),
* @OA\Property(property="user", type="object", description="用户", @OA\Property(property="data", type="object", ref="#/components/schemas/User"))
* )
*/
public function transform($user)
{
return [
'access_token' => \Auth::guard('api')->login($user),
'token_type' => 'Bearer',
'expires_in' => \Auth::guard('api')->factory()->getTTL() * 60,
];
}
public function includeUser($user)
{
return $this->item($user, new UserTransformer());
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/8
* Time: 12:20
*/
namespace Modules\Base\Transformers;
use Illuminate\Notifications\DatabaseNotification;
use Illuminate\Support\Carbon;
use SMG\Page\PageModel;
class AnnouncementTransformer extends BaseTransformer
{
protected $last_read_at;
public function __construct($last_read_at)
{
parent::__construct();
if (is_string($last_read_at)) {
$last_read_at = Carbon::parse($last_read_at);
}
$this->last_read_at = $last_read_at;
}
/**
* @OA\Schema(
* description="系统公告信息",
* type="object",
* schema="Announcement",
* @OA\Property(property="id", type="integer", description="ID"),
* @OA\Property(property="type", type="string", description="通知类型"),
* @OA\Property(property="title", type="object", description="通知标题"),
* @OA\Property(property="content", type="object", description="通知内容"),
* @OA\Property(property="is_read", type="string", description="是否已查看"),
* @OA\Property(property="created_at", type="string", description="注册时间"),
* @OA\Property(property="updated_at", type="string", description="更新时间")
* )
*/
public function transform(PageModel $table)
{
$fields = map_attr($table, ['id', 'title', 'img', 'content', 'click', 'created_at', 'introduce', 'author', 'flag1', 'flag2', 'flag3', 'flag4']);
$last_read_at = $this->last_read_at;
if ($last_read_at->gt($table->created_at)) {
$fields['is_read'] = true;
} else {
$fields['is_read'] = false;
}
return $fields;
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/27
* Time: 17:44
*/
namespace Modules\Base\Transformers;
use League\Fractal\TransformerAbstract;
class BaseTransformer extends TransformerAbstract
{
protected static $extraIncludes = [];
protected static $extraDefaultIncludes = [];
public function __construct()
{
if (!isset(static::$extraIncludes[static::class])) {
static::$extraIncludes[static::class] = [];
}
if (!isset(static::$extraDefaultIncludes[static::class])) {
static::$extraDefaultIncludes[static::class] = [];
}
$this->availableIncludes = array_merge($this->availableIncludes, static::$extraIncludes[static::class]);
$this->defaultIncludes = array_merge($this->defaultIncludes, static::$extraDefaultIncludes[static::class]);
}
public static function addIncludes($name)
{
if (!isset(static::$extraIncludes[static::class])) {
static::$extraIncludes[static::class] = [];
}
$name = (array) $name;
$temp = [];
foreach ($name as $key => $value) {
if (is_string($key) && $value instanceof \Closure) {
static::macro('include'.ucfirst($key), $value);
$value = $key;
}
$temp[] = $value;
}
static::$extraIncludes[static::class] = array_merge(static::$extraIncludes[static::class], $temp);
}
public static function addDefaultIncludes($name)
{
if (!isset(static::$extraDefaultIncludes[static::class])) {
static::$extraDefaultIncludes[static::class] = [];
}
static::$extraDefaultIncludes[static::class] += (array) $name;
}
/**
* 修改返回
*
* @param $arr
*
* @return mixed
*/
public function alter($arr)
{
return $arr;
}
public static function checkExtraInclude($key)
{
static $extra_includes;
if ($extra_includes == null) {
$extra_includes = array_map('trim', explode(',', request('extra_include', '')));
}
return array_search($key, $extra_includes) === false ? false : true;
}
public function single($value, $transformer)
{
return $value ? $this->item($value, $transformer) : null;
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/15
* Time: 9:47
*/
namespace Modules\Base\Transformers;
use League\Fractal\TransformerAbstract;
class CommonTransformer extends TransformerAbstract
{
public function transform($data)
{
return (array) $data;
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/15
* Time: 9:47
*/
namespace Modules\Base\Transformers;
use Modules\Base\Entities\File;
class FileTransformer extends BaseTransformer
{
/**
* @OA\Schema(
* description="文件信息",
* type="object",
* schema="File",
* @OA\Property(property="id", type="integer", description="ID"),
* @OA\Property(property="name", type="string", description="文件名"),
* @OA\Property(property="path", type="string", description="文件路径"),
* @OA\Property(property="mime", type="string", description="MIME类型"),
* @OA\Property(property="type", type="string", description="文件类型"),
* @OA\Property(property="url", type="string", description="访问URL"),
* @OA\Property(property="created_at", type="string", description="注册时间"),
* @OA\Property(property="updated_at", type="string", description="更新时间")
* )
*/
public function transform(File $file)
{
return map_attr($file, [
'id', 'name', 'path', 'type', 'mime', 'created_at', 'updated_at',
'url' => get_file_url($file->path, $file->type),
]);
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/8
* Time: 12:20
*/
namespace Modules\Base\Transformers;
use Illuminate\Notifications\DatabaseNotification;
class NotificationTransformer extends BaseTransformer
{
/**
* @OA\Schema(
* description="通知信息",
* type="object",
* schema="Notification",
* @OA\Property(property="id", type="integer", description="ID"),
* @OA\Property(property="type", type="string", description="通知类型"),
* @OA\Property(property="data", type="object", description="通知数据"),
* @OA\Property(property="read_at", type="string", description="查看时间"),
* @OA\Property(property="created_at", type="string", description="注册时间"),
* @OA\Property(property="updated_at", type="string", description="更新时间")
* )
*/
public function transform(DatabaseNotification $notification)
{
return map_attr($notification, ['id', 'type', 'data', 'read_at', 'created_at', 'updated_at']);
}
}
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/6/13
* Time: 11:12
*/
namespace Modules\Base\Transformers;
use Illuminate\Support\Traits\Macroable;
use Modules\Base\Entities\User;
class UserTransformer extends BaseTransformer
{
use Macroable;
protected $hideDetail = false;
public function __construct($hideDetail = false)
{
$this->hideDetail = $hideDetail;
parent::__construct();
}
/**
* @OA\Schema(
* description="用户信息",
* type="object",
* schema="User",
* @OA\Property(property="id", type="integer", description="用户ID"),
* @OA\Property(property="name", type="string", description="用户名"),
* @OA\Property(property="email", type="string", description="邮箱"),
* @OA\Property(property="phone", type="string", description="手机号"),
* @OA\Property(property="created_at", type="string", description="注册时间"),
* @OA\Property(property="updated_at", type="string", description="更新时间")
* )
*/
public function transform(User $user)
{
$return = ['id', 'name', 'avatar', 'phone', 'sex', 'level', 'show_name2', 'is_shareholder', 'shareholder_count', 'level_title'];
if ($this->hideDetail) {
$phone = $user->phone;
$user->phone = substr($phone, 0, 3).'****'.substr($phone, 7);
} else {
$return = array_merge($return,['email', 'avatar', 'phone', 'created_at', 'updated_at']);
}
return map_attr($user, $this->alter($return));
}
}
<?php
/**
* API START!
*
* @author syw
*
* @OA\OpenApi(
* @OA\Info(
* version="1.0.0",
* title="接口",
* description="<b>通用状态码</b>:
* 200 成功
* 201 成功创建
* 204 执行成功,没有返回内容
*
* 401 没有登陆
* 403 没有权限
* 404 要操作的资源不存在
* 405 操作方法不允许
* 422 参数验证错误
* 500 程序出现错误
*",
* )
* )
*/
/**
* @OA\SecurityScheme(
* securityScheme="jwt_auth",
* type="http",
* scheme="bearer",
* bearerFormat="JWT",
* )
*
* @OA\Get(
* tags={"基础接口"},
* summary="获取验证码",
* path="/api/captcha",
* @OA\Response(
* response="200",
* description="验证码信息",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(property="data", type="object", ref="#/components/schemas/Verify")
* )
* )
* )
* )
*
*
* @OA\Get(
* tags={"基础接口"},
* summary="缩略图",
* path="/imagecache/{template}/{image_path}",
* @OA\Parameter(
* name="template",
* in="path",
* description="图片处理模板,默认有 small,medium,large三种",
* required=true,
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="image_path",
* in="path",
* description="储存的文件名,程序保存时的路径",
* required=true,
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Response(
* response="200",
* description="处理后的图片",
* @OA\MediaType(
* mediaType="image/png",
* @OA\Schema(
* type="string",
* format="binary",
* )
* ),
* @OA\MediaType(
* mediaType="image/jpg",
* @OA\Schema(
* type="string",
* format="binary",
* )
* ),
* @OA\MediaType(
* mediaType="image/jpeg",
* @OA\Schema(
* type="string",
* format="binary",
* )
* ),
* @OA\MediaType(
* mediaType="image/gif",
* @OA\Schema(
* type="string",
* format="binary",
* )
* )
* )
* )
*
* @OA\Schema(
* description="请求验证错误422",
* type="object",
* schema="error422",
* @OA\Property(property="message", type="string", description="422 Unprocessable Entity"),
* @OA\Property(property="error", type="object", description="错误",
* @OA\Property(property="key", type="array", description="请求键值",
* @OA\Items(type="string", description="具体错误"),
* ),
* ),
* @OA\Property(property="status_code", type="integer", description="状态码422", example=422),
* @OA\Property(property="debug", type="object", description="错误调试信息")
* )
*
*
*
* @OA\Schema(
* description="验证码信息",
* type="object",
* schema="Verify",
* @OA\Property(property="sensitive", type="boolean", description="验证码是否大小写敏感"),
* @OA\Property(property="key", type="string", description="验证码KEY"),
* @OA\Property(property="img", type="string", description="验证码图片(base64图片编码)")
* )
*
* @OA\Schema(
* description="手机号",
* type="string",
* schema="phone",
* minLength=11
* )
*
* @OA\Schema(
* description="密码",
* type="string",
* schema="password",
* minLength=6
* )
*
* @OA\Schema(
* description="手机短信验证码",
* type="string",
* schema="phone_code",
* minLength=4
* )
*
* @OA\Schema(
* description="邮箱",
* type="string",
* schema="email"
* )
*
* @OA\Schema(
* description="1为是,0为否",
* type="integer",
* enum={0,1},
* schema="yesno"
* )
*
* @OA\Schema(
* description="验证码KEY",
* type="string",
* schema="captcha_key"
* )
*
* @OA\Schema(
* description="验证码",
* type="string",
* schema="captcha_code"
* )
*/
\ No newline at end of file
{
"name": "smg/base-module",
"description": "Base Module",
"type": "laravel-module",
"authors": [
{
"name": "Evens",
"email": "syw0602@163.com"
}
],
"extra": {
"laravel": {
"providers": [
"Modules\\Base\\Providers\\BaseServiceProvider"
],
"aliases": {
}
}
},
"autoload": {
"psr-4": {
"Modules\\Base\\": ""
}
}
}
{
"name": "Base",
"alias": "base",
"description": "",
"keywords": [],
"active": 1,
"order": 0,
"providers": [
"Modules\\Base\\Providers\\BaseServiceProvider"
],
"aliases": {},
"files": [
"start.php"
],
"requires": []
}
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"cross-env": "^5.1.4",
"laravel-mix": "^2.1",
"laravel-mix-merge-manifest": "^0.1.1"
}
}
\ No newline at end of file
<?php
/*
|--------------------------------------------------------------------------
| Register Namespaces and Routes
|--------------------------------------------------------------------------
|
| When your module starts, this file is executed automatically. By default
| it will only load the module's route file. However, you can expand on
| it to load anything else from the module, such as a class or view.
|
*/
if (!app()->routesAreCached()) {
require __DIR__.'/Http/routes.php';
}
const { mix } = require('laravel-mix');
require('laravel-mix-merge-manifest');
mix.setPublicPath('../../public').mergeManifest();
mix.js(__dirname + '/Resources/assets/js/app.js', 'js/base.js')
.sass(__dirname + '/Resources/assets/sass/app.scss', 'css/base.css');
if (mix.inProduction()) {
mix.version();
}
\ No newline at end of file
<?php
return [
'name' => 'Project'
];
<?php
namespace Modules\Project\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class ProjectDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
// $this->call("OthersTableSeeder");
}
}
This diff is collapsed.
This diff is collapsed.
<?php
namespace Modules\Project\Http\Controllers\Api;
use Modules\Base\Http\Controllers\Api\ApiController;
class ConfigController extends ApiController
{
/**
* 配置信息
*
* @return mixed
*
* @OA\Get(
* tags={"基础接口"},
* summary="配置信息",
* path="/api/configs",
* @OA\Response(
* response="200",
* description="成功",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="object",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(),
* description="配置项"
* ),
* )
* )
* )
* )
*/
public function index()
{
$config = [
//'point_convert_fee_rate' => db_config('point_convert_fee_rate', 0.13),
//'shop_point_rate' => db_config('shop_point_rate', 0.2),
];
return $this->response->array(['data' => $config]);
}
}
<?php
namespace Modules\Project\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller;
class ProjectController extends Controller
{
/**
* Display a listing of the resource.
* @return Response
*/
public function index()
{
return view('project::index');
}
/**
* Show the form for creating a new resource.
* @return Response
*/
public function create()
{
return view('project::create');
}
/**
* Store a newly created resource in storage.
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
}
/**
* Show the specified resource.
* @return Response
*/
public function show()
{
return view('project::show');
}
/**
* Show the form for editing the specified resource.
* @return Response
*/
public function edit()
{
return view('project::edit');
}
/**
* Update the specified resource in storage.
* @param Request $request
* @return Response
*/
public function update(Request $request)
{
}
/**
* Remove the specified resource from storage.
* @return Response
*/
public function destroy()
{
}
}
<?php
/*
* admin
*/
Route::group([
'prefix' => config('admin.route.prefix'),
'middleware' => config('admin.route.middleware'),
'namespace' => 'Modules\Project\Http\Controllers\Admin',
], function ($router) {
$router->resource('user', 'UserController');
//会员
$router->get('/user/org/{user_id}', 'UserController@org');
//资产
$router->get('/wallet', 'WalletController@index');
//入金日志
$router->get('/wallet/money_log', 'WalletController@moneyLog');
$router->get('/wallet/admin_money_log', 'WalletController@adminMoneyLog');
//修改积分
$router->get('/wallet/add_point', 'WalletController@addPoint');
$router->post('/wallet/add_point', 'WalletController@addPoint');
//设置支付密码
$router->get('/wallet/password', 'WalletController@password');
$router->post('/wallet/password', 'WalletController@password');
//__AUTO_INSERT_ADMIN_ROUTE_PLACE__
});
$api = app('Dingo\Api\Routing\Router');
$api->version(
'v1',
array_merge(
[
'namespace' => 'Modules\Project\Http\Controllers\Api',
'prefix' => 'api',
],
config('api.defaultSetting', [])
),
function ($api) {
//公共配置信息
$api->get('configs', 'ConfigController@index')->name('api.configs');
//__AUTO_INSERT_API_ROUTE_PLACE__
// 需要 token 验证的接口
$api->group(['middleware' => 'api.auth'], function ($api) {
//__AUTO_INSERT_AUTH_API_ROUTE_PLACE__
});
}
);
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/7/8
* Time: 18:52
*/
namespace Modules\Project\Listeners;
use SMG\Mall\Events\OrderCreatedEvent;
class OrderCreateListener
{
public function handle(OrderCreatedEvent $event)
{
$order = $event->order;
// if ($order->type != 'default') {
// return;
// }
// $user = $order->user;
// $parent = $user->invitation ? ($user->invitation->parent ? $user->invitation->parent->user : 0) : null;
// if ($parent) {
// $order->parent_id = $parent->id;
// $order->save();
// }
}
}
<?php
namespace Modules\Project\Listeners;
use Modules\Project\Services\JCYPService;
use Modules\Project\Services\MLDService;
use SMG\Mall\Listeners\OrderStatusChangeListenerBase;
class OrderStatusChangeListener extends OrderStatusChangeListenerBase
{
public function afterPaid()
{
$order = $this->order;
//(new \Modules\Project\Services\RewardService)->orderPaid($order);
}
public function afterShipped()
{
$order = $this->order;
(new \Modules\Project\Services\RewardService())->orderComplete($order);
}
public function afterClosed()
{
$order = $this->order;
}
public function afterCancelled()
{
$order = $this->order;
}
}
<?php
namespace Modules\Project\Listeners;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Modules\Base\Entities\UserAgentDoukuai;
use Modules\Base\Entities\UserDoukuaiCode;
use Modules\Project\Services\CardOrderRewardService;
use Modules\Project\Services\DoukuaiUserService;
use Modules\Project\Services\UserDaoyoudaoService;
use SMG\Pay\Events\PaymentSuccessEvent;
use SMG\Pay\Models\Pay;
class PaymentSuccessListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
public function handle(PaymentSuccessEvent $event)
{
$pay = $event->pay;
$model_type = $pay->model; //union
//用户抖快模式升级
if ($model_type == 'xxxx') {
}
}
}
<?php
namespace Modules\Project\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Factory;
use Modules\Project\Services\MacroService;
class ProjectServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Boot the application events.
*
* @return void
*/
public function boot()
{
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->registerFactories();
$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
Event::listen('SMG\Mall\Events\OrderStatusChangeEvent', 'Modules\Project\Listeners\OrderStatusChangeListener');
Event::listen('SMG\Pay\Events\PaymentSuccessEvent', 'Modules\Project\Listeners\PaymentSuccessListener');
//添加一系列宏
app(MacroService::class)->addMacro();
$userClass = get_user_model();
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
/**
* Register config.
*
* @return void
*/
protected function registerConfig()
{
$this->publishes([
__DIR__.'/../Config/config.php' => config_path('project.php'),
], 'config');
$this->mergeConfigFrom(
__DIR__.'/../Config/config.php', 'project'
);
}
/**
* Register views.
*
* @return void
*/
public function registerViews()
{
$viewPath = resource_path('views/modules/project');
$sourcePath = __DIR__.'/../Resources/views';
$this->publishes([
$sourcePath => $viewPath
],'views');
$this->loadViewsFrom(array_merge(array_map(function ($path) {
return $path . '/modules/project';
}, \Config::get('view.paths')), [$sourcePath]), 'project');
}
/**
* Register translations.
*
* @return void
*/
public function registerTranslations()
{
$langPath = resource_path('lang/modules/project');
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, 'project');
} else {
$this->loadTranslationsFrom(__DIR__ .'/../Resources/lang', 'project');
}
}
/**
* Register an additional directory of factories.
*
* @return void
*/
public function registerFactories()
{
if (! app()->environment('production')) {
app(Factory::class)->load(__DIR__ . '/../Database/factories');
}
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [];
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment