# 注冊 User/reg

注冊頁的地址是 user/reg。
然后模板就是一個表單
~~~
<extend name="Index/base" />
<block name="header"></block>
<block name="main">
<form class="form-signin" action="{:U('/user/reg')}" method="post">
<h2 class="form-signin-heading">注冊</h2>
<label for="inputNickname" class="sr-only">用戶名</label>
<input type="text" id="inputNickname" class="form-control hide-data" placeholder="用戶名" required="" autofocus="" name="nickname">
<label for="inputPassword" class="sr-only">密碼</label>
<input type="password" id="inputPassword" class="form-control hide-data" placeholder="密碼" required="" name="pwd">
<button class="btn btn-lg btn-primary ajax-post" type="submit" target-form="form-signin">注冊</button>
<a href="{:U('/user/login')}" class="btn btn-text">有賬號了?點我去登錄</a>
</form>
</block>
<block name="sidebar"></block>
~~~
至于提交表單的ajax,前面已經說過了,common.js里 ajax-post
由于注冊和登錄邏輯里面有特殊session處理,干脆就沒有用rest。rest預留著給后臺這種只可能批量添加用戶數據,而不需要登錄邏輯處理的使用。
//注冊
~~~
public function reg(){
if(IS_POST){ //注冊用戶
$Member = D('Member');
$nickname = I('post.nickname');
$pwd = I('post.pwd');
$data = $Member->create(array('nickname'=>$nickname, 'pwd'=>$pwd));
if($data){
$Member->startTrans();
if($Member->add()){
if($Member->login($uid, $nickname)){
$Member->commit();
$this->success('注冊成功',U('/user/login'));
} else {
$Member->rollback();
$this->error($Member->getError());
}
}else{
$Member->rollback();
$this->error($Member->getError());
}
}else{
$this->error($Member->getError());
}
} else { //顯示注冊表單
$this->display();
}
}
~~~
注意的幾點:
1. 一個方法里通過IS_POST判斷是否是提交數據還是頁面顯示
2. 使用了事務(數據表必須是支持事務的數據引擎,mysql的是innodb)
3. 插入數據前用模型驗證
4. 注冊完畢后自動登錄(可以選擇不自動登錄)
## 注冊驗證和登錄
~~~
protected $_validate = array(
array('nickname','','帳號名稱已經存在!',0,'unique',self::MODEL_INSERT), // 在新增的時候驗證name字段是否唯一
);
protected $_auto = array (
array('status','1'), // 新增的時候把status字段設置為1
array('settings', '{}'),
array('pwd','password',1,'function') , // 對password字段在新增的時候使password函數處理
array('create_at','datetime',self::MODEL_INSERT,'function'), // 對create_at字段在更新的時候寫入當前時間戳
array('update_at','datetime',self::MODEL_BOTH,'function'), // 對create_time字段在更新的時候寫入當前時間戳
);
~~~
自動驗證和自動完成:
注冊時需要驗證賬號是否被注冊過
完成里序列化字段setting的初始化。密碼字段pwd的加密處理。以及時間字段的自動完成。
PS:自動完成和自動驗證里的時間參數最好用self::MODEL_INSERT 和self::MODEL_BOTH 及self::MODEL_UPDATE 這幾個類靜態常量,這樣不用在0、1、2中記混了。
# 登錄 User/login

~~~
public function login(){
if(IS_POST){ //登錄驗證
$Member = D('Member');
$nickname = I('post.nickname');
$pwd = I('post.pwd');
$uid = $Member->checkLogin($nickname, $pwd);
if(0 < $uid){
//登錄用戶
if($Member->login($uid, $nickname)){
$this->success('登錄成功!',U('/mine'));
} else {
$this->error($Member->getError());
}
} else { //登錄失敗
switch($uid) {
case -1: $error = '用戶不存在或被禁用!'; break; //系統級別禁用
case -2: $error = '密碼錯誤!'; break;
default: $error = '未知錯誤!'; break; // 0-接口參數錯誤(調試階段使用)
}
$this->error($error);
}
} else { //顯示登錄表單
$this->display();
}
}
~~~
登錄邏輯也很簡單,我們直接看POST部分,checkLogin用于檢測用戶是否存在以及密碼是否對。正確后然后執行Mmember模型的login方法并跳轉個人空間。
MemberModel里的checkLogin
~~~
public function checkLogin($nickname, $pwd){
$member = $this->where("nickname = '{$nickname}'")->find();
if($member){
if(password($pwd) == $member['pwd']){
return $member['id'];
}else{
return -2;
}
}else{
return -1;
}
}
~~~
Member里的login方法
~~~
public function login($uid, $nickname){
$array = array(
'uid' =>$uid,
'nickname'=>$nickname
);
try {
session('user', $array);
return true;
} catch (Exception $e) {
$this->error = '未知錯誤';
return false;
}
}
~~~
其實登錄就是保存一個session到服務器里,然后用到登錄的地方用于獲取用戶id和賬號。
密碼相關函數:
~~~
//密碼加密
function password($password){
$md5str=md5($password);
$salt=get_password_salt($md5str);
return hash('sha256',$md5str.$salt);
}
function get_password_salt($md5str,$d=1001){
$crc32_value = floatval(sprintf("%u", crc32($md5str)));
$crc32_value = ($crc32_value > PHP_INT_MAX) ?
(($crc32_value - PHP_INT_MAX ) % $d + PHP_INT_MAX % $d) % $d : $crc32_value % $d;
return $crc32_value;
}
~~~
高級應用:
- session 設置前綴和過期時間
- cookie 自動登錄
- [session存入數據庫持久化](http://www.jb51.net/article/52557.htm)
- 序
- 前言
- 內容簡介
- 目錄
- 基礎知識
- 起步
- 控制器
- 模型
- 模板
- 命名空間
- 進階知識
- 路由
- 配置
- 緩存
- 權限
- 擴展
- 國際化
- 安全
- 單元測試
- 拿來主義
- 調試方法
- 調試的步驟
- 調試工具
- 顯示trace信息
- 開啟調試和關閉調試的區別
- netbeans+xdebug
- Socketlog
- PHP常見錯誤
- 小黃鴨調試法,每個程序員都要知道的
- 應用場景
- 第三方登錄
- 圖片處理
- 博客
- SAE
- REST實踐
- Cli
- ajax分頁
- barcode條形碼
- excel
- 發郵件
- 漢字轉全拼和首字母,支持帶聲調
- 中文分詞
- 瀏覽器useragent解析
- freelog項目實戰
- 需求分析
- 數據庫設計
- 編碼實踐
- 前端實現
- rest接口
- 文章發布
- 文件上傳
- 視頻播放
- 音樂播放
- 圖片幻燈片展示
- 注冊和登錄
- 個人資料更新
- 第三方登錄的使用
- 后臺
- 微信的開發
- 首頁及個人主頁
- 列表
- 歸檔
- 搜索
- 分頁
- 總結經驗
- 自我提升
- 進行小項目的鍛煉
- 對現有輪子的重構和移植
- 寫技術博客
- 制作視頻教程
- 學習PHP的知識和新特性
- 和同行直接溝通、交流
- 學好英語,走向國際
- 如何參與
- 瀏覽官網和極思維還有看云
- 回答ThinkPHP新手的問題
- 嘗試發現ThinkPHP的bug,告訴官方人員或者push request
- 開發能提高效率的ThinkPHP工具
- 嘗試翻譯官方文檔
- 幫新手入門
- 創造基于ThinkPHP的產品,進行連帶推廣
- 展望未來
- OneThink
- ThinkPHP4
- 附錄