coding code
change world

自己遵循多年的PHP代码规范

卢哥阅读(70)

PHP代码规范(非完全遵循psr-1,psr-2)

  • 代码tab键进行缩进,indent_size = 4
  • 每行的字符数应该软性保持在80个之内, 不可多于120个
  • 每个 namespace 命名空间声明语句和 use 声明语句块后面,必须插入一个空白行。
  • 类的开始花括号({)必须写在函数声明后自成一行,结束花括号(})也必须写在函数主体后自成一行。
  • 方法的开始花括号({)必须写在函数声明后自成一行,结束花括号(})也必须写在函数主体后自成一行。
  • 控制结构的关键字后必须要有一个空格符,而调用方法或函数时则一定不能有。
  • 控制结构的开始花括号({)必须写在声明的同一行,而结束花括号(})必须写在主体后自成一行。

1.1 例子

以下代码展示了绝大部分上述规范

<?php
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class Foo extends Bar implements FooInterface
{
	public function sampleFunction($a, $b = null)
	{
		if ($a === $b) {
			bar();
		} elseif ($a > $b) {
			$foo->bar($arg1);
		} else {
			BazClass::bar($arg2, $arg3);
		}
	}
	
	final public static functionbar()
	{
		// method body
	}
}

2.2 文件

  • 所有PHP文件必须使用Unix LF (linefeed)作为行的结束符。
  • 所有PHP文件必须以一个空白行作为结束。
  • 纯PHP代码文件必须省略最后的 ?> 结束标签。

关键字 以及 True/False/Null

PHP所有 关键字必须全部小写。 常量 true 、false 和 null 也必须全部小写。

方法的参数

参数列表中,每个参数后面必须要有一个空格,而前面一定不能有空格。

有默认值的参数,必须放到参数列表的末尾。

例子:

<?php
namespace Vendor\Package;

class ClassName
{
	public functionfoo($arg1, &$arg2, $arg3 = [])
	{
	// method body
	}
}

PHPSTORM设置

  • 勾选 Editor => General => Appearance => Show whitespaces
  • 安装editconfig插件,以下提供一份本公司通用的editconfig
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = whitespace
indent_size = 4
trim_trailing_whitespace = false

[*.php]
end_of_line = lf
indent_style = tab
indent_size = 4

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2

huhu~~,商城项目终于测试接近尾声,即将上线了

卢哥阅读(82)

将近一个半月的早996,确切的说比996更厉害,日志也断更了一些时日了,今天做一个阶段性的总结。

为什么一个人撸了所有的后端代码,干嘛不招人

  • 对于小公司来说,能活着并且盈利,已经不是那么容易,作为老板来说,总想着利益最大化,就导致了疯狂加班
  • 这段时间也确实面试了一些php程序员,但是基本都停留在用框架,脱离框架就无法动工
  • 短期内进人,会分散我的精力,由于项目紧急,也确实没时间带新人了
  • 可能是时间不对吧,最近面试的PHP开发人员质量确实不高,但是薪资要的确实高,只会用框架,windows作为开发操作系统,也没有经历过大流量高并发的锻炼,开口基本就是25k-30k,我是真的搞不懂这个招聘行情了,所以最近就一直没有找到合适的队员

遇到的问题

  • 项目急,导致需求并没有进行评审,给了产品原型,仔细过了几遍,就开始进行系统设计,编码,上测试环境了,个人是比较讨厌如此的不规范的骚操作的,但是现实就是这样,与其吐槽,不如在各种困难中把项目搞定才是真切
  • 多项目同时推进,战线拉得太长,我绝大部分时间是这样度过的,在写A项目,B项目有东西要做,写B的时候C项目因为流量激增,需要优化,当然C项目并不是我写的,但是我接手了,每天将近500万左右的请求量,主要服务员于淘宝卖家,然后每天在三个项目中间来回切换着写,庆幸的是,AB都即将上线,以后就是版本迭代,C的话就是不停的加入新功能并改造性能,因为已经发生性能上的问题

学到了啥?

  • 让自己更加坚韧了
  • 第一次在生产环境用上了swoole,并且swoole运行的很好,至少一周没出现过崩溃的情况
  • 自己脾气变的比以前好太多太多了

centos 安装redis 、设置密码

卢哥阅读(77)

yum install epel-release

yum install redis

redis-server /etc/redis.conf

redis-cli > CONFIG SET requirepass xinshiji@123

nginx 502,gdb 调试php-fpm子进程异常退出

卢哥阅读(143)

今天项目上线,在新的vps上部署了一套lnmp,原本部署php项目早就已经轻车熟路,谁知竟然翻车了,后来祭出gdb才最终搞定了php-fpm异常退出导致nginx 502 的bug,经查,据说这个bug是php7.3以后才有,未经考证,记录下处理过程

错误

[07-Jul-2020 18:05:35] WARNING: [pool www] child 25159 exited on signal 11 (SIGSEGV) after 99.606752 seconds from start
[07-Jul-2020 18:05:35] NOTICE: [pool www] child 25408 started
[07-Jul-2020 18:05:36] WARNING: [pool www] child 25155 exited on signal 11 (SIGSEGV) after 100.420225 seconds from start
[07-Jul-2020 18:05:36] NOTICE: [pool www] child 25410 started
[07-Jul-2020 18:05:36] WARNING: [pool www] child 25156 exited on signal 11 (SIGSEGV) after 101.007471 seconds from start
[07-Jul-2020 18:05:36] NOTICE: [pool www] child 25411 started
[07-Jul-2020 18:05:37] WARNING: [pool www] child 25160 exited on signal 11 (SIGSEGV) after 101.356937 seconds from start

设置core dump的生成路径

echo "/tmp/core.%p" > /proc/sys/kernel/core_pattern

修改ulimit允许生成 core dump

ulimit -c unlimited

重启php-fpm

service php-fpm restart

请求之前502的接口

查看/tmp文件夹,发现很多core.xxx文件

关闭ulimit

ulimit -c 0

gdb /usr/local/php/sbin/php-fpm -c /tmp/core.28826

Program terminated with signal 11, Segmentation fault.
#0  0x00007fe0a2a8d4a1 in redis_spprintf (redis_sock=redis_sock@entry=0x7fe0a927d240, slot=slot@entry=0x0, ret=ret@entry=0x7ffe4b02da20, kw=kw@entry=0x7fe0a2ab8220 "AUTH",
    fmt=fmt@entry=0x7fe0a2ab7790 "S") at /tmp/pear/temp/redis/library.c:855
855	/tmp/pear/temp/redis/library.c: No such file or directory.

一眼扫过去,瞬间锁定问题,大大的AUTH,猜想基本可能是redis的认证出问题了,然后去看了一下,果然,redis的密码没有设置正确,设置redis连接的正确密码后,php-fpm 进程退出的问题顺利解决

这里欠一个技术债,最近开发太忙了,下一篇文章,补上这个发生的真正原因

centos 安装 redis server实践备忘

卢哥阅读(75)

使用yum 安装,简单快捷,谁用谁知道

更新yum源

sudo yum install epel-release
sudo yum update
yum -y install redis

启动
systemctl start redis

重启
systemctl restart redis

停止
systemctl stop redis

开机自启
systemctl enable redis

禁止开机自启
systemctl disable redis

Gitbook-cli安装及使用说明

卢哥阅读(133)

Gitbook-cli是使用NPM来进行安装的,可以在命令行中输入下面的命令进行安装:


npm install gitbook-cli -g

安装完成之后,你可以使用下面的命令来检验是否安装成功

gitbook -V
gitbook init
gitbook serve

windows下3.2.3版本的gitbook会报错如下错误

解决办法:用3.0.0版本

gitbook fetch 3.0.0

恭喜,开始你的gitbook之旅吧

centos7 安装 nodejs

卢哥阅读(93)

1、增加nodejs的yum repo到系统

curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash -

2、输入yum 安装命令

sudo yum install nodejs

3、验证是否安装成功

node --version
npm --version

国内用户更换一下淘宝源

npm install --registry=https://registry.npm.taobao.org

分享一份曾经负责的社区电商的数据表结构

卢哥阅读(66)

说明:该项目已经不在线运营,所以把表结构放博客备忘。同时分享给有需要的coder

由于安全原因,不能上传sql文件,请下载后自行修改后缀成.SQL

CREATE TABLE merchants(
	id				INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,

	username		VARCHAR(32) NOT NULL,									# 登录用户名
	password		VARCHAR(255) NOT NULL,									# 加密密码
	simple_name		VARCHAR(255),											# 商家简称
	full_name		VARCHAR(255),											# 商家全称

	category_id		INT UNSIGNED,											# 主营分类
	type			TINYINT UNSIGNED,										# 商家类型 企业 个人

	province_id 	INT UNSIGNED,											# 省ID
	province_name	VARCHAR(50),											# 省名称
	city_id 		INT UNSIGNED,											# 市ID
	city_name		VARCHAR(50),											# 市名称
	district_id 	INT UNSIGNED,											# 区ID
	district_name	VARCHAR(50),											# 区名称
	address 		VARCHAR(255),											# 详细地址

	contact			VARCHAR(16),											# 联系人
	mobile 			CHAR(11),												# 联系手机号
	email			VARCHAR(64),											# 电子邮箱

	telephone		VARCHAR(16),											# 客服联系方式

	status			CHAR(1) NOT NULL,										# 状态
	reject_reason	VARCHAR(256),											# 驳回原因

	time 			DATETIME NOT NULL										# 创建时间
)ENGINE=INNODB;

ALTER TABLE merchants ADD UNIQUE INDEX idx_username(username);

CREATE TABLE merchant_exts(
	id					INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	merchant_id			INT UNSIGNED NOT NULL,								# merchants.id

	legal_name			VARCHAR(16),										# 姓名
	idcard				CHAR(19)		,									# 身份证号码
	idcard_expire_date	DATE,												# 身份证有效期
	idcard_front_url	VARCHAR(255),										# 身份证正面URL
	idcard_reverse_url	VARCHAR(255),										# 身份证反面URL
	idcard_manual_url	VARCHAR(255),										# 手持身份证URL

	legal_mobile		CHAR(11),											# 联系方式
	legal_email			VARCHAR(64),										# 联系邮箱

	company_name		VARCHAR(64),										# 公司名称
	business_address	VARCHAR(64),										# 公司经营地址

	license				VARCHAR(18),										# 营业执照|三证合一统一社会信用卡
	license_expire_date	DATE,												# 有效期至
	license_url			VARCHAR(255),										# 营业执照URL

	org_code			VARCHAR(9),											# 组织机构代码证
	org_expire_date		DATE,												# 组织机构代码证有效期
	org_url				VARCHAR(255),										# 组织机构代码证URL

	tax_code			VARCHAR(20),										# 纳税人识别码
	tax_url				VARCHAR(255),										# 税务登记证书URL

	opening_permit_url	VARCHAR(255),										# 开户许可证URL

	# 发票相关
	invoice_type		TINYINT UNSIGNED,									# 发票类型
	invoice_title		VARCHAR(64),										# 发票抬头
	invoice_tax			VARCHAR(20),										# 税务识别号
	invoice_recipient	VARCHAR(16),										# 收件人
	invoice_mobile		CHAR(11),											# 联系电话
	invoice_address		VARCHAR(128),										# 收货地址

	# 收款信息
	payee_name			VARCHAR(64),										# 收款方名称
	payee_bankcard		VARCHAR(20),										# 银行账号
	payee_bank_address	VARCHAR(128),										# 开户行
	payee_currency		TINYINT UNSIGNED									# 币种
)ENGINE=INNODB;

# 地区表
CREATE TABLE areas(
	id					INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
	name				VARCHAR(50) NOT NULL,								# 地区名称 如 华东
	pinyin_name_abbr	VARCHAR(10),										# 简称
	sorder				TINYINT UNSIGNED DEFAULT '0'						# 排序
)ENGINE=INNODB;

# 省份表
CREATE TABLE provinces (
	id					INT UNSIGNED NOT NULL PRIMARY KEY,
	code				VARCHAR(6) NOT NULL,								# 省份code
	name				VARCHAR(50) NOT NULL,								# 省份名称
	name_abbr			VARCHAR(50),										# 名称简称
	pinyin_name			VARCHAR(50),										# 省份拼音
	pinyin_name_abbr	VARCHAR(20),										# 省份拼音简称
	sorder				INT UNSIGNED NOT NULL DEFAULT '0',					# 排序
	area_id				TINYINT UNSIGNED NOT NULL,							# 地区ID 指华东 华北
	en_name				VARCHAR(100)										# 英文名称
) ENGINE=InnoDB;


CREATE TABLE cities(
	id					INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	code				VARCHAR(6) NOT NULL,							# 城市代码
	name				VARCHAR(50) NOT NULL,							# 城市名称
	name_abbr			VARCHAR(50),									# 名称简称
	pinyin_name			VARCHAR(50),									# 拼音
	pinyin_name_abbr	VARCHAR(20),									# 拼音简称
	en_name				VARCHAR(100),									# 英文名称
	longitude			VARCHAR(60),									# 经度
	latitude			VARCHAR(60),									# 纬度
	province_code		VARCHAR(6) NOT NULL								# 省份code
) ENGINE=InnoDB;

CREATE TABLE districts(
	id INT UNSIGNED NOT NULL PRIMARY KEY,
	code				VARCHAR(6) NOT NULL,							# 城市代码
	name				VARCHAR(50) NOT NULL,							# 城市名称
	name_abbr			VARCHAR(50),									# 名称简称
	pinyin_name			VARCHAR(50),									# 拼音
	pinyin_name_abbr	VARCHAR(20),									# 拼音简称
	city_code			VARCHAR(6) NOT NULL								# 城市代码
) ENGINE = InnoDB;

# 银行
CREATE TABLE banks(
	id			INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
	name		VARCHAR(255) NOT NULL,								# 支行名称
	head_name	VARCHAR(255) NOT NULL,								# 总行
	city_id		INT UNSIGNED NOT NULL								# 城市ID
)ENGINE=INNODB;
ALTER TABLE banks ADD INDEX idx_city_id(city_id);


CREATE TABLE merchant_logs(
	id			INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	merchant_id	INT UNSIGNED NOT NULL,								# 商户ID
	op			CHAR(2) NOT NULL,									# 操作 MCOP_*
	context_id	INT UNSIGNED,										# 上下文ID
	additional	TEXT,												# 日志内容
	time DATETIME NOT NULL											# 创建时间
)ENGINE=INNODB;

CREATE TABLE spus(
	id 					INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	merchant_id			INT UNSIGNED NOT NULL,								# 商户ID

	# 搜索展示相关
	spu_sn 				VARCHAR(32) NOT NULL,								# spu编码
	name				VARCHAR(255) NOT NULL,								# spu 名称
	search_name			VARCHAR(10000) NOT NULL,							# 搜索关键字
	category_id			INT NOT NULL,										# 分类id
	selling_points		VARCHAR(255) NOT NULL DEFAULT '',					# 卖点
	min_price			BIGINT UNSIGNED,									# sku最低价格
	max_price			BIGINT UNSIGNED,									# sku最高价格


	vitural_number		INT UNSIGNED NOT NULL DEFAULT 0,					# 虚拟销量
	actual_number			INT UNSIGNED NOT NULL DEFAULT 0,				# 实际销量

	# 运费相关
	freight_configid	INT UNSIGNED NOT NULL,										# 运费模版

	# 封面轮播图
	picture_url			VARCHAR(255) NOT NULL,								# 封面图
	carousel_imgs		JSON,												# 轮播图JSON

	# 状态
	status				CHAR(1) NOT NULL,									# 状态 SPU_STATUS_*
	state				CHAR(1) NOT NULL,									# 审核状态 SPU_STATE_*

	# 结算
	settlement_type		CHAR(1) NOT NULL,									# 结算类型 SPU_SETTLEMENT_TYPE_*

	# 时间相关
	active_time			DATETIME,											# 上架时间
	time				DATETIME NOT NULL,									# 录入时间
	update_time			DATETIME											# 更新时间
)ENGINE=INNODB;

CREATE TABLE spu_exts(
	id					INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	spu_id				INT UNSIGNED NOT NULL,								# spus.id
	detail				TEXT NOT NULL,										# 商品详情
	cover_video_url		VARCHAR(255),										# 封面视频url
	out_video_id		VARCHAR(255),										# 外部视频id
	video_duration		FLOAT(10,2)											# 视频时长
)ENGINE=INNODB;

ALTER TABLE spu_exts ADD INDEX idx_spuid(spu_id);

CREATE TABLE skus(
	id				INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	spu_id			INT UNSIGNED NOT NULL,									# spus.id
	sku_sn			VARCHAR(32) NOT NULL,									# sku编码
	name			varchar(255) NOT NULL,									# sku 名称
	code			VARCHAR(255),											# 商品编码
	barcode			VARCHAR(255),											# 商品条形码

	picture_url		VARCHAR(255) NOT NULL,									# 商品图片

	cost_price		BIGINT UNSIGNED NOT NULL,								# 成本价
	sale_price		BIGINT UNSIGNED NOT NULL,								# 售价

	weight			INT UNSIGNED NOT NULL DEFAULT 0,						# 净重 g为单位

	delivery_type	TINYINT UNSIGNED NOT NULL,								# 发货方式 DELIVERY_TYPE_*

	time			DATETIME NOT NULL,										# 创建时间
	update_time		DATETIME												# 更新时间
)ENGINE=INNODB;

ALTER TABLE skus ADD INDEX idx_spuid(spu_id);


CREATE TABLE attrs(
	id				INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,		#
	name			VARCHAR(255) NOT NULL,									# 属性名
	merchant_id		INT UNSIGNED NOT NULL,									# 商户id
	time			DATETIME NOT NULL,										# 创建时间
	update_time		DATETIME												# 更新时间
)ENGINE=INNODB;

ALTER TABLE attrs ADD INDEX idx_merchantid(merchant_id);

CREATE TABLE attr_values(
	id			INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,			#
	name		VARCHAR(255) NOT NULL,										# 属性值
	attr_id		INT UNSIGNED NOT NULL,										# attrs.id
	time		DATETIME NOT NULL,											# 创建时间
	update_time	DATETIME													# 更新时间
)ENGINE=INNODB;

ALTER TABLE attr_values ADD INDEX idx_attr_id(attr_id);

CREATE TABLE brands(
	id			INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	name		VARCHAR(255) NOT NULL,										# 品牌名称
	logo_url	VARCHAR(255) NOT NULL,										# 品牌logo
	time		DATETIME NOT NULL,											# 创建时间
	update_time	DATETIME													# 更新时间
)ENGINE=INNODB;

# 库存表
CREATE TABLE stocks(
	id				INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,		#
	sku_id			INT UNSIGNED NOT NULL,									# skus.id
	sku_sn			VARCHAR(32) NOT NULL,									# skus.sku_sn
	available_stock	INT UNSIGNED NOT NULL,									# 可用库存
	frozen_stock	INT UNSIGNED NOT NULL,									# 占用库存 / 冻结库存
	time			DATETIME NOT NULL,										# 创建时间
	update_time		DATETIME												# 更新时间
)ENGINE=INNODB;

ALTER TABLE stocks ADD INDEX idx_sku_id(sku_id);

CREATE TABLE stock_logs(
	id				INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	stock_id		INT NOT NULL,
	op			CHAR(2) NOT NULL,											# 操作 ORDER_OP_*
	available_stock	INT UNSIGNED NOT NULL,									# 可用库存
	frozen_stock	INT UNSIGNED NOT NULL,									# 占用库存
	addtional		TEXT,													# 额外附加信息
	time			DATETIME NOT NULL										# 创建时间
)ENGINE=INNODB;

ALTER TABLE stock_logs ADD INDEX idx_stock_id(stock_id);


CREATE TABLE sms_templates(
	id			INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	name		VARCHAR(32) NOT NULL,										# 模版名称
	description VARCHAR(255) NOT NULL,										# 模版描述
	content		VARCHAR(255) NOT NULL,										# 模版内容
	status		CHAR(1) NOT NULL,											# 状态 SMS_TEMPLATE_STATUS_*
	time		DATETIME NOT NULL,											# 创建时间
	update_time DATETIME													# 更新时间
)ENGINE=INNODB;

CREATE TABLE sms_records(
	id			INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	mobile		INT UNSIGNED,												# 手机号
	content		VARCHAR(255) NOT NULL,										# 短信内容
	status		TINYINT UNSIGNED NOT NULL,									# SMS_RECORD_STATUS_*
	time		DATETIME NOT NULL											# 创建时间
);

# 普通用户成长为推广员
CREATE TABLE users(
	id						INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,

	# 基础信息
	username				VARCHAR(32) NOT NULL,		# 用户名
	password				VARCHAR(64) NOT NULL,		# 密码
	mobile					CHAR(11),					# 手机号
	avatar					VARCHAR(255),				# 头像
	gender					TINYINT UNSIGNED,			# 性别

	# token
	reset_password_token	INT UNSIGNED,				# token

	# 登录相关
	signin_count			INT UNSIGNED DEFAULT 0,		# 登录次数
	last_signin_time		DATETIME,					# 上次登录时间
	last_signin_ip			CHAR(15),					# 上次登录IP

	status					CHAR(1) NOT NULL,			# 用户状态

	# 时间相关
	time DATETIME NOT NULL,
	update_time DATETIME
)ENGINE=INNODB;

CREATE TABLE addresses(
	id				INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	user_id			INT UNSIGNED NOT NULL,								# users.id
	province_id		INT UNSIGNED NOT NULL,								# 省份ID
	priovince_name	VARCHAR(255),										# 省份名称
	city_id			INT UNSIGNED NOT NULL,								# 城市ID
	city_name		VARCHAR(255),										# 城市名称
	district_id		INT UNSIGNED NOT NULL,								# 区ID
	district_name	VARCHAR(255),										# 区名称
	address			VARCHAR(255) NOT NULL,								# 详细地址
	mobile			CHAR(11) NOT NULL,									# 手机号码
	consignee		VARCHAR(16) NOT NULL,								# 收货人
	is_default		TINYINT UNSIGNED,									# 是否默认
	time			DATETIME NOT NULL,									# 创建时间
	update_time		DATETIME											# 更新时间
)ENGINE=INNODB;


CREATE TABLE categories(
	id			INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	name		VARCHAR(255) NOT NULL,								# 分类名称
	icon_url	VARCHAR(255),										# 图片地址
	parent_id	INT UNSIGNED NOT NULL,								# 父级分类id 值为0代表顶级分类
	time		DATETIME,											# 创建时间
	update_time	DATETIME
)ENGINE=INNODB;

CREATE TABLE orders(
	id				INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,

	merchant_id		INT UNSIGNED NOT NULL,								# 商家ID

	# 基础信息
	order_sn		VARCHAR(60) NOT NULL,								# 订单号
	status			TINYINT UNSIGNED NOT NULL,							# 订单状态 ORDER_STATUS_*
	user_id			INT UNSIGNED NOT NULL,								# users.id

	# 金额
	skus_amount		INT UNSIGNED NOT NULL,								# 购买商品总金额
	shipping_fee	INT UNSIGNED NOT NULL,								# 运费 单位 分
	coupon_amount	INT UNSIGNED NOT NULL,								# 优惠金额 单位 分
	order_amount	INT UNSIGNED NOT NULL,								# 订单总金额 单位 分

	source			CHAR(10),											# 订单来源 ORDER_SOURCE_*
	pay_channel		CHAR(10),											# 支付通道 PAY_CHANNEL_*
	pay_status		CHAR(1),											# 支付状态 PAY_STATUS_*

	paid_time		DATETIME,											# 付款时间

	confirm_time	DATETIME,											# 确认收获时间
	note			VARCHAR(255),										# 备注

	buyer_message	TEXT,												# 买家留言

	# 结算
	settlement_type	CHAR(1) NOT NULL,									# 结算口径

	time DATETIME NOT NULL												# 订单创建时间
)ENGINE=INNODB;

ALTER TABLE orders ADD INDEX idx_user_id(user_id);


CREATE TABLE order_addresses(
	id				INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	order_id		INT UNSIGNED NOT NULL,							# orders.id
	province_id		INT UNSIGNED NOT NULL,							# 省份ID
	priovince_name	VARCHAR(50),									# 省份名称
	city_id			INT UNSIGNED NOT NULL,							# 城市ID
	city_name		VARCHAR(50),									# 城市名称
	district_id		INT UNSIGNED NOT NULL,							# 区ID
	district_name	VARCHAR(50),									# 区名称
	address			VARCHAR(255) NOT NULL,							# 详细地址
	time DATETIME NOT NULL
)ENGINE=INNODB;

ALTER TABLE order_addresses ADD INDEX idx_order_id(order_id);

# 订单快照
CREATE TABLE order_snapshots(
	id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	order_id INT UNSIGNED NOT NULL
)ENGINE=INNODB;


CREATE TABLE order_logs(
	id				INT UNSIGNED PRIMARY KEY NOT NULL,		#
	context_id		INT UNSIGNED NOT NULL,							# 上下文ID

	order_id		INT UNSIGNED NOT NULL,							# orders.id
	order_sn		VARCHAR(255) NOT NULL,							# orders.order_sn
	order_status 	TINYINT UNSIGNED NOT NULL,						# 操作后的订单状态

	op				CHAR(2) NOT NULL,								# 操作
	time DATETIME													# 创建时间
)ENGINE=INNODB;


CREATE TABLE order_skus(
	id 	INT UNSIGNED PRIMARY KEY NOT NULL,
	order_id	INT UNSIGNED NOT NULL,								# orders.id
	sku_id		INT UNSIGNED NOT NULL,								# skus.id
	spu_id		INT UNSIGNED NOT NULL								# spus.id
)ENGINE=INNODB;


# 支付单表
CREATE TABLE payments(
	id				INT UNSIGNED PRIMARY KEY NOT NULL,
	out_trade_no	VARCHAR(255) NOT NULL,							# 外部交易流水号
	escrow_trade_no	VARCHAR(255),									# 第三方支付流水号
	channel			TINYINT UNSIGNED NOT NULL,						# 交易通道
	pay_amount		INT UNSIGNED NOT NULL,							# 支付金额
	pay_status		TINYINT UNSIGNED NOT NULL						# 支付状态
)ENGINE=INNODB;

# 支付单号-订单对应表
CREATE TABLE payment_to_orders(
	payment_id INT UNSIGNED NOT NULL,								# payments.id
	order_id INT UNSIGNED NOT NULL									# orders.id
);

ALTER TABLE payment_to_orders ADD INDEX order_payment(order_id, payment_id);

CREATE TABLE spu_collections(
	id			INT UNSIGNED PRIMARY KEY NOT NULL,					#
	user_id		INT UNSIGNED NOT NULL,								# 用户ID
	spu_id		INT UNSIGNED NOT NULL								# 商品ID
)ENGINE=INNODB;

ALTER TABLE spu_collections ADD INDEX idx_user_spu(user_id, spu_id);

CREATE TABLE packages(
	id				INT UNSIGNED PRIMARY KEY NOT NULL,
	package_sn		VARCHAR(255) NOT NULL,							# 包裹编号

	merchant_id		INT UNSIGNED NOT NULL,							# 商户ID
	order_id		INT UNSIGNED NOT NULL,							# 订单号
	order_sn		VARCHAR(255) NOT NULL,							# 订单编码


	shipping_code 	VARCHAR(10),									# 快递公司编码
	shipping_name	VARCHAR(32),									# 快递公司名称
	shipping_status TINYINT UNSIGNED NOT NULL,						# 快递状态

	delivered_time	DATETIME,										# 发货时间
	delivered_canceled_time DATETIME,								# 物流取消时间

	consignee		VARCHAR(16) NOT NULL,							# 收货人
	mobile			CHAR(11) NOT NULL,								# 手机号

	# 物流实时信息
	logistics_info	TEXT,											# 物流信息

	# 省市区 方便日后数据统计
	province_id		INT UNSIGNED NOT NULL,
	province_name	VARCHAR(50) NOT NULL,							# 省份
	city_id			INT UNSIGNED NOT NULL,
	city_name		VARCHAR(50) NOT NULL,							# 市
	district_id		INT UNSIGNED NOT NULL,
	district_name	VARCHAR(50) NOT NULL,							# 区

	address	VARCHAR(255) NOT NULL,									# 详细地址


	note VARCHAR(255),												# 备注

	time DATETIME NOT NULL,											# 创建时间
	update_time DATETIME											# 更新时间
)ENGINE=INNODB;

CREATE TABLE admins(
	id				INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	admin_name		VARCHAR(32) NOT NULL,							# 登录名
	password		VARCHAR(255) NOT NULL,							# 密码
	display_name	VARCHAR(16),									# 显示名称 如 张三
	status			CHAR(1) NOT NULL,								# 状态
	api_token		VARCHAR(255),									# token
	time			DATETIME NOT NULL								# 创建时间
)ENGINE=INNODB;

CREATE TABLE admin_roles(
	id			INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	name		VARCHAR(16) NOT NULL,								# 角色名称
	descipriton	VARCHAR(255) NOT NULL,								# 角色描述
	time DATETIME NOT NULL
)ENGINE=INNODB;

CREATE TABLE admin_to_roles(
	id			INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
	admin_id	INT UNSIGNED NOT NULL,
	role_id		INT UNSIGNED NOT NULL
)ENGINE=InnoDB;

CREATE TABLE admin_privileges(
	id			INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	method		CHAR(10) NOT NULL,									# 请求方式
	uri			CHAR(255) NOT NULL,									# URI
	name		VARCHAR(16) NOT NULL,								# 权限名称
	description VARCHAR(255) NOT NULL,								# 权限描述
	time 		DATETIME NOT NULL,									# 创建时间
	update_time DATETIME											# 更新时间
)ENGINE=INNODB;

CREATE TABLE admin_role_to_privileges(
	id				INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	role_id			INT UNSIGNED NOT NULL,								# 角色ID
	privilege_id	INT UNSIGNED NOT NULL								# 权限ID
)ENGINE=INNODB;


CREATE TABLE admin_logs(
	id			INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
	admin_id	INT UNSIGNED NOT NULL,								# 管理员ID
	op			CHAR(2) NOT NULL,									# 操作
	context_id	INT UNSIGNED,										# 上下文ID
	additional	TEXT,												# 日志内容
	time DATETIME NOT NULL											# 创建时间
)ENGINE=INNODB;

# 文件上传表
CREATE TABLE file_uploads(
	id			INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	merchant_id	INT UNSIGNED,										# 商户号 方便统计
	filename	VARCHAR(255) NOT NULL,								# 文件名称
	type		CHAR(2) NOT NULL,									# 文件类型 FILE_UPLOAD_TYPE_*
	error_code	INT,												# 错误码
	time		DATETIME
)ENGINE=INNODB;

lumen redis server went away

卢哥阅读(84)

今天新起了一个电商项目,花了半天时间设计完成了所有的数据表结构,选了lumen作为快速开发框架,主要是用lumen的路由以及lumen对数据库和redis的开箱即用,未使用orm以及lumen其他任何的核心功能,因为个人觉得把php写的太复杂了,php就是简单的面向过程式编程coding出来的代码才完美、优秀、可维护性也很高。

然后做用户token保存时用到了redis,发生了如下错误

[RedisException] Redis server went away

google了一下,基本的答案就是composer 安装如下2个库

composer require predis/predis
 composer require illuminate/redis

predis已经被作者遗弃多年,国内很多php开发者图省事却还在使用

这里我并未采用网上绝大部分的随大流解决方案

而是在lumen中单例出了一个原生的redis对象,并交给lumen容器进行管理redis

bootstrap/app.php 中添加如下代码即可

$app->singleton('redis', function(){
	$redis = new \Redis;
	$redis->pconnect(config('database.redis.default.host'), config('database.redis.default.port'));
	return $redis;
});
调用的话就用
app('redis')->set('key', 'value');

git config && git alias(pretty)

卢哥阅读(71)

自己常用的git global配置以及alias、git log美化

[push]
    default = current
[user]
    email = luyunhua1987@gmail.com
    name = luyunhua
[alias]
    co = checkout
    ci = commit
    br = branch
    st = status
    lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
[credential]
    helper = store