万水千山总是情,给个鼓励行不行?!呱呱呱呱
首先,能进入公司本来就是一件特别幸福的事。更有幸能在一周后就跟着龙哥开始我第一个完整项目,第一个像自己培育的小树苗一样看着它慢慢枝繁叶茂,终成苍翠(我们的树叫苹果树梨树李子树686)。
努力培育树苗的这一个月左右的时光中,更还能幸得像奶孩子一样奶着我的良师益友的龙哥(我能不能说说龙哥,不,必须要说),日常互怼的小鑫,帅炸天的小勇勇,大胸的剑鑫,还有吊炸天的F4,文字这么苍白,上个图添添色彩
这个色彩怎么样
还有行姿优雅声音又好听的文总,让时光不再有孤独,工作不会寂寥。
以前都是对着已经长成的树浇水,第一次播种子,真的学到更多的“培植”技巧(我们真是在认真种树)。
Done & Get:
1、谈谈数据表:视野要开放,把控全局,展望未来
设计自己数据表慢慢的在业务的进程中就发现自己开始想的有多理想化和年轻哦。比如:1.在用户表一开始就局限在用户用数字账号登录,所以就一直没有想着给有用户名这个字段,可是,想嘛,正常的登录不该都是用户名嘛
这个就是最后的用户表
CREATE TABLE `wa_member` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '会员自增ID',
`vip_number` int(11) NOT NULL COMMENT '会员卡号',
`username` char(5) NOT NULL COMMENT '用户名',
`parent_id` int(10) NOT NULL DEFAULT '1' COMMENT '直推会员id',
`register_member_id` int(11) NOT NULL COMMENT '注册会员的meber_id',
`name` varchar(255) NOT NULL DEFAULT '' COMMENT '用户姓名',
`password` varchar(255) NOT NULL DEFAULT '' COMMENT '会员密码',
`mobile` varchar(255) NOT NULL DEFAULT '' COMMENT '电话',
`deposit_bank` varchar(255) NOT NULL DEFAULT '' COMMENT '开户行',
`bank_account` varchar(255) NOT NULL DEFAULT '' COMMENT '银行账号',
`address` varchar(255) NOT NULL DEFAULT '' COMMENT '地址',
`last_login_ip` varchar(36) DEFAULT NULL COMMENT '最后登录ip',
`last_login_time` int(10) NOT NULL DEFAULT '0' COMMENT '最后登录时间',
`status` int(10) NOT NULL DEFAULT '1' COMMENT '状态 0:被冻结 1:正常 2:已退网',
`created_at` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间 注册时间 入网时间',
`updated_at` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间 退网时间',
`a_coin` int(11) NOT NULL COMMENT '金果数',
`b_coin` int(11) NOT NULL COMMENT '金种子数',
`child_num` int(11) NOT NULL COMMENT '直推数量',
`out_status` int(10) NOT NULL DEFAULT '0' COMMENT '是否可以退网 0:否 1:是',
PRIMARY KEY (`id`),
UNIQUE KEY `index_unique_vip_number` (`vip_number`),
UNIQUE KEY `index_unique_username` (`username`),
KEY `index_parent_id` (`parent_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='会员信息表';
2.在做用于数据统计记录的表bonus的时候,字段开始是没有问题,但在类型上开始对未来用到的类型就想的不是很全面,一直type到了11种,其实应该把这个字段单独做成一个表做关联是更好的 3.在很多相关信的数据表中,为了更好的把之前的初始记录做更好更简洁的记录可以新建一个字段,以类似json这种将数据打包存放。
这个是类型,是不是很累形?
`type` int(11) NOT NULL DEFAULT '0' COMMENT '获得类型 1:绩效 2:分享 3:额外分享 4:提现 5:注册奖金 6:充值 7:扣除 8:赠送 9:提现返回 10:注册扣除 11:获赠',
这个是数据处理和记录的样子
'ext_data' => json_encode($ext_data, JSON_UNESCAPED_UNICODE)
return Helper::saveBonusLog($member->id, $this->type, 7, $this->num, 0, ['note'=> '后台扣除','relation'=>'wenzz']);
2、说说代码吧:代码规范从我做起。学会优雅,赏心悦目。学会优化学会简洁。
从会员信息管理,开始熟悉yii的actionform和load,开始使用yii牛逼的过滤器,使用gii更快捷的生成初始的代码等等。但龙哥一开始就和和蔼的甩我一句:逻辑性的东西啊,尽量不要给控制器里写。一开始还不太懂龙哥这话的意思,但在后来,我看到一个个整洁的控制器和一个个被调度的model才越来越感觉到每个框架所吹捧的优雅是个什么意思,越来越懂得代码规范所带来的那种赏心悦目的.php。因为一开始写的会员信息那块,在修改信息那里因为从在hash密码的存入,因为对框架的不熟练和hash的陌生,看源码看方法,然后就写了很多冗余和画蛇添足的步骤和代码。在最后收尾回头看的时候,我自己都想对自己说龙哥经常说的:low。哈哈哈哈。所以,挊了它。
这是我写的控制器里最长的代码
public function actionUpdate($id)
{
$model = MemberForm::findOne($id);
if ($model->load(Yii::$app->request->post()) && $model->updateMember($id, Yii::$app->request->post())) {
Yii::$app->session->setFlash('success', '修改成功');
return $this->redirect(['index']);
}
return $this->render('update', [
'model' => $model,
]);
}
这就是在model中做更多的逻辑处理,在回顾或者纠错的时候其实你会很明白去哪里修改,因为逻辑都在这里啊,所以不要在控制器里写全部写在这里将会使你有一个愉快的开始和美丽的结束
public function login($username, $password)
{
if(empty($username) || empty($password)){
$this->addError('message', '账号或者密码不能为空');
return false;
}
$detail = Member::findOne(['username'=>$username]);
$query = new Query();
$member = $query
->from(Member::tableName())
->where(['username'=>$username])
->one();
if(!isset($detail) || !Member::validatePassword($password,$detail->password)){
$this->addError('message', '账号或密码错误');
return false;
}
if($member['status'] != 1){
$this->addError('message', '请联系管理员');
return false;
}
$detail->last_login_time = time();
$detail->last_login_ip = Yii::$app->request->getUserIP();
$detail->save(false);
// session 保存用户登录数据
Yii::$app->session->set('member',['member_id'=>$member['id'],'member_name'=>$member['name'], 'vip_number'=>$member['vip_number'], 'username' => $member['username']]);
return true;
}
3、说说成就感:谁知屏中码,行行皆辛苦。
每每做完一个模块(当然可能就是未来的一个坑,比如修改我就给自己埋了个坑~),但都会有和开始懵懂进入php世界时候的那种没完成一个有效输出时候的激情感。每每从龙哥那里获取到真实可剽窃的更为简洁优化的function,
比如更加美观的上传
public function upload($params)
{
$type = $params['type'];
switch ($type) {
case 'goods':
return $this->uploadGoodsImgs($params);
break;
case 'fruiter':
return $this->uploadFruiterImgs($params);
break;
}
}
从身边优秀的人身上学习优秀的东西,我和庆幸身边有优秀的你们值得我去模仿学习并创新
而且自己应用成功的时候,总也还可以无耻的窃喜。每每学到yii更多的新功能块新插件也可以愉快的舒口气去开心的拉个粑粑。慢慢的在工作中忘记时间,沉浸在脑洞中无法自拔。在做到查询用户区数量和用户挂靠数的时候,遇到了职业生涯第一难点(这个生涯是不是太短啦,尴尬一笑,毫不羞耻)试过很多循环,最后都失败告终,某一个灵机一动,搞个递归吧,因为开始模拟的数据还少,竟然查询成功了,多么激动的时刻,而且龙哥第一次没有鄙视我,说666,我二话没说,拿起纸就去厕所愉悦了(当然,不是去挊,是放松,不要开车,严肃严肃)。
public function group($id, $num =0)
{
$query = (new \yii\db\Query());
$district = $query->select('district')->from(District::tableName())->where(['member_id' => $id, 'seat' => 1])->one();
$query = (new \yii\db\Query());
$data = $query->select('member_id')->from(District::tableName())->where(['district' => $district['district']])->all();
if (count($data) >= 40) {
$num++ ;
$data = array_splice($data,1);
foreach ($data as $v) {
$num = $this->group($v['member_id'], $num);
}
}
return $num;
}
最后还是流产了
我们欣赏一下龙哥的处理
public static function addMemberNode($member_id)
{
//先根据Member_id 找到对应的上级id
$parent_district = District::findOne(['member_id'=>$member_id, 'seat'=>[2,3,4]])->district;
$parent_id = District::findOne(['district'=>$parent_district, 'seat'=>1])->member_id;
$model = new MemberNode();
$model->member_id = $member_id;
$model->above_member_id = $parent_id;
if(!$model->save()){
return false;
}
//获取上级的所有,并继承过来
$parentMemberNode = MemberNode::find()->select( 'above_member_id')->where(['member_id'=>$parent_id])->orderBy(['id'=>SORT_ASC])->asArray()->all();
if(isset($parentMemberNode) && count($parentMemberNode)){
foreach($parentMemberNode as &$val){
$val[] = $member_id;
}
$result = Yii::$app->db->createCommand()->batchInsert(MemberNode::tableName(), ['above_member_id', 'member_id'], $parentMemberNode)->execute();
if(!$result){
return false;
}
}
return true;
}
/**
* 获取会员的挂靠区数
* @param $member_id
* @return mixed
*/
public static function getMemberUnderDistrict($member_id)
{
$underDistrict = Yii::$app->cache->get('under_district');
if(empty($underDistrict) || !isset($underDistrict[$member_id])){
$member_under_ids = MemberNode::find()->select('member_id')->where(['above_member_id'=>$member_id])->asArray()->column();
if(isset($member_id) && count($member_under_ids)){
//获取区数量
$underDistrict[$member_id] = District::find()->where(['member_id'=>$member_under_ids, 'seat'=>40])->count();
}else{
$underDistrict[$member_id] = 0;
}
Yii::$app->cache->set('under_district', $underDistrict);
}
return ArrayHelper::getValue($underDistrict, $member_id, 0);
}
/**
* 清楚缓存
* @return bool
*/
public static function cleanMemberCache()
{
Yii::$app->cache->delete('under_num');
Yii::$app->cache->delete('under_district');
return true;
}
后来模拟数据的过程中又从龙哥那里学会了自动脚本,ajax模拟器等更为实用的代码小工具,甚是愉悦,但第二天就悲剧了,因为数据量大的时候,首先问题是查询语句有问题,请教过双哥,完美解决,但更为爆炸的时候数据过千的时候数据库崩掉了,插询的太过深,受不了了。最后这个是龙哥在我奢华的外卖中脑洞出来的,貌似已经完美收官(替龙哥鼓掌,接下来我会剽窃一波龙哥的成果),但故事是从我这里美好的开始的啊,我骄傲。还有很多很多,留着我们下回分解。
4、最后的最后,再容我说一句
不吹不黑, ∑!帅呆了。感谢各位的相伴同行和提携和指点。感谢各位的颜值和才华,已经深深被你们感染到了。谢谢大家。爱你们,么么哒
2017.06.24
小胖