Commit 7f1a9930 by 叶明星

合并分支

parents eeab48cf 910b4cfd
Showing with 1096 additions and 3260 deletions
......@@ -23,4 +23,14 @@ SYSTEM_NAME=IC业务助手福利中心服务
//laravels监听IP和端口
LARAVELS_LISTEN_IP=0.0.0.0
LARAVELS_LISTEN_PORT=61009
\ No newline at end of file
LARAVELS_LISTEN_PORT=61009
REDIS_HOST=192.168.1.235
REDIS_PASSWORD=icDb29mLy2s
REDIS_PORT=6379
REDIS_READ_HOST=192.168.1.235
REDIS_READ_PASSWORD=icDb29mLy2s
REDIS_READ_PORT=6379
......@@ -6,14 +6,22 @@ namespace App\Http\Controllers;
use App\Http\Filters\ExchangeSettingFilter;
use App\Models\ExchangeSetting;
use App\Models\Integral;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* 红包兑换项管理
* Class ExchangeSettingsController
* @package App\Http\Controllers
*/
class ExchangeSettingsController extends Controller
{
/**
* 单个红包兑换项详细信息
* @param Request $request
* @return array
*/
public function show(Request $request)
{
$id = $request->id;
......@@ -22,73 +30,133 @@ class ExchangeSettingsController extends Controller
return $this->Export(0, 'ok', ['data' => $exchangeSetting]);
}
public function index(Request $request, ExchangeSettingFilter $filter)
/**
* 红包商品兑换项列表
* @param Request $request
* @param ExchangeSetting $exchangeSetting
* @param ExchangeSettingFilter $filter
* @return array
*/
public function index(Request $request, ExchangeSetting $exchangeSetting, ExchangeSettingFilter $filter)
{
$page = $request->has('page') ? $request->page : 1;
$page_size = $request->has('page_size') ? $request->page_size : 10;
$page = $request->has('page') ? $request->page : self::DEFAULT_PAGE;
$pageSize = $request->has('page_size') ? $request->page_size : self::DEFAULT_PAGE_SIZE;
$settings = ExchangeSetting::filter($filter)
->page($page, $page_size)
->orderBy('id', 'desc')
->get()->toArray();
$count = ExchangeSetting::filter($filter)->count();
$result = $exchangeSetting->getExchangeSettingList($page, $pageSize, $filter);
return $this->Export(0, 'ok', ['data' => $settings, 'count' => $count]);
return $this->Export(0, 'ok', $result);
}
public function store(Request $request)
/**
* 存储新增的兑换商品项目
* @param Request $request
* @param ExchangeSetting $exchangeSetting
* @return array
*/
public function store(Request $request, ExchangeSetting $exchangeSetting)
{
$res = DB::table('exchange_settings')->insert([
$data = [
'name' => $request->name,
'stock' => $request->stock,
'amount' => $request->amount,
'type' => $request->type,
'add_time' => time(),
'status' => $request->status,
]);
];
$res = $exchangeSetting->addExchangeSetting($data);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(041, 5), '新增积分信息失败');
return $this->Export(ErrorCode(11, 5), '新增兑换商品项目失败');
}
}
/**
* 更新兑换商品项目
* @param Request $request
* @param ExchangeSetting $exchangeSetting
* @return array
*/
public function update(Request $request, ExchangeSetting $exchangeSetting)
{
$id = $request->id;
$data = [
'name' => $request->name,
'amount' => $request->amount,
'stock' => $request->stock,
'type' => $request->type,
'status' => $request->status,
'update_time' => time(),
];
$res = $exchangeSetting->updateExchangeSetting($id, $data);
if (!$res) {
return $this->Export(12, '更新兑换商品项目失败');
} else {
return $this->Export(0, 'ok');
}
}
public function update(Request $request)
/**
* 修改配置项是否可用状态
* @param Request $request
* @param ExchangeSetting $exchangeSetting
* @return array
*/
public function updateStatus(Request $request, ExchangeSetting $exchangeSetting)
{
$id = $request->id;
$data = array_merge($request->all(), ['update_time' => time()]);
$res = DB::table('exchange_settings')->where('id', $id)
->update($data);
$status = $request->status;
$data = [
'status' => $status,
'update_time' => time(),
];
$res = $exchangeSetting->updateExchangeSetting($id, $data);
return $this->Export(0, 'ok');
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(14, '修改兑换商品项目可使用状态失败');
}
}
public function destroy(Request $request)
/**
* 删除兑换商品项目
* @param Request $request
* @param ExchangeSetting $exchangeSetting
* @return array
*/
public function destroy(Request $request, ExchangeSetting $exchangeSetting)
{
$ids = $request->ids;
$ids = explode(',', trim($ids));
$res = DB::table('exchange_settings')->whereIn('id', $ids)->delete();
$res = $exchangeSetting->deleteExchangeSetting($ids);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(043, 5), '删除积分信息失败');
return $this->Export(ErrorCode(13, 5), '删除兑换商品项目失败');
}
}
public function batchUpdateStatus(Request $request)
/**
* 批量更新兑换商品项目状态
* @param Request $request
* @param ExchangeSetting $exchangeSetting
* @return array
*/
public function batchUpdateStatus(Request $request, ExchangeSetting $exchangeSetting)
{
$ids = $request->ids;
if (!is_array($ids)) {
return Log::Info('批量修改参数不是数组');
}
$status = $request->status;
$result = DB::table('exchange_settings')
->whereIn('id', $ids)
->update(['status' => (int)$status, 'update_time' => time()]);
return $this->Export(0, 'ok');
// return $this->Export(033, '批量修改用户积分失败');
$res = $exchangeSetting->batchUpdateStatus($status, $ids);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(15, 5), '批量更新兑换商品项目可使用状态失败');
}
}
}
\ No newline at end of file
<?php
namespace App\Http\Controllers;
use App\Http\Filters\IntegralBillFilter;
use App\Http\Filters\UserIntegralFilter;
use App\Models\IntegralBill;
use App\Models\UserIntegral;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class IntegralBillsController extends Controller
{
public function index(Request $request, IntegralBillFilter $filter)
{
$page = $request->has('page') ? $request->page : 1;
$page_size = $request->has('page_size') ? $request->page_size : 10;
$bills = IntegralBill::with('integral')->filter($filter)->page($page, $page_size)
->orderBy('id', 'desc')
->get()->toArray();
$count = IntegralBill::filter($filter)->count();
return $this->Export(0, 'ok', ['data' => $bills, 'count' => $count]);
}
public function create(Request $request)
{
$res = DB::table('integral_bills')->insert([
'user_id' => $request->user_id,
'amount' => $request->amount,
'integral_id' => $request->integral_id,
'status' => 1,
'add_time' => time(),
]);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(021, 5), '新增积分账单失败');
}
}
public function update(Request $request)
{
$id = $request->id;
$res = DB::table('integral_bills')->where('id', $id)
->update([
'user_id' => $request->user_id,
'amount' => $request->amount,
'integral_id' => $request->integral_id,
'status' => 1,
'update_time' => time(),
]);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(022, 5), '更新积分账单失败');
}
}
public function destroy(Request $request)
{
$ids = $request->ids;
$ids = explode(',', trim($ids));
$res = DB::table('integral_bills')->whereIn('id', $ids)->delete();
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(023, 5), '删除积分账单失败');
}
}
<?php
namespace App\Http\Controllers;
use App\Http\Filters\IntegralBillFilter;
use App\Http\Filters\IntegralFilter;
use App\Models\IntegralBill;
use Illuminate\Http\Request;
/**
* 用户红包获取流水(非兑现)
* Class IntegralBillsController
* @package App\Http\Controllers
*/
class IntegralBillsController extends Controller
{
/**
* 用户红包获取流水列表
* @param Request $request
* @param IntegralBill $integralBill
* @param IntegralBillFilter $filter
* @return array
*/
public function index(Request $request, IntegralBill $integralBill, IntegralBillFilter $filter)
{
$page = $request->has('page') ? $request->page : self::DEFAULT_PAGE;
$pageSize = $request->has('page_size') ? $request->page_size : self::DEFAULT_PAGE_SIZE;
$res = $integralBill->getIntegralBillList($page, $pageSize, $filter);
return $this->Export(0, 'ok', $res);
}
/**
* 创建红包获取记录
* @param Request $request
* @param IntegralBill $integralBill
* @return array
*/
public function create(Request $request, IntegralBill $integralBill)
{
$data = [
'user_id' => $request->user_id,
'amount' => $request->integral_amount,
'integral_id' => $request->integral_id,
'status' => 1,
'add_time' => time(),
];
$res = $integralBill->createIntegralBill($data);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(6, 5), '新增红包获取记录失败');
}
}
/**
* 更新红包获取记录
* @param Request $request
* @param IntegralBill $integralBill
* @return array
*/
public function update(Request $request, IntegralBill $integralBill)
{
$id = $request->id;
$data = [
'user_id' => $request->user_id,
'amount' => $request->amount,
'integral_id' => $request->integral_id,
'status' => 1,
'update_time' => time(),
];
$res = $integralBill->updateIntegralBill($id, $data);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(7, 5), '更新红包获取记录失败');
}
}
/**
* 删除红包获取记录
* @param Request $request
* @param IntegralBill $integralBill
* @return array
*/
public function destroy(Request $request, IntegralBill $integralBill)
{
$ids = $request->ids;
$ids = explode(',', trim($ids));
$res = $integralBill->deleteIntegralBill($ids);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(8, 5), '删除红包获取记录失败');
}
}
}
\ No newline at end of file
<?php
namespace App\Http\Controllers;
use App\Models\IntegralType;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class IntegralTypesController extends Controller
{
public function index()
{
$integrals = IntegralType::all()->toArray();
return $this->Export(0, 'ok', ['data' => $integrals]);
}
public function create(Request $request)
{
$res = DB::table('integral_types')->insert([
'name' => $request->name,
'add_time' => time(),
'status' => 1,
]);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(011, 5), '新增积分信息失败');
}
}
public function update(Request $request)
{
$id = $request->id;
$res = DB::table('integral_types')->where('id', $id)
->update([
'name' => $request->name,
'status' => $request->status,
]);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(012, 5), '更新积分信息失败');
}
}
public function destroy(Request $request)
{
$ids = $request->ids;
$ids = explode(',', trim($ids));
$res = DB::table('integral_types')->whereIn('id', $ids)->delete();
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(013, 5), '删除积分信息失败');
}
}
}
\ No newline at end of file
......@@ -10,8 +10,18 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* 红包基础信息管理
* Class IntegralsController
* @package App\Http\Controllers
*/
class IntegralsController extends Controller
{
/**
* 单个红包信息
* @param Request $request
* @return array
*/
public function show(Request $request)
{
$id = $request->id;
......@@ -20,72 +30,140 @@ class IntegralsController extends Controller
return $this->Export(0, 'ok', ['data' => $integral]);
}
public function index(Request $request, IntegralFilter $filter)
/**
* 红包列表
* @param Request $request
* @param Integral $integral
* @param IntegralFilter $filter
* @return array
*/
public function index(Request $request, Integral $integral, IntegralFilter $filter)
{
$page = $request->has('page') ? $request->page : 1;
$page_size = $request->has('page_size') ? $request->page_size : 10;
$page = $request->has('page') ? $request->page : self::DEFAULT_PAGE;
$pageSize = $request->has('page_size') ? $request->page_size : self::DEFAULT_PAGE_SIZE;
$integrals = Integral::with('integralType:id,name')
->filter($filter)
->page($page, $page_size)
->orderBy('id', 'desc')
->get()->toArray();
$count = Integral::count();
if ($request->has('is_api') && $request->is_api) {
$result = $integral->getIntegralListForApi();
} else {
$result = $integral->getIntegralList($page, $pageSize, $filter);
}
return $this->Export(0, 'ok', ['data' => $integrals, 'count' => $count]);
return $this->Export(0, 'ok', $result);
}
public function create(Request $request)
/**
* 创建红包
* @param Request $request
* @param Integral $integral
* @return array
*/
public function create(Request $request, Integral $integral)
{
$res = DB::table('integrals')->insert([
$data = [
'name' => $request->name,
'description' => $request->description,
'daily_limit' => $request->daily_limit,
'amount' => $request->amount,
'add_time' => time(),
'status' => $request->status,
]);
];
$res = $integral->addIntegral($data);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(001, 5), '新增积分信息失败');
return $this->Export(ErrorCode(1, 5), '新增红包信息失败');
}
}
public function update(Request $request)
/**
* 更新红包
* @param Request $request
* @param Integral $integral
* @return array
*/
public function update(Request $request, Integral $integral)
{
$id = $request->id;
$data = array_merge($request->all(), ['update_time' => time()]);
$res = DB::table('integrals')->where('id', $id)
->update($data);
$data = [
'name' => $request->name,
'description' => $request->description,
'amount' => $request->amount,
'status' => $request->status,
'daily_limit' => $request->daily_limit,
'update_time' => time(),
];
return $this->Export(0, 'ok');
$res = $integral->updateIntegral($id, $data);
if (!$res) {
return $this->Export(2, '更新红包信息失败');
} else {
return $this->Export(0, 'ok');
}
}
public function batchUpdateStatus(Request $request)
/**
* 删除红包
* @param Request $request
* @param Integral $integral
* @return array
*/
public function destroy(Request $request, Integral $integral)
{
$ids = $request->ids;
if (!is_array($ids)) {
return Log::Info('批量修改参数不是数组');
$ids = explode(',', trim($ids));
$res = $integral->deleteIntegral($ids);
if (!$res) {
return $this->Export(ErrorCode(3, 5), '删除红包信息失败');
} else {
return $this->Export(0, 'ok');
}
$status = $request->status;
$result = DB::table('integrals')
->whereIn('id', $ids)
->update(['status' => (int)$status]);
return $this->Export(0, 'ok');
// return $this->Export(033, '批量修改用户积分失败');
}
public function destroy(Request $request)
/**
* 更新红包是否可用状态
* @param Request $request
* @param Integral $integral
* @return array
*/
public function updateStatus(Request $request, Integral $integral)
{
$ids = $request->ids;
$ids = explode(',', trim($ids));
$res = DB::table('integrals')->whereIn('id', $ids)->delete();
$id = $request->id;
$status = $request->status;
$data = [
'status' => $status,
'update_time' => time(),
];
$res = $integral->updateIntegral($id, $data);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(ErrorCode(003, 5), '删除积分信息失败');
return $this->Export(5, '修改红包可使用状态失败');
}
}
/**
* 批量更改状态
* @param Request $request
* @param Integral $integral
* @return array
*/
public function batchUpdateStatus(Request $request, Integral $integral)
{
$ids = $request->get('ids');
if (!is_array($ids)) {
Log::Info('批量修改参数不是数组');
return $this->Export(44, '批量修改参数不是数组');
}
$status = $request->status;
$data = ['status' => $status, 'update_time' => time()];
$res = $integral->batchUpdateStatus($ids, $data);
if (!$res) {
return $this->Export(4, '批量更新红包可使用状态失败');
} else {
return $this->Export(0, 'ok');
}
}
......
......@@ -14,52 +14,94 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* 用户红包兑换管理
* Class UserExchangesController
* @package App\Http\Controllers
*/
class UserExchangesController extends Controller
{
/**
* @param Request $request
* @return array
*/
public function show(Request $request)
{
$id = $request->id;
$userExchange = UserExchange::where('user_id', $id)->first()->toArray();
$userExchange = UserExchange::with('exchange_setting')->where('id', $id)->first()->toArray();
return $this->Export(0, 'ok', ['data' => $userExchange]);
}
public function index(Request $request, UserExchangeFilter $filter)
/**
* 用户兑换红包列表
* @param Request $request
* @param UserExchange $userExchange
* @param UserExchangeFilter $filter
* @return array
*/
public function index(Request $request, UserExchange $userExchange, UserExchangeFilter $filter)
{
$page = $request->has('page') ? $request->page : 1;
$pageSize = $request->has('page_size') ? $request->page_size : 10;
$page = $request->has('page') ? $request->page : self::DEFAULT_PAGE;
$pageSize = $request->has('page_size') ? $request->page_size : self::DEFAULT_PAGE_SIZE;
$userExchanges = UserExchange::filter($filter)->page($page, $pageSize)
->orderBy('id', 'desc')
->get()->toArray();
$count = UserExchange::filter($filter)->count();
$res = $userExchange->getUserExchangeList($page, $pageSize, $filter);
return $this->Export(0, 'ok', ['data' => $userExchanges, 'count' => $count]);
return $this->Export(0, 'ok', $res);
}
public function update(Request $request)
{
$id = $request->id;
$data = array_merge($request->all(), ['update_time' => time()]);
$res = DB::table('user_exchanges')->where('id', $id)
->update($data);
return $this->Export(0, 'ok');
/**
* 审核用户的兑换
* @param Request $request
* @param UserExchange $userExchange
* @return array
*/
public function audit(Request $request, UserExchange $userExchange)
{
$data = [
'audit_reason' => $request->audit_reason,
'audit_time' => time(),
'update_time' => time(),
'audit_id' => $request->audit_id,
'user_id' => $request->user_id,
'audit_email' => $request->audit_email,
'status' => $request->status,
];
$res = $userExchange->auditUserExchange($request->id, $request->exchange_amount, $data);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(16, '审核用户兑换失败');
}
}
public function batchUpdateStatus(Request $request)
/**
* 批量审核
* @param Request $request
* @param UserExchange $userExchange
* @return array
*/
public function batchAuditReject(Request $request, UserExchange $userExchange)
{
$ids = $request->ids;
if (!is_array($ids)) {
return Log::Info('批量修改参数不是数组');
}
$status = $request->status;
$result = DB::table('user_exchanges')
->whereIn('id', $ids)
->update(['status' => (int)$status]);
return $this->Export(0, 'ok');
// return $this->Export(033, '批量修改用户积分失败');
$data = [
'status' => (int)$request->status,
'audit_reason' => $request->audit_reason,
'audit_id' => $request->audit_id,
'audit_email' => $request->audit_email,
'update_time' => time(),
];
$res = $userExchange->batchAuditRejectUserExchange($ids, $data);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(17, '审核批量拒绝兑换失败');
}
}
//用于抢兑换名额(接口自己需要先验证是否能)
......
......@@ -5,18 +5,27 @@ namespace App\Http\Controllers;
use App\Http\Filters\UserIntegralFilter;
use App\Models\Integral;
use App\Models\IntegralBill;
use App\Models\UserIntegral;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* 用户红包详情列表
* Class UserIntegralsController
* @package App\Http\Controllers
*/
class UserIntegralsController extends Controller
{
/**
* 查看用户红包情况
* @param Request $request
* @return array
*/
public function show(Request $request)
{
$id = $request->id;
$integral = UserIntegral::where('user_id', $id)->first();
$userId = $request->get('id');
$integral = UserIntegral::where('user_id', $userId)->first();
$integral = $integral ?: [];
return $this->Export(0, 'ok', ['data' => $integral]);
......@@ -24,38 +33,82 @@ class UserIntegralsController extends Controller
}
public function index(Request $request, UserIntegralFilter $filter)
/**
* 用户红包详情列表
* @param Request $request
* @param UserIntegral $userIntegral
* @param UserIntegralFilter $filter
* @return array
*/
public function index(Request $request, UserIntegral $userIntegral, UserIntegralFilter $filter)
{
$integrals = UserIntegral::filter($filter)->page($request->page, $request->page_size)
->orderBy('id', 'desc')
->get()->toArray();
$count = UserIntegral::filter($filter)->count();
$page = $request->has('page') ? $request->page : self::DEFAULT_PAGE;
$pageSize = $request->has('page_size') ? $request->page_size : self::DEFAULT_PAGE_SIZE;
$res = $userIntegral->getUserIntegralList($page, $pageSize, $filter);
return $this->Export(0, 'ok', ['data' => $integrals, 'count' => $count]);
return $this->Export(0, 'ok', $res);
}
public function update(Request $request)
/**
* 更新用户红包可领取状态
* @param Request $request
* @param UserIntegral $userIntegral
* @return array
*/
public function updateStatus(Request $request, UserIntegral $userIntegral)
{
$id = $request->id;
$data = array_merge($request->all(), ['update_time' => time()]);
$res = DB::table('user_integrals')->where('id', $id)
->update($data);
$data = [
'status' => $request->status,
'update_time' => time(),
];
$res = $userIntegral->updateUserIntegral($id, $data);
return $this->Export(0, 'ok');
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(9, '修改用户红包可领取状态失败');
}
}
public function batchUpdateStatus(Request $request)
/**
* 批量修改用户是否能够领取红包
* @param Request $request
* @param UserIntegral $userIntegral
* @return array
*/
public function batchUpdateStatus(Request $request, UserIntegral $userIntegral)
{
$ids = $request->ids;
if (!is_array($ids)) {
return Log::Info('批量修改参数不是数组');
}
$status = $request->status;
$result = DB::table('user_integrals')
->whereIn('id', $ids)
->update(['status' => (int)$status]);
return $this->Export(0, 'ok');
// return $this->Export(033, '批量修改用户积分失败');
$data = ['status' => (int)$request->status, 'update_time' => time()];
$res = $userIntegral->batchUpdateStatus($ids, $data);
if ($res) {
return $this->Export(0, 'ok');
} else {
return $this->Export(10, '批量修改用户是否可领取红包失败');
}
}
/**
* 单个用户的红包兑换统计信息
* @param Request $request
* @param IntegralBill $integralBill
* @return array
*/
public function statistics(Request $request, IntegralBill $integralBill)
{
$userId = $request->user_id;
$result = $integralBill->getUserIntegralStatistics($userId);
return $result;
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
namespace App\Http\Middleware;
use Closure;
use App\Model\TokenModel;
//use App\Model\TokenModel;
class UniqueMiddleware
{
......
......@@ -6,7 +6,10 @@ namespace App\Models;
use App\Http\Filters\QueryFilter;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen;
//活动红包模型
class Integral extends Model
{
public $timestamps = false;
......@@ -23,8 +26,201 @@ class Integral extends Model
return $filters->apply($query);
}
public function integralType()
//获取活动红包列表
public function getIntegralList($page, $pageSize, $filter)
{
return $this->belongsTo(IntegralType::class, 'integral_type_id', 'id');
$integrals = Integral::filter($filter)
->page($page, $pageSize)
->get()->toArray();
$count = Integral::filter($filter)->count();
return ['data' => $integrals, 'count' => $count];
}
//获取红包活动列表,给API使用
public function getIntegralListForApi()
{
//先从redis里面查询是否有列表,没有的话从MySQL里面取出并且放入redis
$redis = new RedisModel();
$integrals = $this->getIntegralListFromRedis();
$count = 0;
if (!$integrals) {
$result = $this->addIntegralListToRedis();
if (!$result) {
ErrorLog(ErrorCode(18, '5'), '写入红包活动列表到Redis失败');
$count = Integral::where('status', 1)->count();
}
} else {
$count = $redis->hlen('ic_welfare_integrals');
}
$integrals = arraySequence($integrals,'id','SORT_ASC');
return ['data' => array_values($integrals), 'count' => $count];
}
//从redis查询出红包列表
public function getIntegralListFromRedis()
{
$redis = new RedisModel();
$integrals = $redis->hgetall('ic_welfare_integrals');
$integrals = array_map(function ($value) {
return json_decode($value, true);
}, $integrals);
return $integrals;
}
//添加红包列表到Redis
public function addIntegralListToRedis()
{
$integrals = Integral::where('status', 1)
->get()->toArray();
$redis = new RedisModel();
//转换数据存储到Redis的哈希类型
$data = [];
foreach ($integrals as $key => $integral) {
$data[$integral['id']] = json_encode($integral);
}
//这里如果没有数据放到缓存了,直接删除key
if ($data) {
$result = $redis->hmset('ic_welfare_integrals', $data);
} else {
$result = $redis->del('ic_welfare_integrals');
}
return $result;
}
//添加单个红包
public function addIntegral($data = [])
{
$result = DB::transaction(function () use ($data) {
$id = DB::table('integrals')->insertGetId($data);
$data['update_time'] = 0;
$data['id'] = $id;
if (!$id) {
return false;
}
$result = $this->addIntegralToRedis($id, $data);
if ($result === false) {
throw new \Exception('新增红包活动缓存数据失败', ErrorCode(19, 5));
}
return true;
}, 5);
return $result;
}
//添加单个红包活动到redis
public function addIntegralToRedis($id, $data)
{
$redis = new RedisModel();
$result = $redis->hset('ic_welfare_integrals', $id, json_encode($data));
return $result;
}
//更新单个红包活动
public function updateIntegral($id, $data = [])
{
$result = DB::transaction(function () use ($id, $data) {
$result = DB::table('integrals')->where('id', $id)
->update($data);
if (!$result) {
return false;
}
if ($result) {
$result = $this->changeIntegralsFromRedis([$id]);
if ($result === false) {
throw new \Exception('更新红包活动缓存数据失败', ErrorCode(20, 5));
}
}
return $result ? true : false;
}, 5);
return $result;
}
//更新Redis的单个红包活动
public function updateIntegralFromRedis($id, $data)
{
$redis = new RedisModel();
$integral = $redis->hget('ic_welfare_integrals', $id);
$result = false;
if ($integral) {
//为什么用array_merge,因为右边的数组的键值会覆盖左边的对应值
$data = array_merge(json_decode($integral, true), $data);
$result = $redis->hset('ic_welfare_integrals', $id, json_encode($data));
}
return $result;
}
//更新可使用状态,要将redis的列表也更新
public function batchUpdateStatus($ids = [], $data = [])
{
$result = DB::transaction(function () use ($ids, $data) {
$result = DB::table('integrals')->whereIn('id', $ids)->update($data);
if (!$result) {
return false;
}
$result = $this->changeIntegralsFromRedis($ids);
if ($result === false) {
throw new \Exception('更新部分红包信息到redis失败', ErrorCode(21, 5));
}
return true;
}, 5);
return $result;
}
//因为修改状态会涉及到不少信息的更变,所以直接重新更新有变化的数据(根据ids)
public function changeIntegralsFromRedis($ids = [])
{
if ($ids) {
$changedIntegrals = DB::table('integrals')
->whereIn('id', $ids)->get()->toArray();
$needDelete = $needUpdate = [];
foreach ($changedIntegrals as $key => $value) {
//判断是不是禁用,如果是禁用,就从redis里面删除
if (!$value->status) {
$needDelete[] = $value->id;
} else {
$needUpdate[$value->id] = json_encode($value);
}
}
$redis = new RedisModel();
if ($needDelete) {
$result = $redis->hdel('ic_welfare_integrals', $needDelete);
if ($result === false) {
return false;
}
}
if ($needUpdate) {
$result = $redis->hmset('ic_welfare_integrals', $needUpdate);
if ($result === false) {
return false;
}
}
return true;
}
return true;
}
public function deleteIntegral($ids = [])
{
$res = DB::table('integrals')->whereIn('id', $ids)->delete();
return $res;
}
}
\ No newline at end of file
<?php
namespace App\Models;
use App\Http\Filters\QueryFilter;
use Illuminate\Database\Eloquent\Model;
class IntegralBill extends Model
{
public $timestamps = false;
public function integral()
{
return $this->belongsTo(Integral::class, 'integral_id', 'id');
}
public function scopePage($query, $page = 1, $pageSize = 10)
{
return $query->offset(($page - 1) * $pageSize)->limit($pageSize);
}
public function scopeFilter($query, QueryFilter $filters)
{
return $filters->apply($query);
}
<?php
namespace App\Models;
use App\Http\Filters\IntegralBillFilter;
use App\Http\Filters\QueryFilter;
use http\Env\Request;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class IntegralBill extends Model
{
public $timestamps = false;
public function integral()
{
return $this->belongsTo(Integral::class, 'integral_id', 'id');
}
public function scopePage($query, $page = 1, $pageSize = 10)
{
return $query->offset(($page - 1) * $pageSize)->limit($pageSize);
}
public function scopeFilter($query, QueryFilter $filters)
{
return $filters->apply($query);
}
//获取用户兑换红包列表
public function getIntegralBillList($page, $pageSize, $filter)
{
$request = new \Illuminate\Http\Request();
$bills = IntegralBill::with('integral')->filter($filter)->page($page, $pageSize)
->orderBy('id', 'desc')
->get()->toArray();
$count = IntegralBill::filter($filter)->count();
return ['data' => $bills, 'count' => $count];
}
public function createIntegralBill($data = [])
{
$res = DB::transaction(function () use ($data) {
DB::table('integral_bills')->insert($data);
});
return $res;
}
//更新用户红包兑换列表
public function updateIntegralBill($id, $data = [])
{
$res = DB::table('integral_bills')->where('id', $id)
->update($data);
return $res;
}
//删除
public function deleteIntegralBill($ids = [])
{
$res = DB::table('integral_bills')->whereIn('id', $ids)->delete();
return $res;
}
//获取用户红包统计信息
public function getUserIntegralStatistics($userId)
{
//一共获得的积分金额
$totalAmount = DB::table('integral_bills')
->leftJoin('integrals', 'integral_bills.integral_id', 'integrals.id')
->where('user_id', $userId)
->sum('amount');
//已经兑换的金额
$exchangedAmount = DB::table('user_exchanges')
->leftJoin('exchange_settings', 'user_exchanges.exchange_id', 'exchange_settings.id')
->where('user_id', $userId)
->sum('amount');
//剩余可兑换积分金额
$integral = DB::table('user_integrals')
->where('user_id', $userId)->value('integral');
return [
'total_amount' => $totalAmount,
'exchanged_amount' => $exchangedAmount,
'integral' => $integral,
];
}
}
\ No newline at end of file
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class IntegralType extends Model
{
public $timestamps = false;
protected $fillable = ['name','status'];
}
\ No newline at end of file
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Redis;
class RedisModel extends Model
{
const WRITE_CONNECT_METHOD = ['set', 'del', 'rpush','lpush', 'expire', 'hset', 'hmset', 'hdel','hsetnx','hincrby'];
private $read = [];
private $write = [];
public function __construct($ConnectWrite = 'default', $ConnectRead = 'read')
{
parent::__construct();
$this->read = Redis::connection($ConnectRead);
$this->write = Redis::connection($ConnectWrite);
}
public function __call($method, $args)
{
$cls = &$this;
$tmp = function($method, $args) use ($cls) {
if (strpos($method, 'pipeline_')) {//使用管道
$method = substr($method, 9);
if (in_array($method, $cls::WRITE_CONNECT_METHOD)) {
return $cls->write->pipeline(function ($pipe) use ($args) {
foreach ($args as $arg) {
$pipe->$method(...$arg);
}
});
} else {
try {
return $cls->read->pipeline(function ($pipe) use ($args) {
foreach ($args as $arg) {
$pipe->$method(...$arg);
}
});
} catch (ConnectionException $e) {
return $cls->write->pipeline(function ($pipe) use ($args) {
foreach ($args as $arg) {
$pipe->$method(...$arg);
}
});
}
}
} else {
if (in_array($method, $cls::WRITE_CONNECT_METHOD)) {
return $cls->write->$method(...$args);
} else {
try {
return $cls->read->$method(...$args);
} catch (ConnectionException $e) {
return $cls->write->$method(...$args);
}
}
}
};
try {
return $tmp($method, $args);
} catch (\Exception $e) {
dd($e);
return false;
}
// if (strpos($method, 'catch_') === 0) {
// $method = substr($method, 6);
// try {
// return $tmp($method, $args);
// } catch (\Exception $e) {
// return null;
// }
// } else {
// return $tmp($method, $args);
// }
}
}
......@@ -6,6 +6,7 @@ namespace App\Models;
use App\Http\Filters\QueryFilter;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class UserExchange extends Model
{
......@@ -21,6 +22,7 @@ class UserExchange extends Model
return $filters->apply($query);
}
//添加提现记录
public function addRecord(&$data){
$data['add_time'] = time();
......@@ -32,8 +34,76 @@ class UserExchange extends Model
return true;
}
public function SaveRecord($id,$data){
public function SaveRecord($id,$data)
{
$data['update_time'] = time();
return $this->where('id','=',$id)->update($data);
return $this->where('id', '=', $id)->update($data);
}
public function exchange_setting()
{
return $this->hasOne(ExchangeSetting::class, 'id', 'exchange_id');
}
public function user_integral()
{
return $this->belongsTo(UserIntegral::class, 'user_id', 'user_id');
}
public function getUserExchangeList($page, $pageSize, $filter)
{
$userExchanges = UserExchange::with(['exchange_setting', 'user_integral'])->filter($filter)->page($page,
$pageSize)
->orderBy('id', 'desc')
->get()->toArray();
$count = UserExchange::filter($filter)->count();
return ['data' => $userExchanges, 'count' => $count];
}
//审核用户的兑换
public function auditUserExchange($id, $exchangedAmount, $data = [])
{
$result = DB::transaction(function () use ($id, $exchangedAmount, $data) {
//先去修改审核状态等信息
$result = DB::table('user_exchanges')->where('id', $id)->update($data);
if (!$result) {
return false;
}
//兑换审核通过后,需要对用户剩余的红包金额进行对应的减少
$result = DB::table('user_integrals')->where('user_id', $data['user_id'])
->decrement('integral', $exchangedAmount);
if (!$result) {
return false;
}
//同时用户积分详情的更新时间
$result = DB::table('user_integrals')->where('user_id', $data['user_id'])
->update(['update_time' => $data['update_time']]);
if (!$result) {
return false;
}
return true;
});
if (!$result) {
return false;
}
return true;
}
public function batchAuditRejectUserExchange($ids = [], $data = [])
{
$res = DB::table('user_exchanges')
->whereIn('id', $ids)
->update($data);
return $res;
}
}
\ No newline at end of file
......@@ -6,6 +6,7 @@ namespace App\Models;
use App\Http\Filters\QueryFilter;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class UserIntegral extends Model
{
......@@ -21,8 +22,38 @@ class UserIntegral extends Model
return $filters->apply($query);
}
//扣减红包,需要制定扣减数量
public function Deduction($user_id , $integral){
return $this->where('user_id','=',$user_id)->decrement('integral',$integral,['update_time'=>time()]);
public function Deduction($user_id , $integral)
{
return $this->where('user_id', '=', $user_id)->decrement('integral', $integral, ['update_time' => time()]);
}
public function getUserIntegralList($page, $pageSize, $filter)
{
$settings = UserIntegral::filter($filter)
->page($page, $pageSize)
->orderBy('id', 'desc')
->get()->toArray();
$count = UserIntegral::filter($filter)->count();
return ['data' => $settings, 'count' => $count];
}
public function updateUserIntegral($id, $data = [])
{
$res = DB::table('user_integrals')->where('id', $id)
->update($data);
return $res;
}
public function batchUpdateStatus($ids = [], $data = [])
{
$res = DB::table('user_integrals')
->whereIn('id', $ids)
->update($data);
return $res;
}
}
\ No newline at end of file
......@@ -2,6 +2,8 @@
use App\Http\Middleware\UniqueMiddleware;
use Common\Exceptions\Handler;
use Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider;
use Illuminate\Redis\RedisServiceProvider;
require_once __DIR__.'/../vendor/autoload.php';
......@@ -30,7 +32,6 @@ $app = new Laravel\Lumen\Application(
$app->withEloquent();
$app->register(Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class);
/*
|--------------------------------------------------------------------------
......@@ -88,6 +89,8 @@ $app->singleton(
// $app->register(App\Providers\AppServiceProvider::class);
// $app->register(App\Providers\AuthServiceProvider::class);
// $app->register(App\Providers\EventServiceProvider::class);
$app->register(Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class);
$app->register(Illuminate\Redis\RedisServiceProvider::class);
/*
|--------------------------------------------------------------------------
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6217641796c92c3ef02247c4e3fd7a58",
"content-hash": "bc687c7ebdab62e992ab75510d81f58a",
"packages": [
{
"name": "doctrine/inflector",
......@@ -1073,6 +1073,57 @@
"time": "2018-08-15T13:22:41+00:00"
},
{
"name": "illuminate/redis",
"version": "v5.5.44",
"source": {
"type": "git",
"url": "https://github.com/illuminate/redis.git",
"reference": "2d57f7ec6177a5df2ac181fb08532bb3102d0d8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/redis/zipball/2d57f7ec6177a5df2ac181fb08532bb3102d0d8a",
"reference": "2d57f7ec6177a5df2ac181fb08532bb3102d0d8a",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"illuminate/contracts": "5.5.*",
"illuminate/support": "5.5.*",
"php": ">=7.0",
"predis/predis": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.5-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Redis\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Redis package.",
"homepage": "https://laravel.com",
"time": "2018-05-22T11:51:18+00:00"
},
{
"name": "illuminate/session",
"version": "v5.5.44",
"source": {
......@@ -1797,6 +1848,62 @@
"time": "2018-07-02T15:55:56+00:00"
},
{
"name": "predis/predis",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/nrk/predis.git",
"reference": "f0210e38881631afeafb56ab43405a92cafd9fd1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1",
"reference": "f0210e38881631afeafb56ab43405a92cafd9fd1",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3.9"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"suggest": {
"ext-curl": "Allows access to Webdis when paired with phpiredis",
"ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol"
},
"type": "library",
"autoload": {
"psr-4": {
"Predis\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniele Alessandri",
"email": "suppakilla@gmail.com",
"homepage": "http://clorophilla.net"
}
],
"description": "Flexible and feature-complete Redis client for PHP and HHVM",
"homepage": "http://github.com/nrk/predis",
"keywords": [
"nosql",
"predis",
"redis"
],
"time": "2016-06-16T16:22:20+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",
"source": {
......@@ -1960,16 +2067,16 @@
},
{
"name": "swoole/ide-helper",
"version": "4.4.3",
"version": "4.4.4",
"source": {
"type": "git",
"url": "https://github.com/swoole/ide-helper.git",
"reference": "d8fdeff72d0c01d8547c03272b0e6fb05f6c2aa6"
"reference": "9493a89afa6d05175d14c58c5ff7ee36e85fd5cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swoole/ide-helper/zipball/d8fdeff72d0c01d8547c03272b0e6fb05f6c2aa6",
"reference": "d8fdeff72d0c01d8547c03272b0e6fb05f6c2aa6",
"url": "https://api.github.com/repos/swoole/ide-helper/zipball/9493a89afa6d05175d14c58c5ff7ee36e85fd5cd",
"reference": "9493a89afa6d05175d14c58c5ff7ee36e85fd5cd",
"shasum": "",
"mirrors": [
{
......@@ -1983,11 +2090,6 @@
"zendframework/zend-code": "~3.3.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Swoole\\IDEHelper\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
......@@ -1999,7 +2101,7 @@
}
],
"description": "IDE help files for Swoole.",
"time": "2019-08-09T06:19:25+00:00"
"time": "2019-08-19T20:56:30+00:00"
},
{
"name": "symfony/console",
......
......@@ -138,15 +138,21 @@ return [
'redis' => [
'client' => 'predis',
'cluster' => env('REDIS_CLUSTER', false),
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
'port' => env('REDIS_PORT', 6379),
'database' => 2
],
'read' =>[
'host' => env('REDIS_READ_HOST', ''),
'password' => env('REDIS_READ_PASSWORD', null),
'port' => env('REDIS_READ_PORT', 6379),
'database' => 2
]
],
];
......@@ -24,6 +24,7 @@ $router->post('/integrals/list', 'IntegralsController@index');
$router->post('/integrals/info', 'IntegralsController@show');
$router->post('/integrals/add', 'IntegralsController@create');
$router->post('/integrals/update', 'IntegralsController@update');
$router->post('/integrals/updateStatus', 'IntegralsController@updateStatus');
$router->post('/integrals/delete', 'IntegralsController@destroy');
$router->post('/integrals/batchUpdateStatus', 'IntegralsController@batchUpdateStatus');
......@@ -43,8 +44,11 @@ $router->post('/integral_bills/delete', 'IntegralBillsController@destroy');
//用户积分信息
$router->post('/user_integrals/info', 'UserIntegralsController@show');
$router->post('/user_integrals/list', 'UserIntegralsController@index');
$router->post('/user_integrals/update', 'UserIntegralsController@update');
$router->post('/user_integrals/updateStatus', 'UserIntegralsController@updateStatus');
$router->post('/user_integrals/batchUpdateStatus', 'UserIntegralsController@batchUpdateStatus');
$router->post('/user_integrals/updateExchangedIntegral', 'UserIntegralsController@updateExchangedIntegral');
$router->post('/user_integrals/statistics', 'UserIntegralsController@statistics');
//兑换配置
......@@ -52,14 +56,16 @@ $router->post('/exchange_settings/info', 'ExchangeSettingsController@show');
$router->post('/exchange_settings/list', 'ExchangeSettingsController@index');
$router->post('/exchange_settings/add', 'ExchangeSettingsController@store');
$router->post('/exchange_settings/update', 'ExchangeSettingsController@update');
$router->post('/exchange_settings/updateStatus', 'ExchangeSettingsController@updateStatus');
$router->post('/exchange_settings/delete', 'ExchangeSettingsController@destroy');
$router->post('/exchange_settings/batchUpdateStatus', 'ExchangeSettingsController@batchUpdateStatus');
//用户兑换记录
$router->post('/user_exchanges/info', 'UserExchangesController@show');
$router->post('/user_exchanges/audit', 'UserExchangesController@audit');
$router->post('/user_exchanges/list', 'UserExchangesController@index');
$router->post('/user_exchanges/update', 'UserExchangesController@update');
$router->post('/user_exchanges/batchUpdateStatus', 'UserExchangesController@batchUpdateStatus');
$router->post('/user_exchanges/batchAuditReject', 'UserExchangesController@batchAuditReject');
//抢兑换名额
$router->post('/rob/exchange/quota', 'UserExchangesController@create');
5983
\ No newline at end of file
9058
\ No newline at end of file
......@@ -11,10 +11,9 @@ return array(
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
'1d1b89d124cc9cb8219922c9d5569199' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest.php',
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
'bee9632da3ca00a99623b9c35d0c4f8b' => $vendorDir . '/laravel/lumen-framework/src/helpers.php',
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'f4e9c7747917193061b46ee142399603' => $vendorDir . '/dingo/api/src/helpers.php',
'7039eb1b48735a2a2905d88c22d84a48' => $baseDir . '/common/function.php',
'c71e5a39a1f58c05a11e8537318d6d3d' => $baseDir . '/common/LogReport.php',
'83c5b4042a3162a51b89dd77dc1632db' => $baseDir . '/app/helpers.php',
......
......@@ -14,7 +14,6 @@ return array(
'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'),
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
......@@ -22,20 +21,19 @@ return array(
'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
'Swoole\\IDEHelper\\' => array($vendorDir . '/swoole/ide-helper/src'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
'Predis\\' => array($vendorDir . '/predis/predis/src'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'League\\Fractal\\' => array($vendorDir . '/league/fractal/src'),
'Laravel\\Lumen\\' => array($vendorDir . '/laravel/lumen-framework/src'),
'Illuminate\\View\\' => array($vendorDir . '/illuminate/view'),
'Illuminate\\Validation\\' => array($vendorDir . '/illuminate/validation'),
'Illuminate\\Translation\\' => array($vendorDir . '/illuminate/translation'),
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/support'),
'Illuminate\\Session\\' => array($vendorDir . '/illuminate/session'),
'Illuminate\\Routing\\' => array($vendorDir . '/illuminate/routing'),
'Illuminate\\Redis\\' => array($vendorDir . '/illuminate/redis'),
'Illuminate\\Queue\\' => array($vendorDir . '/illuminate/queue'),
'Illuminate\\Pipeline\\' => array($vendorDir . '/illuminate/pipeline'),
'Illuminate\\Pagination\\' => array($vendorDir . '/illuminate/pagination'),
......@@ -58,10 +56,7 @@ return array(
'Faker\\' => array($vendorDir . '/fzaninotto/faker/src/Faker'),
'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'),
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer'),
'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Common/Inflector'),
'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations'),
'Dingo\\Api\\' => array($vendorDir . '/dingo/api/src'),
'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
'Cron\\' => array($vendorDir . '/mtdowling/cron-expression/src/Cron'),
'Common\\' => array($baseDir . '/common'),
......
......@@ -12,10 +12,9 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
'1d1b89d124cc9cb8219922c9d5569199' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest.php',
'6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
'bee9632da3ca00a99623b9c35d0c4f8b' => __DIR__ . '/..' . '/laravel/lumen-framework/src/helpers.php',
'6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'f4e9c7747917193061b46ee142399603' => __DIR__ . '/..' . '/dingo/api/src/helpers.php',
'7039eb1b48735a2a2905d88c22d84a48' => __DIR__ . '/../..' . '/common/function.php',
'c71e5a39a1f58c05a11e8537318d6d3d' => __DIR__ . '/../..' . '/common/LogReport.php',
'83c5b4042a3162a51b89dd77dc1632db' => __DIR__ . '/../..' . '/app/helpers.php',
......@@ -38,7 +37,6 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
'Symfony\\Contracts\\Translation\\' => 30,
'Symfony\\Contracts\\EventDispatcher\\' => 34,
'Symfony\\Component\\Translation\\' => 30,
'Symfony\\Component\\Routing\\' => 26,
'Symfony\\Component\\Process\\' => 26,
'Symfony\\Component\\HttpKernel\\' => 29,
'Symfony\\Component\\HttpFoundation\\' => 33,
......@@ -46,7 +44,6 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
'Symfony\\Component\\EventDispatcher\\' => 34,
'Symfony\\Component\\Debug\\' => 24,
'Symfony\\Component\\Console\\' => 26,
'Swoole\\IDEHelper\\' => 17,
),
'P' =>
array (
......@@ -54,6 +51,7 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
'Psr\\Log\\' => 8,
'Psr\\Container\\' => 14,
'Prophecy\\' => 9,
'Predis\\' => 7,
),
'M' =>
array (
......@@ -61,7 +59,6 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
),
'L' =>
array (
'League\\Fractal\\' => 15,
'Laravel\\Lumen\\' => 14,
),
'I' =>
......@@ -71,7 +68,7 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
'Illuminate\\Translation\\' => 23,
'Illuminate\\Support\\' => 19,
'Illuminate\\Session\\' => 19,
'Illuminate\\Routing\\' => 19,
'Illuminate\\Redis\\' => 17,
'Illuminate\\Queue\\' => 17,
'Illuminate\\Pipeline\\' => 20,
'Illuminate\\Pagination\\' => 22,
......@@ -103,10 +100,7 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
array (
'Dotenv\\' => 7,
'Doctrine\\Instantiator\\' => 22,
'Doctrine\\Common\\Lexer\\' => 22,
'Doctrine\\Common\\Inflector\\' => 26,
'Doctrine\\Common\\Annotations\\' => 28,
'Dingo\\Api\\' => 10,
'DeepCopy\\' => 9,
),
'C' =>
......@@ -155,10 +149,6 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
array (
0 => __DIR__ . '/..' . '/symfony/translation',
),
'Symfony\\Component\\Routing\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/routing',
),
'Symfony\\Component\\Process\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/process',
......@@ -187,10 +177,6 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
array (
0 => __DIR__ . '/..' . '/symfony/console',
),
'Swoole\\IDEHelper\\' =>
array (
0 => __DIR__ . '/..' . '/swoole/ide-helper/src',
),
'Psr\\SimpleCache\\' =>
array (
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
......@@ -207,13 +193,13 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
array (
0 => __DIR__ . '/..' . '/phpspec/prophecy/src/Prophecy',
),
'Monolog\\' =>
'Predis\\' =>
array (
0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
0 => __DIR__ . '/..' . '/predis/predis/src',
),
'League\\Fractal\\' =>
'Monolog\\' =>
array (
0 => __DIR__ . '/..' . '/league/fractal/src',
0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
),
'Laravel\\Lumen\\' =>
array (
......@@ -239,9 +225,9 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
array (
0 => __DIR__ . '/..' . '/illuminate/session',
),
'Illuminate\\Routing\\' =>
'Illuminate\\Redis\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/routing',
0 => __DIR__ . '/..' . '/illuminate/redis',
),
'Illuminate\\Queue\\' =>
array (
......@@ -331,22 +317,10 @@ class ComposerStaticInit9c11833987e743dc3f50bdb92ca1aa2a
array (
0 => __DIR__ . '/..' . '/doctrine/instantiator/src/Doctrine/Instantiator',
),
'Doctrine\\Common\\Lexer\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/lexer/lib/Doctrine/Common/Lexer',
),
'Doctrine\\Common\\Inflector\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Common/Inflector',
),
'Doctrine\\Common\\Annotations\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations',
),
'Dingo\\Api\\' =>
array (
0 => __DIR__ . '/..' . '/dingo/api/src',
),
'DeepCopy\\' =>
array (
0 => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy',
......
| Q | A
| ----------------- | ---
| Bug? | no|yes
| New Feature? | no|yes
| Framework | Laravel|Lumen
| Framework version | 5.x.y
| Package version | 1.x.y
| PHP version | 5.x.y|7.x.y
#### Actual Behaviour
Describe the behaviour you're experiencing. Do not just copy and paste a random error message and expect help.
#### Expected Behaviour
Describe the behaviour you're expecting.
#### Steps to Reproduce
List all the steps needed to reproduce the issue you're having. Make sure to include code (affected models, configurations),
any screenshots and/or other resources that may help us understand what's going on.
#### Possible Solutions
If you have any ideas on how to solve the issue, add them here, otherwise you can omit this part.
preset: laravel
enabled:
- phpdoc_order
- phpdoc_separation
- unalign_double_arrow
Copyright (c) 2014-2015, Jason Lewis
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Dingo API nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
"name": "dingo/api",
"description": "A RESTful API package for the Laravel and Lumen frameworks.",
"keywords": [
"api",
"dingo",
"laravel",
"restful"
],
"license": "BSD-3-Clause",
"authors": [{
"name": "Jason Lewis",
"email": "jason.lewis1991@gmail.com"
}],
"require": {
"php": "^7.1",
"dingo/blueprint": "^0.2",
"illuminate/routing": "^5.5",
"illuminate/support": "^5.5",
"league/fractal": "^0.17"
},
"require-dev": {
"phpdocumentor/reflection-docblock": "3.3.2",
"friendsofphp/php-cs-fixer": "~2",
"illuminate/auth": "^5.5",
"illuminate/cache": "^5.5",
"illuminate/console": "^5.5",
"illuminate/database": "^5.5",
"illuminate/events": "^5.5",
"illuminate/filesystem": "^5.5",
"illuminate/log": "^5.5",
"illuminate/pagination": "^5.5",
"laravel/lumen-framework": "^5.5",
"mockery/mockery": "~1.0",
"phpunit/phpunit": "^4.8.35 || ^5.4.3 || ^6.5",
"squizlabs/php_codesniffer": "~2.0",
"tymon/jwt-auth": "1.0.*"
},
"suggest": {
"tymon/jwt-auth": "Protect your API with JSON Web Tokens."
},
"autoload": {
"psr-4": {
"Dingo\\Api\\": "src/"
},
"files": [
"src/helpers.php"
]
},
"autoload-dev": {
"psr-4": {
"Dingo\\Api\\Tests\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
},
"laravel": {
"providers": [
"Dingo\\Api\\Provider\\LaravelServiceProvider"
],
"aliases": {
"API": "Dingo\\Api\\Facade\\API"
}
}
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true
}
<?php
return [
/*
|--------------------------------------------------------------------------
| Standards Tree
|--------------------------------------------------------------------------
|
| Versioning an API with Dingo revolves around content negotiation and
| custom MIME types. A custom type will belong to one of three
| standards trees, the Vendor tree (vnd), the Personal tree
| (prs), and the Unregistered tree (x).
|
| By default the Unregistered tree (x) is used, however, should you wish
| to you can register your type with the IANA. For more details:
| https://tools.ietf.org/html/rfc6838
|
*/
'standardsTree' => env('API_STANDARDS_TREE', 'x'),
/*
|--------------------------------------------------------------------------
| API Subtype
|--------------------------------------------------------------------------
|
| Your subtype will follow the standards tree you use when used in the
| "Accept" header to negotiate the content type and version.
|
| For example: Accept: application/x.SUBTYPE.v1+json
|
*/
'subtype' => env('API_SUBTYPE', ''),
/*
|--------------------------------------------------------------------------
| Default API Version
|--------------------------------------------------------------------------
|
| This is the default version when strict mode is disabled and your API
| is accessed via a web browser. It's also used as the default version
| when generating your APIs documentation.
|
*/
'version' => env('API_VERSION', 'v1'),
/*
|--------------------------------------------------------------------------
| Default API Prefix
|--------------------------------------------------------------------------
|
| A default prefix to use for your API routes so you don't have to
| specify it for each group.
|
*/
'prefix' => env('API_PREFIX', null),
/*
|--------------------------------------------------------------------------
| Default API Domain
|--------------------------------------------------------------------------
|
| A default domain to use for your API routes so you don't have to
| specify it for each group.
|
*/
'domain' => env('API_DOMAIN', null),
/*
|--------------------------------------------------------------------------
| Name
|--------------------------------------------------------------------------
|
| When documenting your API using the API Blueprint syntax you can
| configure a default name to avoid having to manually specify
| one when using the command.
|
*/
'name' => env('API_NAME', null),
/*
|--------------------------------------------------------------------------
| Conditional Requests
|--------------------------------------------------------------------------
|
| Globally enable conditional requests so that an ETag header is added to
| any successful response. Subsequent requests will perform a check and
| will return a 304 Not Modified. This can also be enabled or disabled
| on certain groups or routes.
|
*/
'conditionalRequest' => env('API_CONDITIONAL_REQUEST', true),
/*
|--------------------------------------------------------------------------
| Strict Mode
|--------------------------------------------------------------------------
|
| Enabling strict mode will require clients to send a valid Accept header
| with every request. This also voids the default API version, meaning
| your API will not be browsable via a web browser.
|
*/
'strict' => env('API_STRICT', false),
/*
|--------------------------------------------------------------------------
| Debug Mode
|--------------------------------------------------------------------------
|
| Enabling debug mode will result in error responses caused by thrown
| exceptions to have a "debug" key that will be populated with
| more detailed information on the exception.
|
*/
'debug' => env('API_DEBUG', false),
/*
|--------------------------------------------------------------------------
| Generic Error Format
|--------------------------------------------------------------------------
|
| When some HTTP exceptions are not caught and dealt with the API will
| generate a generic error response in the format provided. Any
| keys that aren't replaced with corresponding values will be
| removed from the final response.
|
*/
'errorFormat' => [
'message' => ':message',
'errors' => ':errors',
'code' => ':code',
'status_code' => ':status_code',
'debug' => ':debug',
],
/*
|--------------------------------------------------------------------------
| API Middleware
|--------------------------------------------------------------------------
|
| Middleware that will be applied globally to all API requests.
|
*/
'middleware' => [
],
/*
|--------------------------------------------------------------------------
| Authentication Providers
|--------------------------------------------------------------------------
|
| The authentication providers that should be used when attempting to
| authenticate an incoming API request.
|
*/
'auth' => [
],
/*
|--------------------------------------------------------------------------
| Throttling / Rate Limiting
|--------------------------------------------------------------------------
|
| Consumers of your API can be limited to the amount of requests they can
| make. You can create your own throttles or simply change the default
| throttles.
|
*/
'throttling' => [
],
/*
|--------------------------------------------------------------------------
| Response Transformer
|--------------------------------------------------------------------------
|
| Responses can be transformed so that they are easier to format. By
| default a Fractal transformer will be used to transform any
| responses prior to formatting. You can easily replace
| this with your own transformer.
|
*/
'transformer' => env('API_TRANSFORMER', Dingo\Api\Transformer\Adapter\Fractal::class),
/*
|--------------------------------------------------------------------------
| Response Formats
|--------------------------------------------------------------------------
|
| Responses can be returned in multiple formats by registering different
| response formatters. You can also customize an existing response
| formatter with a number of options to configure its output.
|
*/
'defaultFormat' => env('API_DEFAULT_FORMAT', 'json'),
'formats' => [
'json' => Dingo\Api\Http\Response\Format\Json::class,
],
'formatsOptions' => [
'json' => [
'pretty_print' => env('API_JSON_FORMAT_PRETTY_PRINT_ENABLED', false),
'indent_style' => env('API_JSON_FORMAT_INDENT_STYLE', 'space'),
'indent_size' => env('API_JSON_FORMAT_INDENT_SIZE', 2),
],
],
];
![](https://cloud.githubusercontent.com/assets/829059/9216039/82be51cc-40f6-11e5-88f5-f0cbd07bcc39.png)
The Dingo API package is meant to provide you, the developer, with a set of tools to help you easily and quickly build your own API. While the goal of this package is to remain as flexible as possible it still won't cover all situations and solve all problems.
[![Build Status](https://img.shields.io/travis/dingo/api/master.svg?style=flat-square)](https://travis-ci.org/dingo/api)
[![License](https://img.shields.io/packagist/l/dingo/api.svg?style=flat-square)](LICENSE)
[![Development Version](https://img.shields.io/packagist/vpre/dingo/api.svg?style=flat-square)](https://packagist.org/packages/dingo/api)
[![Monthly Installs](https://img.shields.io/packagist/dm/dingo/api.svg?style=flat-square)](https://packagist.org/packages/dingo/api)
[![StyleCI](https://styleci.io/repos/18673522/shield)](https://styleci.io/repos/18673522)
## Features
This package provides tools for the following, and more:
- Content Negotiation
- Multiple Authentication Adapters
- API Versioning
- Rate Limiting
- Response Transformers and Formatters
- Error and Exception Handling
- Internal Requests
- API Blueprint Documentation
## Documentation
Please refer to our extensive [Wiki documentation](https://github.com/dingo/api/wiki) for more information.
## API Boilerplate
If you are looking to start a new project from scratch, consider using the [Laravel 5 API Boilerplate](https://github.com/specialtactics/laravel5-api-boilerplate), which builds on top of the dingo-api package, and adds a lot of great features.
## Support
For answers you may not find in the Wiki, avoid posting issues. Feel free to ask for support on the dedicated [Slack](https://larachat.slack.com/messages/api/) room. Make sure to mention **specialtactics** / **@jasonlewis** so he is notified.
## License
This package is licensed under the [BSD 3-Clause license](http://opensource.org/licenses/BSD-3-Clause).
<?php
namespace Dingo\Api\Auth;
use Exception;
use Dingo\Api\Routing\Router;
use Illuminate\Container\Container;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class Auth
{
/**
* Router instance.
*
* @var \Dingo\Api\Routing\Router
*/
protected $router;
/**
* Illuminate container instance.
*
* @var \Illuminate\Container\Container
*/
protected $container;
/**
* Array of available authentication providers.
*
* @var array
*/
protected $providers;
/**
* The provider used for authentication.
*
* @var \Dingo\Api\Contract\Auth\Provider
*/
protected $providerUsed;
/**
* Authenticated user instance.
*
* @var \Illuminate\Auth\GenericUser|\Illuminate\Database\Eloquent\Model
*/
protected $user;
/**
* Create a new auth instance.
*
* @param \Dingo\Api\Routing\Router $router
* @param \Illuminate\Container\Container $container
* @param array $providers
*
* @return void
*/
public function __construct(Router $router, Container $container, array $providers)
{
$this->router = $router;
$this->container = $container;
$this->providers = $providers;
}
/**
* Authenticate the current request.
*
* @param array $providers
*
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*
* @return mixed
*/
public function authenticate(array $providers = [])
{
$exceptionStack = [];
// Spin through each of the registered authentication providers and attempt to
// authenticate through one of them. This allows a developer to implement
// and allow a number of different authentication mechanisms.
foreach ($this->filterProviders($providers) as $provider) {
try {
$user = $provider->authenticate($this->router->getCurrentRequest(), $this->router->getCurrentRoute());
$this->providerUsed = $provider;
return $this->user = $user;
} catch (UnauthorizedHttpException $exception) {
$exceptionStack[] = $exception;
} catch (BadRequestHttpException $exception) {
// We won't add this exception to the stack as it's thrown when the provider
// is unable to authenticate due to the correct authorization header not
// being set. We will throw an exception for this below.
}
}
$this->throwUnauthorizedException($exceptionStack);
}
/**
* Throw the first exception from the exception stack.
*
* @param array $exceptionStack
*
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*
* @return void
*/
protected function throwUnauthorizedException(array $exceptionStack)
{
$exception = array_shift($exceptionStack);
if ($exception === null) {
$exception = new UnauthorizedHttpException('dingo', 'Failed to authenticate because of bad credentials or an invalid authorization header.');
}
throw $exception;
}
/**
* Filter the requested providers from the available providers.
*
* @param array $providers
*
* @return array
*/
protected function filterProviders(array $providers)
{
if (empty($providers)) {
return $this->providers;
}
return array_intersect_key($this->providers, array_flip($providers));
}
/**
* Get the authenticated user.
*
* @param bool $authenticate
*
* @return \Illuminate\Auth\GenericUser|\Illuminate\Database\Eloquent\Model|null
*/
public function getUser($authenticate = true)
{
if ($this->user) {
return $this->user;
} elseif (! $authenticate) {
return;
}
try {
return $this->user = $this->authenticate();
} catch (Exception $exception) {
return;
}
}
/**
* Alias for getUser.
*
* @param bool $authenticate
*
* @return \Illuminate\Auth\GenericUser|\Illuminate\Database\Eloquent\Model
*/
public function user($authenticate = true)
{
return $this->getUser($authenticate);
}
/**
* Set the authenticated user.
*
* @param \Illuminate\Auth\GenericUser|\Illuminate\Database\Eloquent\Model $user
*
* @return \Dingo\Api\Auth\Auth
*/
public function setUser($user)
{
$this->user = $user;
return $this;
}
/**
* Check if a user has authenticated with the API.
*
* @param bool $authenticate
*
* @return bool
*/
public function check($authenticate = false)
{
return ! is_null($this->user($authenticate));
}
/**
* Get the provider used for authentication.
*
* @return \Dingo\Api\Contract\Auth\Provider
*/
public function getProviderUsed()
{
return $this->providerUsed;
}
/**
* Extend the authentication layer with a custom provider.
*
* @param string $key
* @param object|callable $provider
*
* @return void
*/
public function extend($key, $provider)
{
if (is_callable($provider)) {
$provider = call_user_func($provider, $this->container);
}
$this->providers[$key] = $provider;
}
}
<?php
namespace Dingo\Api\Auth\Provider;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
abstract class Authorization implements \Dingo\Api\Contract\Auth\Provider
{
/**
* Array of provider specific options.
*
* @var array
*/
protected $options = [];
/**
* Validate the requests authorization header for the provider.
*
* @param \Illuminate\Http\Request $request
*
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
*
* @return bool
*/
public function validateAuthorizationHeader(Request $request)
{
if (Str::startsWith(strtolower($request->headers->get('authorization')), $this->getAuthorizationMethod())) {
return true;
}
throw new BadRequestHttpException;
}
/**
* Get the providers authorization method.
*
* @return string
*/
abstract public function getAuthorizationMethod();
}
<?php
namespace Dingo\Api\Auth\Provider;
use Dingo\Api\Routing\Route;
use Illuminate\Http\Request;
use Illuminate\Auth\AuthManager;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class Basic extends Authorization
{
/**
* Illuminate authentication manager.
*
* @var \Illuminate\Auth\AuthManager
*/
protected $auth;
/**
* Basic auth identifier.
*
* @var string
*/
protected $identifier;
/**
* Create a new basic provider instance.
*
* @param \Illuminate\Auth\AuthManager $auth
* @param string $identifier
*
* @return void
*/
public function __construct(AuthManager $auth, $identifier = 'email')
{
$this->auth = $auth;
$this->identifier = $identifier;
}
/**
* Authenticate request with Basic.
*
* @param \Illuminate\Http\Request $request
* @param \Dingo\Api\Routing\Route $route
*
* @return mixed
*/
public function authenticate(Request $request, Route $route)
{
$this->validateAuthorizationHeader($request);
if (($response = $this->auth->onceBasic($this->identifier)) && $response->getStatusCode() === 401) {
throw new UnauthorizedHttpException('Basic', 'Invalid authentication credentials.');
}
return $this->auth->user();
}
/**
* Get the providers authorization method.
*
* @return string
*/
public function getAuthorizationMethod()
{
return 'basic';
}
}
<?php
namespace Dingo\Api\Auth\Provider;
use Exception;
use Tymon\JWTAuth\JWTAuth;
use Dingo\Api\Routing\Route;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class JWT extends Authorization
{
/**
* The JWTAuth instance.
*
* @var \Tymon\JWTAuth\JWTAuth
*/
protected $auth;
/**
* Create a new JWT provider instance.
*
* @param \Tymon\JWTAuth\JWTAuth $auth
*
* @return void
*/
public function __construct(JWTAuth $auth)
{
$this->auth = $auth;
}
/**
* Authenticate request with a JWT.
*
* @param \Illuminate\Http\Request $request
* @param \Dingo\Api\Routing\Route $route
*
* @return mixed
*/
public function authenticate(Request $request, Route $route)
{
$token = $this->getToken($request);
try {
if (! $user = $this->auth->setToken($token)->authenticate()) {
throw new UnauthorizedHttpException('JWTAuth', 'Unable to authenticate with invalid token.');
}
} catch (JWTException $exception) {
throw new UnauthorizedHttpException('JWTAuth', $exception->getMessage(), $exception);
}
return $user;
}
/**
* Get the JWT from the request.
*
* @param \Illuminate\Http\Request $request
*
* @throws \Exception
*
* @return string
*/
protected function getToken(Request $request)
{
try {
$this->validateAuthorizationHeader($request);
$token = $this->parseAuthorizationHeader($request);
} catch (Exception $exception) {
if (! $token = $request->query('token', false)) {
throw $exception;
}
}
return $token;
}
/**
* Parse JWT from the authorization header.
*
* @param \Illuminate\Http\Request $request
*
* @return string
*/
protected function parseAuthorizationHeader(Request $request)
{
return trim(str_ireplace($this->getAuthorizationMethod(), '', $request->header('authorization')));
}
/**
* Get the providers authorization method.
*
* @return string
*/
public function getAuthorizationMethod()
{
return 'bearer';
}
}
<?php
namespace Dingo\Api\Console\Command;
use Dingo\Api\Routing\Router;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Dingo\Api\Contract\Routing\Adapter;
use Illuminate\Contracts\Console\Kernel;
class Cache extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
public $signature = 'api:cache';
/**
* The console command description.
*
* @var string
*/
public $description = 'Create a route cache file for faster route registration';
/**
* Filesystem instance.
*
* @var \Illuminate\Filesystem\Filesystem
*/
protected $files;
/**
* Router instance.
*
* @var \Dingo\Api\Routing\Router
*/
private $router;
/**
* Adapter instance.
*
* @var \Dingo\Api\Contract\Routing\Adapter
*/
private $adapter;
/**
* Create a new cache command instance.
*
* @param \Illuminate\Filesystem\Filesystem $files
* @param \Dingo\Api\Routing\Router $router
* @param \Dingo\Api\Contract\Routing\Adapter $adapter
*
* @return void
*/
public function __construct(Filesystem $files, Router $router, Adapter $adapter)
{
$this->files = $files;
$this->router = $router;
$this->adapter = $adapter;
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->callSilent('route:clear');
$app = $this->getFreshApplication();
$this->call('route:cache');
$routes = $app['api.router']->getAdapterRoutes();
foreach ($routes as $collection) {
foreach ($collection as $route) {
$app['api.router.adapter']->prepareRouteForSerialization($route);
}
}
$stub = "app('api.router')->setAdapterRoutes(unserialize(base64_decode('{{routes}}')));";
$path = $this->laravel->getCachedRoutesPath();
if (! $this->files->exists($path)) {
$stub = "<?php\n\n$stub";
}
$this->files->append(
$path,
str_replace('{{routes}}', base64_encode(serialize($routes)), $stub)
);
}
/**
* Get a fresh application instance.
*
* @return \Illuminate\Contracts\Container\Container
*/
protected function getFreshApplication()
{
if (method_exists($this->laravel, 'bootstrapPath')) {
$app = require $this->laravel->bootstrapPath().'/app.php';
} else {
$app = require $this->laravel->basePath().'/bootstrap/app.php';
}
$app->make(Kernel::class)->bootstrap();
return $app;
}
}
<?php
namespace Dingo\Api\Console\Command;
use ReflectionClass;
use Dingo\Blueprint\Writer;
use Illuminate\Support\Arr;
use Dingo\Api\Routing\Router;
use Dingo\Blueprint\Blueprint;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
class Docs extends Command
{
/**
* Router instance.
*
* @var \Dingo\Api\Routing\Router
*/
protected $router;
/**
* The blueprint instance.
*
* @var \Dingo\Blueprint\Blueprint
*/
protected $blueprint;
/**
* Blueprint instance.
*
* @var \Dingo\Blueprint\Blueprint
*/
protected $docs;
/**
* Writer instance.
*
* @var \Dingo\Blueprint\Writer
*/
protected $writer;
/**
* Default documentation name.
*
* @var string
*/
protected $name;
/**
* Default documentation version.
*
* @var string
*/
protected $version;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'api:docs {--name= : Name of the generated documentation}
{--use-version= : Version of the documentation to be generated}
{--output-file= : Output the generated documentation to a file}
{--include-path= : Path where included documentation files are located}
{--use-controller= : Specify a controller where to generate documentation for}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate API documentation from annotated controllers';
/**
* Create a new docs command instance.
*
* @param \Dingo\Api\Routing\Router $router
* @param \Dingo\Blueprint\Blueprint $blueprint
* @param \Dingo\Blueprint\Writer $writer
* @param string $name
* @param string $version
*
* @return void
*/
public function __construct(Router $router, Blueprint $blueprint, Writer $writer, $name, $version)
{
parent::__construct();
$this->router = $router;
$this->blueprint = $blueprint;
$this->writer = $writer;
$this->name = $name;
$this->version = $version;
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$contents = $this->blueprint->generate($this->getControllers(), $this->getDocName(), $this->getVersion(), $this->getIncludePath());
if ($file = $this->option('output-file')) {
$this->writer->write($contents, $file);
return $this->info('Documentation was generated successfully.');
}
return $this->line($contents);
}
/**
* Get the documentation name.
*
* @return string
*/
protected function getDocName()
{
$name = $this->option('name') ?: $this->name;
if (! $name) {
$this->comment('A name for the documentation was not supplied. Use the --name option or set a default in the configuration.');
exit;
}
return $name;
}
/**
* Get the include path for documentation files.
*
* @return string
*/
protected function getIncludePath()
{
return base_path($this->option('include-path'));
}
/**
* Get the documentation version.
*
* @return string
*/
protected function getVersion()
{
$version = $this->option('use-version') ?: $this->version;
if (! $version) {
$this->comment('A version for the documentation was not supplied. Use the --use-version option or set a default in the configuration.');
exit;
}
return $version;
}
/**
* Get all the controller instances.
*
* @return array
*/
protected function getControllers()
{
$controllers = new Collection;
if ($controller = $this->option('use-controller')) {
$this->addControllerIfNotExists($controllers, app($controller));
return $controllers;
}
foreach ($this->router->getRoutes() as $collections) {
foreach ($collections as $route) {
if ($controller = $route->getControllerInstance()) {
$this->addControllerIfNotExists($controllers, $controller);
}
}
}
return $controllers;
}
/**
* Add a controller to the collection if it does not exist. If the
* controller implements an interface suffixed with "Docs" it
* will be used instead of the controller.
*
* @param \Illuminate\Support\Collection $controllers
* @param object $controller
*
* @return void
*/
protected function addControllerIfNotExists(Collection $controllers, $controller)
{
$class = get_class($controller);
if ($controllers->has($class)) {
return;
}
$reflection = new ReflectionClass($controller);
$interface = Arr::first($reflection->getInterfaces(), function ($key, $value) {
return ends_with($key, 'Docs');
});
if ($interface) {
$controller = $interface;
}
$controllers->put($class, $controller);
}
}
<?php
namespace Dingo\Api\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Dingo\Api\Routing\Router;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Illuminate\Foundation\Console\RouteListCommand;
class Routes extends RouteListCommand
{
/**
* Dingo router instance.
*
* @var \Dingo\Api\Routing\Router
*/
protected $router;
/**
* Array of route collections.
*
* @var array
*/
protected $routes;
/**
* The console command name.
*
* @var string
*/
protected $name = 'api:routes';
/**
* The console command description.
*
* @var string
*/
protected $description = 'List all registered API routes';
/**
* The table headers for the command.
*
* @var array
*/
protected $headers = ['Host', 'Method', 'URI', 'Name', 'Action', 'Protected', 'Version(s)', 'Scope(s)', 'Rate Limit'];
/**
* Create a new routes command instance.
*
* @param \Dingo\Api\Routing\Router $router
*
* @return void
*/
public function __construct(Router $router)
{
// Ugly, but we need to bypass the constructor and directly target the
// constructor on the command class.
Command::__construct();
$this->router = $router;
}
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
$this->routes = $this->router->getRoutes();
parent::fire();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
$this->routes = $this->router->getRoutes();
parent::handle();
}
/**
* Compile the routes into a displayable format.
*
* @return array
*/
protected function getRoutes()
{
$routes = [];
foreach ($this->router->getRoutes() as $collection) {
foreach ($collection->getRoutes() as $route) {
$routes[] = $this->filterRoute([
'host' => $route->domain(),
'method' => implode('|', $route->methods()),
'uri' => $route->uri(),
'name' => $route->getName(),
'action' => $route->getActionName(),
'protected' => $route->isProtected() ? 'Yes' : 'No',
'versions' => implode(', ', $route->versions()),
'scopes' => implode(', ', $route->scopes()),
'rate' => $this->routeRateLimit($route),
]);
}
}
if ($sort = $this->option('sort')) {
$routes = Arr::sort($routes, function ($value) use ($sort) {
return $value[$sort];
});
}
if ($this->option('reverse')) {
$routes = array_reverse($routes);
}
if ($this->option('short')) {
$this->headers = ['Method', 'URI', 'Name', 'Version(s)'];
$routes = array_map(function ($item) {
return array_only($item, ['method', 'uri', 'name', 'versions']);
}, $routes);
}
return array_filter(array_unique($routes, SORT_REGULAR));
}
/**
* Display the routes rate limiting requests per second. This takes the limit
* and divides it by the expiration time in seconds to give you a rough
* idea of how many requests you'd be able to fire off per second
* on the route.
*
* @param \Dingo\Api\Routing\Route $route
*
* @return null|string
*/
protected function routeRateLimit($route)
{
[$limit, $expires] = [$route->getRateLimit(), $route->getRateLimitExpiration()];
if ($limit && $expires) {
return sprintf('%s req/s', round($limit / ($expires * 60), 2));
}
}
/**
* Filter the route by URI, Version, Scopes and / or name.
*
* @param array $route
*
* @return array|null
*/
protected function filterRoute(array $route)
{
$filters = ['name', 'path', 'protected', 'unprotected', 'versions', 'scopes'];
foreach ($filters as $filter) {
if ($this->option($filter) && ! $this->{'filterBy'.ucfirst($filter)}($route)) {
return;
}
}
return $route;
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
$options = parent::getOptions();
foreach ($options as $key => $option) {
if ($option[0] == 'sort') {
unset($options[$key]);
}
}
return array_merge(
$options,
[
['sort', null, InputOption::VALUE_OPTIONAL, 'The column (domain, method, uri, name, action) to sort by'],
['versions', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Filter the routes by version'],
['scopes', 'S', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Filter the routes by scopes'],
['protected', null, InputOption::VALUE_NONE, 'Filter the protected routes'],
['unprotected', null, InputOption::VALUE_NONE, 'Filter the unprotected routes'],
['short', null, InputOption::VALUE_NONE, 'Get an abridged version of the routes'],
]
);
}
/**
* Filter the route by its path.
*
* @param array $route
*
* @return bool
*/
protected function filterByPath(array $route)
{
return Str::contains($route['uri'], $this->option('path'));
}
/**
* Filter the route by whether or not it is protected.
*
* @param array $route
*
* @return bool
*/
protected function filterByProtected(array $route)
{
return $this->option('protected') && $route['protected'] == 'Yes';
}
/**
* Filter the route by whether or not it is unprotected.
*
* @param array $route
*
* @return bool
*/
protected function filterByUnprotected(array $route)
{
return $this->option('unprotected') && $route['protected'] == 'No';
}
/**
* Filter the route by its versions.
*
* @param array $route
*
* @return bool
*/
protected function filterByVersions(array $route)
{
foreach ($this->option('versions') as $version) {
if (Str::contains($route['versions'], $version)) {
return true;
}
}
return false;
}
/**
* Filter the route by its name.
*
* @param array $route
*
* @return bool
*/
protected function filterByName(array $route)
{
return Str::contains($route['name'], $this->option('name'));
}
/**
* Filter the route by its scopes.
*
* @param array $route
*
* @return bool
*/
protected function filterByScopes(array $route)
{
foreach ($this->option('scopes') as $scope) {
if (Str::contains($route['scopes'], $scope)) {
return true;
}
}
return false;
}
}
<?php
namespace Dingo\Api\Contract\Auth;
use Dingo\Api\Routing\Route;
use Illuminate\Http\Request;
interface Provider
{
/**
* Authenticate the request and return the authenticated user instance.
*
* @param \Illuminate\Http\Request $request
* @param \Dingo\Api\Routing\Route $route
*
* @return mixed
*/
public function authenticate(Request $request, Route $route);
}
<?php
namespace Dingo\Api\Contract\Debug;
use Exception;
interface ExceptionHandler
{
/**
* Handle an exception.
*
* @param \Exception $exception
*
* @return \Illuminate\Http\Response
*/
public function handle(Exception $exception);
}
<?php
namespace Dingo\Api\Contract\Debug;
interface MessageBagErrors
{
/**
* Get the errors message bag.
*
* @return \Illuminate\Support\MessageBag
*/
public function getErrors();
/**
* Determine if message bag has any errors.
*
* @return bool
*/
public function hasErrors();
}
<?php
namespace Dingo\Api\Contract\Http;
use Illuminate\Http\Request as IlluminateRequest;
interface Parser
{
/**
* Parse an incoming request.
*
* @param \Illuminate\Http\Request $request
*
* @return mixed
*/
public function parse(IlluminateRequest $request);
}
<?php
namespace Dingo\Api\Contract\Http\RateLimit;
use Dingo\Api\Http\Request;
use Illuminate\Container\Container;
interface HasRateLimiter
{
/**
* Get rate limiter callable.
*
* @param \Illuminate\Container\Container $app
* @param \Dingo\Api\Http\Request $request
*
* @return string
*/
public function getRateLimiter(Container $app, Request $request);
}
<?php
namespace Dingo\Api\Contract\Http\RateLimit;
use Illuminate\Container\Container;
interface Throttle
{
/**
* Attempt to match the throttle against a given condition.
*
* @param \Illuminate\Container\Container $container
*
* @return bool
*/
public function match(Container $container);
/**
* Get the time in minutes that the throttles request limit will expire.
*
* @return int
*/
public function getExpires();
/**
* Get the throttles request limit.
*
* @return int
*/
public function getLimit();
}
<?php
namespace Dingo\Api\Contract\Http;
use Illuminate\Http\Request as IlluminateRequest;
interface Request
{
/**
* Create a new Dingo request instance from an Illuminate request instance.
*
* @param \Illuminate\Http\Request $old
*
* @return \Dingo\Api\Http\Request
*/
public function createFromIlluminate(IlluminateRequest $old);
}
<?php
namespace Dingo\Api\Contract\Http;
use Illuminate\Http\Request as IlluminateRequest;
interface Validator
{
/**
* Validate a request.
*
* @param \Illuminate\Http\Request $request
*
* @return bool
*/
public function validate(IlluminateRequest $request);
}
<?php
namespace Dingo\Api\Contract\Routing;
use Illuminate\Http\Request;
interface Adapter
{
/**
* Dispatch a request.
*
* @param \Illuminate\Http\Request $request
* @param string $version
*
* @return mixed
*/
public function dispatch(Request $request, $version);
/**
* Get the URI, methods, and action from the route.
*
* @param mixed $route
* @param \Illuminate\Http\Request $request
*
* @return array
*/
public function getRouteProperties($route, Request $request);
/**
* Add a route to the appropriate route collection.
*
* @param array $methods
* @param array $versions
* @param string $uri
* @param mixed $action
*
* @return void
*/
public function addRoute(array $methods, array $versions, $uri, $action);
/**
* Get all routes or only for a specific version.
*
* @param string $version
*
* @return mixed
*/
public function getRoutes($version = null);
/**
* Get a normalized iterable set of routes. Top level key must be a version with each
* version containing iterable routes that can be consumed by the adapter.
*
* @param string $version
*
* @return mixed
*/
public function getIterableRoutes($version = null);
/**
* Set the routes on the adapter.
*
* @param array $routes
*
* @return void
*/
public function setRoutes(array $routes);
/**
* Prepare a route for serialization.
*
* @param mixed $route
*
* @return mixed
*/
public function prepareRouteForSerialization($route);
}
<?php
namespace Dingo\Api\Contract\Transformer;
use Dingo\Api\Http\Request;
use Dingo\Api\Transformer\Binding;
interface Adapter
{
/**
* Transform a response with a transformer.
*
* @param mixed $response
* @param object $transformer
* @param \Dingo\Api\Transformer\Binding $binding
* @param \Dingo\Api\Http\Request $request
*
* @return array
*/
public function transform($response, $transformer, Binding $binding, Request $request);
}
<?php
namespace Dingo\Api\Event;
use Dingo\Api\Http\Request;
use Illuminate\Contracts\Container\Container;
class RequestWasMatched
{
/**
* Request instance.
*
* @var \Dingo\Api\Http\Request
*/
public $request;
/**
* Application instance.
*
* @var \Illuminate\Contracts\Container\Container
*/
public $app;
/**
* Create a new request was matched event.
*
* @param \Dingo\Api\Http\Request $request
* @param \Illuminate\Contracts\Container\Container $app
*
* @return void
*/
public function __construct(Request $request, Container $app)
{
$this->request = $request;
$this->app = $app;
}
}
<?php
namespace Dingo\Api\Event;
use Dingo\Api\Http\Response;
class ResponseIsMorphing
{
/**
* Response instance.
*
* @var \Dingo\Api\Http\Response
*/
public $response;
/**
* Response content.
*
* @var string
*/
public $content;
/**
* Create a new response is morphing event. Content is passed by reference
* so that multiple listeners can modify content.
*
* @param \Dingo\Api\Http\Response $response
* @param string $content
*
* @return void
*/
public function __construct(Response $response, &$content)
{
$this->response = $response;
$this->content = &$content;
}
}
<?php
namespace Dingo\Api\Exception;
use Exception;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
class InternalHttpException extends HttpException
{
/**
* The response.
*
* @var \Illuminate\Http\Response
*/
protected $response;
/**
* Create a new internal HTTP exception instance.
*
* @param \Symfony\Component\HttpFoundation\Response $response
* @param string $message
* @param \Exception $previous
* @param array $headers
* @param int $code
*
* @return void
*/
public function __construct(Response $response, $message = null, Exception $previous = null, array $headers = [], $code = 0)
{
$this->response = $response;
parent::__construct($response->getStatusCode(), $message, $previous, $headers, $code);
}
/**
* Get the response of the internal request.
*
* @return \Illuminate\Http\Response
*/
public function getResponse()
{
return $this->response;
}
}
<?php
namespace Dingo\Api\Exception;
use Exception;
use Symfony\Component\HttpKernel\Exception\HttpException;
class RateLimitExceededException extends HttpException
{
/**
* Create a new rate limit exceeded exception instance.
*
* @param string $message
* @param \Exception $previous
* @param array $headers
* @param int $code
*
* @return void
*/
public function __construct($message = null, Exception $previous = null, $headers = [], $code = 0)
{
if (array_key_exists('X-RateLimit-Reset', $headers)) {
$headers['Retry-After'] = $headers['X-RateLimit-Reset'] - time();
}
parent::__construct(429, $message ?: 'You have exceeded your rate limit.', $previous, $headers, $code);
}
}
<?php
namespace Dingo\Api\Exception;
use Exception;
use Illuminate\Support\MessageBag;
use Dingo\Api\Contract\Debug\MessageBagErrors;
use Symfony\Component\HttpKernel\Exception\HttpException;
class ResourceException extends HttpException implements MessageBagErrors
{
/**
* MessageBag errors.
*
* @var \Illuminate\Support\MessageBag
*/
protected $errors;
/**
* Create a new resource exception instance.
*
* @param string $message
* @param \Illuminate\Support\MessageBag|array $errors
* @param \Exception $previous
* @param array $headers
* @param int $code
*
* @return void
*/
public function __construct($message = null, $errors = null, Exception $previous = null, $headers = [], $code = 0)
{
if (is_null($errors)) {
$this->errors = new MessageBag;
} else {
$this->errors = is_array($errors) ? new MessageBag($errors) : $errors;
}
parent::__construct(422, $message, $previous, $headers, $code);
}
/**
* Get the errors message bag.
*
* @return \Illuminate\Support\MessageBag
*/
public function getErrors()
{
return $this->errors;
}
/**
* Determine if message bag has any errors.
*
* @return bool
*/
public function hasErrors()
{
return ! $this->errors->isEmpty();
}
}
<?php
namespace Dingo\Api\Exception;
class StoreResourceFailedException extends ResourceException
{
//
}
<?php
namespace Dingo\Api\Exception;
use Exception;
use Symfony\Component\HttpKernel\Exception\HttpException;
class UnknownVersionException extends HttpException
{
/**
* Create a new unknown version exception instance.
*
* @param string $message
* @param \Exception $previous
* @param int $code
*
* @return void
*/
public function __construct($message = null, Exception $previous = null, $code = 0)
{
parent::__construct(400, $message ?: 'The version given was unknown or has no registered routes.', $previous, [], $code);
}
}
<?php
namespace Dingo\Api\Exception;
class UpdateResourceFailedException extends ResourceException
{
//
}
<?php
namespace Dingo\Api\Exception;
use Exception;
class ValidationHttpException extends ResourceException
{
/**
* Create a new validation HTTP exception instance.
*
* @param \Illuminate\Support\MessageBag|array $errors
* @param \Exception $previous
* @param array $headers
* @param int $code
*
* @return void
*/
public function __construct($errors = null, Exception $previous = null, $headers = [], $code = 0)
{
parent::__construct(null, $errors, $previous, $headers, $code);
}
}
<?php
namespace Dingo\Api\Facade;
use Dingo\Api\Http\InternalRequest;
use Illuminate\Support\Facades\Facade;
class API extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'api.dispatcher';
}
/**
* Bind an exception handler.
*
* @param callable $callback
*
* @return void
*/
public static function error(callable $callback)
{
return static::$app['api.exception']->register($callback);
}
/**
* Register a class transformer.
*
* @param string $class
* @param string|\Closure $transformer
*
* @return \Dingo\Api\Transformer\Binding
*/
public static function transform($class, $transformer)
{
return static::$app['api.transformer']->register($class, $transformer);
}
/**
* Get the authenticator.
*
* @return \Dingo\Api\Auth\Auth
*/
public static function auth()
{
return static::$app['api.auth'];
}
/**
* Get the authenticated user.
*
* @return \Illuminate\Auth\GenericUser|\Illuminate\Database\Eloquent\Model
*/
public static function user()
{
return static::$app['api.auth']->user();
}
/**
* Determine if a request is internal.
*
* @return bool
*/
public static function internal()
{
return static::$app['api.router']->getCurrentRequest() instanceof InternalRequest;
}
/**
* Get the response factory to begin building a response.
*
* @return \Dingo\Api\Http\Response\Factory
*/
public static function response()
{
return static::$app['api.http.response'];
}
/**
* Get the API router instance.
*
* @return \Dingo\Api\Routing\Router
*/
public static function router()
{
return static::$app['api.router'];
}
/**
* Get the API route of the given name, and optionally specify the API version.
*
* @param string $routeName
* @param string $apiVersion
*
* @return string
*/
public static function route($routeName, $apiVersion = 'v1')
{
return static::$app['api.url']->version($apiVersion)->route($routeName);
}
}
<?php
namespace Dingo\Api\Facade;
use Illuminate\Support\Facades\Facade;
class Route extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'api.router';
}
}
<?php
namespace Dingo\Api\Http;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Validation\Validator;
use Dingo\Api\Exception\ValidationHttpException;
use Illuminate\Validation\ValidatesWhenResolvedTrait;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Illuminate\Contracts\Validation\ValidatesWhenResolved;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
class FormRequest extends Request implements ValidatesWhenResolved
{
use ValidatesWhenResolvedTrait;
/**
* The container instance.
*
* @var \Illuminate\Contracts\Container\Container
*/
protected $container;
/**
* The redirector instance.
*
* @var \Illuminate\Routing\Redirector
*/
protected $redirector;
/**
* The URI to redirect to if validation fails.
*
* @var string
*/
protected $redirect;
/**
* The route to redirect to if validation fails.
*
* @var string
*/
protected $redirectRoute;
/**
* The controller action to redirect to if validation fails.
*
* @var string
*/
protected $redirectAction;
/**
* The key to be used for the view error bag.
*
* @var string
*/
protected $errorBag = 'default';
/**
* The input keys that should not be flashed on redirect.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
/**
* Validate the request.
*/
public function validate()
{
if ($this->authorize() === false) {
throw new AccessDeniedHttpException();
}
$validator = app('validator')->make($this->all(), $this->rules(), $this->messages());
if ($validator->fails()) {
throw new ValidationHttpException($validator->errors());
}
}
/**
* Get the validator instance for the request.
*
* @return \Illuminate\Contracts\Validation\Validator
*
* @SuppressWarnings(PHPMD.ElseExpression)
*/
protected function getValidatorInstance()
{
$factory = $this->container->make(ValidationFactory::class);
if (method_exists($this, 'validator')) {
$validator = $this->container->call([$this, 'validator'], compact('factory'));
} else {
$validator = $this->createDefaultValidator($factory);
}
if (method_exists($this, 'withValidator')) {
$this->withValidator($validator);
}
return $validator;
}
/**
* Create the default validator instance.
*
* @param \Illuminate\Contracts\Validation\Factory $factory
*
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function createDefaultValidator(ValidationFactory $factory)
{
return $factory->make(
$this->validationData(),
$this->container->call([$this, 'rules']),
$this->messages(),
$this->attributes()
);
}
/**
* Get data to be validated from the request.
*
* @return array
*/
protected function validationData()
{
return $this->all();
}
/**
* Handle a failed validation attempt.
*
* @param \Illuminate\Contracts\Validation\Validator $validator
*
* @return void
*/
protected function failedValidation(Validator $validator)
{
if ($this->container['request'] instanceof Request) {
throw new ValidationHttpException($validator->errors());
}
parent::failedValidation($validator);
}
/**
* Get the proper failed validation response for the request.
*
* @param array $errors
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function response(array $errors)
{
if ($this->expectsJson()) {
return new JsonResponse($errors, 422);
}
return $this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
}
/**
* Format the errors from the given Validator instance.
*
* @param \Illuminate\Contracts\Validation\Validator $validator
*
* @return array
*/
protected function formatErrors(Validator $validator)
{
return $validator->getMessageBag()->toArray();
}
/**
* Get the URL to redirect to on a validation error.
*
* @return string
*/
protected function getRedirectUrl()
{
$url = $this->redirector->getUrlGenerator();
if ($this->redirect) {
return $url->to($this->redirect);
} elseif ($this->redirectRoute) {
return $url->route($this->redirectRoute);
} elseif ($this->redirectAction) {
return $url->action($this->redirectAction);
}
return $url->previous();
}
/**
* Determine if the request passes the authorization check.
*
* @return bool
*/
protected function passesAuthorization()
{
if (method_exists($this, 'authorize')) {
return $this->container->call([$this, 'authorize']);
}
return false;
}
/**
* Handle a failed authorization attempt.
*
* @return void
*/
protected function failedAuthorization()
{
if ($this->container['request'] instanceof Request) {
throw new HttpException(403);
}
parent::failedAuthorization();
}
/**
* Get custom messages for validator errors.
*
* @return array
*/
public function messages()
{
return [];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes()
{
return [];
}
/**
* Set the Redirector instance.
*
* @param \Laravel\Lumen\Http\Redirector|\Illuminate\Routing\Redirector $redirector
*
* @return $this
*/
public function setRedirector($redirector)
{
$this->redirector = $redirector;
return $this;
}
/**
* Set the container implementation.
*
* @param \Illuminate\Contracts\Container\Container $container
*
* @return $this
*/
public function setContainer(Container $container)
{
$this->container = $container;
return $this;
}
}
<?php
namespace Dingo\Api\Http;
class InternalRequest extends Request
{
public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null)
{
parent::__construct($query, $request, $attributes, $cookies, $files, $server, $content);
// Pass parameters inside internal request into Laravel's JSON ParameterBag,
// so that they can be accessed using $request->input()
if ($this->isJson() && isset($this->request)) {
$this->setJson($this->request);
}
}
}
<?php
namespace Dingo\Api\Http\Middleware;
use Closure;
use Dingo\Api\Routing\Router;
use Dingo\Api\Auth\Auth as Authentication;
class Auth
{
/**
* Router instance.
*
* @var \Dingo\Api\Routing\Router
*/
protected $router;
/**
* Authenticator instance.
*
* @var \Dingo\Api\Auth\Auth
*/
protected $auth;
/**
* Create a new auth middleware instance.
*
* @param \Dingo\Api\Routing\Router $router
* @param \Dingo\Api\Auth\Auth $auth
*
* @return void
*/
public function __construct(Router $router, Authentication $auth)
{
$this->router = $router;
$this->auth = $auth;
}
/**
* Perform authentication before a request is executed.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$route = $this->router->getCurrentRoute();
if (! $this->auth->check(false)) {
$this->auth->authenticate($route->getAuthenticationProviders());
}
return $next($request);
}
}
<?php
namespace Dingo\Api\Http\Middleware;
use Closure;
use Dingo\Api\Routing\Router;
class PrepareController
{
/**
* Dingo router instance.
*
* @var \Dingo\Api\Routing\Router
*/
protected $router;
/**
* Create a new prepare controller instance.
*
* @param \Dingo\Api\Routing\Router $router
*
* @return void
*/
public function __construct(Router $router)
{
$this->router = $router;
}
/**
* Handle the request.
*
* @param \Dingo\Api\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
// To prepare the controller all we need to do is call the current method on the router to fetch
// the current route. This will create a new Dingo\Api\Routing\Route instance and prepare the
// controller by binding it as a singleton in the container. This will result in the
// controller only be instantiated once per request.
$this->router->current();
return $next($request);
}
}
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 sign in to comment