這一篇將會來介紹 ThinkPHP 中的驗證碼功能,本身 ThinkPHP 就有提供驗證碼功能,如果沒有特別的需求的話,使用 ThinkPHP 本身內建驗證碼功能是滿足夠使用的。
由於 ThinkPHP 驗證碼這區塊是屬於擴展包,所以如果要在 ThinkPHP 中使用驗證碼功能,必須先透過 Composer 安裝 think-captcha
,那麼我們打開 cmd 後移動到專案目錄輸入以下指令:
composer require topthink/think-captcha=2.0.*
使用驗證碼的方式非常簡單,有兩種寫法可以使用,只需要在 HTML 模板裡面寫入就可以顯示驗證碼。
第一種寫法,透過 ThinkPHP 生成:
<div>
<div>{:captcha_img()}</div>
<input type="text" name="captcha" id="captcha" class="form-control" placeholder="captcha">
</div>
另一種則是使用 img
標籤的寫法,我個人推薦使用這個做法,因為這會攸關後面所講的東西:
<div>
<div><img src="{:captcha_src()}" alt="captcha" /></div>
<input type="text" name="captcha" id="captcha" class="form-control" placeholder="captcha">
</div>
這樣子我們就可以在前端畫面上看到驗證碼囉 ↓
另外接下來還有一個動作要做,當使用者若沒有填入驗證碼或是驗證碼輸入錯誤時,我們必須要提示錯誤訊息給使用者,所以這邊就要搭配表單驗證的功能,我們打開表單驗證的 validate/User.php
,加入 captcha
驗證 & 錯誤提示訊息:
protected $rule = [
'captcha'=>'require|captcha'
];
protected $message = [
'captcha.require'=>'驗證碼必填',
'captcha.captcha'=>'驗證碼輸入錯誤',
];
這樣子就可以達到驗證碼錯誤訊息提示的效果了,當然這邊就讓我們實際測試送看看,首先是空白的驗證碼會發生何事 ↓
那如果我故意輸入的驗證碼呢?將會導致什麼錯誤訊息? ↓
另外你也可以自定義驗證碼,例如驗證碼變成中文驗證、驗證碼大小、模糊度等等,但是這邊我就不多作介紹,詳細可以看官方手冊 → 連結
由於 ThinkPHP 提供的驗證碼並沒有點擊驗證碼刷新的功能,所以我這邊就提供一下我的作法,由於我有測試過使用 {:captcha_img()}
來製作點擊驗證碼刷新,但是有可能會發生沒有反應的問題,所以我個人推薦使用 img
標籤的作法:
<div>
<div><img src="{:captcha_src()}" alt="captcha" id="captchaImg" style="cursor: pointer;" title="刷新驗證碼"/></div>
<input type="text" name="captcha" id="captcha" class="form-control" placeholder="captcha">
<span class="text-danger">{$Request.session.error.captcha}</span>
</div>
這樣使用者在滑鼠移過去點擊驗證碼圖片時就會顯示 刷新驗證碼 的字樣 ↓
接下來就是寫 JavaScript 來刷新驗證碼圖片,主要只需要重新賦予 captcha
驗證碼圖片路徑:
const captchaImg = document.getElementById('captchaImg');
captchaImg.addEventListener('click',(e) => {
e.preventDefault();
captchaImg.src = "/captcha";
})
這樣子就可以達到點擊驗證碼刷新囉~
最後提供一個超級簡化點擊驗證碼刷新縮寫版,只需要在 img
標籤再加入 onclick="this.src='{:captcha_src()}'"
即可搞定:
<div>
<div><img src="{:captcha_src()}" alt="captcha" id="captchaImg" style="cursor: pointer;" onclick="this.src='{:captcha_src()}'" title="刷新驗證碼"/></div>
<input type="text" name="captcha" id="captcha" class="form-control" placeholder="captcha">
<span class="text-danger">{$Request.session.error.captcha}</span>
</div>
如果希望可以每 60 秒就會自動刷新驗證碼,只需要使用 setInterval()
就可以達到這個需求,這邊也提供給各位參考:
const captchaImg = document.getElementById('captchaImg');
captchaImg.addEventListener('click',(e) => {
e.preventDefault();
captchaImg.src = "/captcha";
})
window.setInterval(() => {
captchaImg.src = "/captcha";
},60000)
我在製作驗證碼的時候,其實是使用 <div>{:captcha_img()}</div>
的做法,但是後來為了要能夠點擊驗證碼刷新驗證碼時,就發現怎麼不能動?後來改寫 <div><img src="{:captcha_src()}" alt="captcha" id="captchaImg" style="cursor: pointer;"/></div>
就可以搞定這個問題,我想應該是因為 JavaScript 被載入時 {:captcha_img()}
驗證碼還沒被渲染完畢,導致 JavaScript 抓不到進而無法控制驗證碼。
本文同步發表於:https://hsiangfeng.github.io/php/20190927/3311186145/