日志-2019年9月

2019-9-2 周一

查询格式

类似于SELECT …的可以修改为这种形式:
pic

2019-9-3 周二

表驱动法(Table-Driven Approach)

用数组代替if-else和switch-case语句
通过在表中查找信息,来代替很多复杂的if-else或者switch-case逻辑判断。这是一种设计的技巧,可以应用很多的场合,不仅可以提高程序的性能,也能大大减少代码量,使得代码变得高效和优雅

用数组代替if-else和switch-case语句 shudou
浅析PHP数组的实现 OamMot

相关实现案例

//判断是否闰年,若为闰年返回1,否则返回0
int IsLeapYear(unsigned int year)
{
	if ((0 == year % 4 && 0 != year % 100) || (0 == year % 400))
		return 1;
	return 0;
}
 
static unsigned int monthdays[2][12] = 
{
	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
}
 
//获取year年month月的天数
unsigned int GetMonthDays(unsigned int year, unsigned int month)
{
	return monthdyas[IsYeapYear(year)][month - 1];
}

2019-9-4 周三

Laravel 6.0 发布

官方文档

注释

相关注释的格式和案例:

/**
 * @api {get} /inner/attributes 属性列表
 * @api http://yapi.lanhanba.com:3000/project/36/interface/api/5892
 * @param  AttributeRequest  $request
 * @return AnonymousResourceCollection
 * @throws \Exception
 */

其中 AnonymousResourceCollection
需要 use Illuminate\Http\Resources\Json\AnonymousResourceCollection;

缓存清理

!重要
php artisan cache:clear
会返回

Cache cleared successfully.

其它缓存

route cache

$ php artisan route:cache

config cache

$ php artisan config:cache

2019-9-5 周四

变基时需要注意很多东西

2019-9-6 周五

!早上需要运行 php artisan cache:clear 清理缓存
部分使用缓存的功能需要重置,否则数据为空

数据库执行超时

 Caused by
 Doctrine\DBAL\Driver\PDOException: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction

解决方法:
执行

SHOW FULL PROCESSLIST;

查看当前的数据库链接情况,然后有阻塞的可以执行

KILL {Id}

可以临时解决阻塞问题

2019-9-7 周六

注释里的链接可以写成
@link http://yapi.lanhanba.com:3000/project/36/interface/api/5892
测试里的跳转可以写成
@see AttributeController::index

2019-9-9 周一

在测试顶部中可以使用以下注释,以忽略重名的类和未定义的方法

<?php
/* @noinspection PhpUndefinedClassInspection */
/* @noinspection PhpUndefinedMethodInspection */
namespace Tests\Feature\Inner\V1;
use Tests\TestCase;
class CategoryControllerTest extends TestCase
{
	// 省略
}
?>

2019-9-10 周二

function_exists 函数
function_exists ( string $function_name ) : bool 如果给定的函数已经被定义就返回 TRUE

if (!function_exists('combine_attributes')) {
    function combine_attributes($communityAttributes, $categoryAttributes)
	{
		// 省略
	}
}

2019-9-11 周三

CURL GET 请求

function curl_get($url){
	$header = array(
		'Accept: application/json',
	);
	$curl = curl_init();
	//设置抓取的url
	curl_setopt($curl, CURLOPT_URL, $url);
	//设置头文件的信息作为数据流输出
	curl_setopt($curl, CURLOPT_HEADER, 0);
	// 超时设置,以秒为单位
	curl_setopt($curl, CURLOPT_TIMEOUT, 1);
	// 超时设置,以毫秒为单位
	// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
	// 设置请求头
	curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
	//设置获取的信息以文件流的形式返回,而不是直接输出。
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
	//执行命令
	$data = curl_exec($curl);

	// 显示错误信息
	if (curl_error($curl)) {
		print "Error: " . curl_error($curl);
	} else {
		// 打印返回的内容
		var_dump($data);
		curl_close($curl);
	}
}

2019-9-12 周四

CURL POST 请求

// $url 是请求的链接
// $postdata 是传输的数据,数组格式
function curl_post( $url, $postdata ) {
	$header = array(
		'Accept: application/json',
	);
	//初始化
	$curl = curl_init();
	//设置抓取的url
	curl_setopt($curl, CURLOPT_URL, $url);
	//设置头文件的信息作为数据流输出
	curl_setopt($curl, CURLOPT_HEADER, 0);
	//设置获取的信息以文件流的形式返回,而不是直接输出。
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
	// 超时设置
	curl_setopt($curl, CURLOPT_TIMEOUT, 10);
	// 超时设置,以毫秒为单位
	// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
	// 设置请求头
	curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
	//设置post方式提交
	curl_setopt($curl, CURLOPT_POST, 1);
	curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
	//执行命令
	$data = curl_exec($curl);
	// 显示错误信息
	if (curl_error($curl)) {
		print "Error: " . curl_error($curl);
	} else {
		// 打印返回的内容
		var_dump($data);
		curl_close($curl);
	}
}

CURL 参考文章

2019-9-16 周一

部署时需要执行的命令在 deployment/v3.15-depoly.sh 文件下,格式如下:

''#! /bin/bash
cd ./../
''# 清空包缓存
php artisan clear-compiled
''# 清空php代码缓存
php artisan opcache:clear
''# 安装扩展
composer install --ignore-platform-reqs --prefer-dist --no-scripts --no-dev -o
''# 优化 composer 生成 classmap
composer dump-autoload -o
''# 缓存配置文件信息
php artisan config:cache
''# 执行迁移文件
php artisan migrate
''# 清除类目属性缓存
echo '清除类目属性缓存'
php artisan redis:clear --key=cate:*

2019-9-17 周二

返回值是对象而不是数组的BUG

$category->attributes = $category->attributes->where('is_user_edit', '=', Attribute::USER_EDIT_NEED);
return new CategoryResource($category);

使用 values() 解决:

$category->attributes = $category->attributes->where('is_user_edit', '=', Attribute::USER_EDIT_NEED)->values();
return new CategoryResource($category);

2019-9-18 周三

查询参考

$user = auth('api')->user(); // 获取用户
$yesterday = Carbon::yesterday(); // Carbon时间取昨天
$invoice_overtime = Invoice::INVOICE_OVERTIME; // 超时默认定义是90
$sixMonths = Carbon::now()->subMonths(6); // 6个月
$list = FieldOrderItem::select('id as field_order_item_id', 'selling_resource_id','start', 'end', 'size', 'lease_term_type', 'actual_fee', 'subsidy_fee', 'tax','deducted', 'deposit', 'custom_dimension', 'pic_url', 'title', 'paid_at', 'execute_period', 'service_fee', 'status', 'invoice_status', 'coupon_amount', 'invoice_cancel_reason')
->orderByRaw("date_add(start, interval {$invoice_overtime} day) > curdate() desc") // 未过期的排在前面
->orderBy('created_at', 'desc')
->where('user_id', $user->id) // 当前用户的
->whereIn('invoice_status', [FieldOrderItem::INVOICE_STATUS_UNISSUE, FieldOrderItem::INVOICE_STATUS_PRE_ISSUE]) // 未开发票的和已预开票的
->whereNull('invoice_id')
->whereNotNull('paid_at')
->whereNotNull('approved_at') // 审核过/进行中
->whereNull('canceled_at') // 未取消的
->where('start', '<=', $yesterday) // 当前日期 >= 执行日期+1天
->where('start', '>=', $sixMonths) // 当前日期 <= 执行日期+6个月
->with([
'selling_resource' => function ($q) {
$q->select('id', 'physical_resource_id');
}, 'selling_resource.physical_resource' => function ($q) {
$q->select('id', 'field_type_id');
}, 'selling_resource.physical_resource.field_type' => function ($q) {
$q->select('id', 'display_name');
},
])
->paginate($request->input('pageSize', CommonValue::DEFAULT_LENGTH));
foreach ($list as $item) { // 遍历一遍
$item->issue_invoice = $item->IssueInvoice();
$item->actual_fee = $item->realPay();
$item->deposit = $item->deposit ? $item->deposit * 100 : 0;
$item->coupon_amount = $item->coupon_amount ? $item->coupon_amount * 100 : 0;
if ($item->invoice_status == FieldOrderItem::INVOICE_STATUS_PRE_ISSUE) { // 标记已预先开票的拒绝理由
$item->invoice_cancel_reason = '已提前开具发票';
}
}
return response()->success($list->toArray());

奇怪的BUG

模型的 save () 和 update () 无法保存成功且不报错

在请求接口的时候偶尔会出现需要修改的值并没有被修改的情况,这个问题可以复现,但是没有报错,偶尔出现不能修改问题后通过多次请求接口又可以修改,一旦可以修改某一个订单数据那么接下来对这个订单的请求就都可以修改成功

相似问题链接

没有报错信息,$fillable 也正常,问题很奇怪

目前的解决方法,修改完后的代码:

/**
* @api {post} orders/field_order_item/pre_invoice 预先开票接口
* @api http://yapi.lanhanba.com:3000/project/36/interface/api/6017
* @param  PreInvoiceFieldOrderItemRequest  $request
* @return
*/
public function preInvoice(PreInvoiceFieldOrderItemRequest $request)
{
$isPreInvoice = $request->input('is_pre_invoice');
$fieldOrderItem = FieldOrderItem::where('id', $request->input('id'))
->whereIn('invoice_status', [
FieldOrderItem::INVOICE_STATUS_UNISSUE, FieldOrderItem::INVOICE_STATUS_PRE_ISSUE
])
->first();
if (is_null($fieldOrderItem)) {
return response()->fail(self::ERROR_PRE_INVOICE_CODE, self::ERROR_PRE_INVOICE_MSG);
}
if ($isPreInvoice == 1) {
$fieldOrderItem->update([
'invoice_status' => FieldOrderItem::INVOICE_STATUS_PRE_ISSUE
]);
} else {
$fieldOrderItem->update([
'invoice_status' => FieldOrderItem::INVOICE_STATUS_UNISSUE
]);
}
return response()->success();
}

原先出问题的时候代码是这样的:

/**
* @api {post} orders/field_order_item/pre_invoice 预先开票接口
* @api http://yapi.lanhanba.com:3000/project/36/interface/api/6017
* @param  PreInvoiceFieldOrderItemRequest  $request
* @return
*/
public function preInvoice(PreInvoiceFieldOrderItemRequest $request)
{
$isPreInvoice = $request->input('is_pre_invoice');
$fieldOrderItem = FieldOrderItem::where('id', $request->input('id'))
->where('invoice_status', '=', FieldOrderItem::INVOICE_STATUS_UNISSUE)
->orwhere('invoice_status', '=', FieldOrderItem::INVOICE_STATUS_PRE_ISSUE)
->whereNull('deleted_at')
->first();
if (is_null($fieldOrderItem)) {
return response()->fail(self::ERROR_PRE_INVOICE_CODE, self::ERROR_PRE_INVOICE_MSG);
}
if ($isPreInvoice == 1) {
$fieldOrderItem->{'invoice_status'} = FieldOrderItem::INVOICE_STATUS_PRE_ISSUE;
} else {
$fieldOrderItem->{'invoice_status'} = FieldOrderItem::INVOICE_STATUS_UNISSUE;
}
$fieldOrderItem->save();
return response()->success();
}

修改点1:查询 FieldOrderItem 时有查询上的问题
修改点2:保存 FieldOrderItem 的方法由 save() 改成 update()
这样修改完后目前来看暂时没有出现问题

2019-9-19 周四

关联关系查询

原先是有一个状态为已取消的

case $parameter->status == Debit::STATUS_CANCELLED:   // 已取消
$query->whereHas('field_order_items', function ($query) {
$query->where('field_order_items.status', '=', 'canceled');
});
break;

更改后所有状态都是已取消的

case $parameter->status == Debit::STATUS_CANCELLED:   // 已取消
$query->whereDoesntHave('field_order_items', function ($query) {
$query->where('field_order_items.status', '<>', 'canceled');
});
break;

使用 whereDoesntHave

相关的查询文档

2019-9-20 周五

工具的额使用技巧:

PhpStorm官方网站

2019-9-21 周六

单元测试代码覆盖率报告:
/public/code-coverage
生成单元测试报告需要启用 Xdebug,目前存在开启 Xdebug 后速度会变得很慢的情况,暂未找到解决方案

2019-9-23 周一

Error {#3234
#message: "Call to a member function toDate() on integer"
#code: 0
#file: "E:\www\LinhuibaServer\app\Console\Commands\Test.php"
#line: 55
trace: {
E:\www\LinhuibaServer\app\Console\Commands\Test.php:55 {$g = (int)'你好';\r$g = $g->toDate();\r//dd(123);\r
}
App\Console\Commands\Test->handle() {}
E:\www\LinhuibaServer\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php:29 {}
E:\www\LinhuibaServer\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php:87 {}
E:\www\LinhuibaServer\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php:31 {}
E:\www\LinhuibaServer\vendor\laravel\framework\src\Illuminate\Container\Container.php:549 {}
E:\www\LinhuibaServer\app\Traits\ExceptionHandler.php:16 {}
E:\www\LinhuibaServer\vendor\symfony\console\Command\Command.php:255 {}
E:\www\LinhuibaServer\vendor\laravel\framework\src\Illuminate\Console\Command.php:170 {}
E:\www\LinhuibaServer\vendor\symfony\console\Application.php:969 {}
E:\www\LinhuibaServer\vendor\symfony\console\Application.php:255 {}
E:\www\LinhuibaServer\vendor\symfony\console\Application.php:148 {}
E:\www\LinhuibaServer\vendor\laravel\framework\src\Illuminate\Console\Application.php:88 {}
E:\www\LinhuibaServer\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php:121 {}
E:\www\LinhuibaServer\artisan:35 {}
}
}

2019-9-24 周二

输出当前环境

echo($_ENV['APP_ENV']);
echo \App::environment();

区分环境名:

private function getEnvName()
{
switch (\App::environment()) {
case 'local':
return '本地环境';
case 'integration':
return '集成环境';
case 'testing':
return '测试环境';
case 'preview':
return '预演环境';
case 'production':
return '生产环境';
default:
return \App::environment();
}
}

2019-9-25 周三

执行堆栈追踪

$bt =  debug_backtrace();
echo "Calling file: ". $bt[0]['file'] . ' line  '. $bt[0]['line'];

执行队列

php artisan queue:work

2019-9-26 周四

SQL

获取多个字段最大值最小值

SELECT GREATEST(DATE('2019-09-26'), DATE('2019-09-29'), DATE('1997-02-06'));-- 2019-09-29
SELECT LEAST(DATE('2019-09-26'), DATE('2015-09-29'), DATE('1997-02-06')); --1997-02-06

列1 为空时取 列2 的值

SELECT IFNULL(event_end, end_time) as event_end_time
-- 当event_end为空时返回end_time

这样其实也可以

select * from table order by IFNULL(updateDate, createDate) desc  

相关示例

-- 为空返回 1,否则返回 0
SELECT ISNULL(1+1); -- 0
SELECT ISNULL(0); -- 0
SELECT ISNULL(1/0); -- 1
SELECT ISNULL(null); -- 1
-- 第一个参数不为空则返回第一个参数,否则返回第二个参数
SELECT IFNULL(1,0); -- 1
SELECT IFNULL(null,100); -- 100
SELECT IFNULL(1/0,100); -- 100.0000
SELECT IFNULL(1/0,'100'); -- 100
SELECT IFNULL(1/0,'六六六'); -- 六六六
-- 相等则为 NULL 否则为第一个参数
SELECT NULLIF(1,1); -- null
SELECT NULLIF(1,2); -- 1
SELECT NULLIF(1,'1'); -- null
SELECT NULLIF('六六六','1'); -- 六六六
SELECT NULLIF(null,1/0); -- null

2019-9-27 周五

以下不一样的地方在于上面的是单个的下面的是集合

return new DepositHistoryResource($depositHistory);
return DepositHistoryResource::collection($depositHistory);

2019-9-29 周日

避免报错 Undefined index 避免字符串越界

isset($operateNames[$this->modified]) ? $operateNames[$this->modified] : $this->modified;

WITH 中有选择的列时,返回为空

而使用 select * 则正常返回
问题原因:未选择有关联关系的列

User::with(['tickets' => function ($q) {
$q->select('user_id');
}])->select('id')->get();

2019-9-30 周一

判断为空可以这样操作

if (!count($depositDetail)) {
return response()->fail(CommonValue::NODATA_CODE, CommonValue::NODATA_MSG);
}