Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
天,有漁老師去現場為一位朋友解決一個網站注冊驗證的問題。問題是這樣的:在朋友的網站用郵箱注冊后,系統會發一封郵件到郵箱,然后點擊鏈接設置賬號的初始化密碼。如下圖所示:
但我點擊這個鏈接后,wordpress一直提示invalid key,也就是說key錯誤。因為是wordpress框架,從url的路由看,我就打開wp-login.php,然后查看其中的action rp。我直觀感覺,應該是get url中的key跟數據庫中的key值不相等導致的。所以,想進入系統的mysql一查究竟,但遺憾的是竟然沒有mysql權限,我也不知道他的網站是讓誰做的,估計是個外包吧。因為朋友是不懂技術的,很多事情問他也是一問三不知。沒辦法,哪就自己悶頭搞吧。
外事不決問google,內事不決問baidu。我習慣性地打開baidu,輸入:wordpress新用戶注冊 key無效。發現碰到類似問題的同行也不少,且看他們是如何解決的?他們的建議是:
編輯wp-includes文件夾中的pluggable.php文件,把變量$message里的>符合去掉。我照做了,發現還是不行的哦。所以,網上的東西,很多都得自己再實踐下,否則是要被坑的。但到這一步,我更加確信是key的值出問題了。然后我又仔細看了下郵件發送過來的鏈接,發現這個鏈接有個問題。
這個鏈接里的&是&被轉義后的值。那么,我在瀏覽器里輸入時把&替換成&會怎樣呢?發現竟然OK了,這時密碼重置成功了。這樣,問題就好辦了,理論上,我只要修改pluggable.php,把&替換成&就可以了。$message的變量賦值如下:
$message .= ‘<‘ . network_site_url(“wp-login.php?action=rp&key=$key&login=” . rawurlencode($user->user_login), ‘login’) . “>\r\n\r\n”;
但問題是,我用htmlspecialchars_decode($message)處理也不行,用str_replace("&","&",$message)處理也不行。也就是說,這個&替換不成&。
我再看這$message變量,rp后面的&怎么沒被轉義,而$key后面的&卻被轉義了。所以,到這一步,我就懷疑是不是語句的順序有問題?然后,我就把&key=$key放到($user->user_login)后面。然后,根據前面baidu的一些意見,順便把<和>符合也去掉。這樣,修改后的message如下:
$message .= network_site_url(“wp-login.php?action=rp&login=” . rawurlencode($user->user_login)."&key=$key", ‘login’) . “\r\n\r\n”;
問題就這樣解決了。
總結:1,出現問題,問baidu一般都能找到一些建議。但這些建議不一定完全正確,自己還得根據實際情況修改。2,html的一些特殊符號,在存數據庫之前需要被轉義,在取出數據庫后,需要被轉換回來,這也是一個很重要的知識點。
mybatis 的 xml 文件里寫的 sql 語句實際用的是一門叫做 OGNL 的表達式語言,OGNL 全稱 Object Graph Navigation Language 對象圖導航語言,是常應用于 Java 中的一個開源的表達式語言(Expression Language),它被集成在 Spring、Mybatis、Struts2 等 Java 框架中,通過簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現類型轉化等功能。
在書寫動態 SQL 時經常需要借助各種標簽,下面是一些在 mybatis 中常用的標簽:
if 標簽的 test 中常用判斷:
* 相等:==
* 不等:!=
* 條件或:or
* 條件與:and
* 條件非:!,也可以用 not
* 包含:in
* 不包含:not in
* 小于:<
* 小于等于:<=
* 大于:>
* 大于等于:>=
相當于 if、else if、else,間接實現了上面 if 標簽不支持的 else 效果
用于拼接 SQL 語句中的 where 子句,條件成立時才會加上 where 關鍵字,可以避免拼接出多余的and、or
<update id="updateUserInfo" parameterType="UserInfo">
update t_user_info
<set>
<if test="userName != null and userName != ''">
user_name = #{userName},
</if>
<if test="age != null">
age = #{age},
</if>
</set>
where user_id = #{userId}
</update>
可以間接實現 where 和 set 標簽一樣的功能
遍歷集合類數據,標簽屬性:
collection 接收的參數:
<!-- mapper -->
int insertUsers(List<User> users);
int updateUsers(List<User> users);
<!-- xml -->
<insert id="insertUsers">
insert into t_user (id, user_name, age) values
<foreach collection="list" separator="," item="user">
(#{user.user_id}, #{user.user_name}, #{user.age})
</foreach>
</insert>
<update id="updateUsers">
<foreach collection="list" separator=";" item="user">
update t_user
<set>
<if test="user.userName != null and user.userName != ''">
user_name= #{user.userName},
</if>
<if test="user.age != null">
age= #{user.age},
</if>
</set>
where user_id = #{user.userId}
</foreach>
</update>
<!-- mapper -->
List<User> selectUsers(@Param("userIds") String[] userIds);
<!-- xml -->
<select id="selectUsers" resultType="User">
select * from t_user where user_id in
<foreach collection="userIds" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
更多參數傳遞可以參考后面的 mybatis 參數章節。
可以在 sql 標簽里定義語句,然后在需要的地方用 include 標簽引入進去,可以實現代碼片段復用。
用于配合插入數據成功后返回的數據,一般用來返回 id 之類的。
主要有以下 5 種傳參方式:
xml 獲取的時候可以隨便寫,mybatis 會去自動處理,反正只有一個參數干脆就讓你寫啥都無所謂,不過推薦還是寫個有意義的形參:
<!-- mapper -->
User getUserByUsername(String userName);
<!-- xml -->
<select id="getUserByUsername" resultType="User">
select * from t_user where user_name = #{xxoo}
</select>
多個匿名參數的時候只能通過 mybatis 內置的 param1、param2 按傳參順序對應:
<!-- mapper -->
List<User> selectByuserNameAndAge(String userName, Integer age);
<!-- xml -->
<select id="selectByuserNameAndAge" resultMap="BaseResultMap" >
select * from t_user where user_name = #{param1} and age = #{param2}
</select>
具名參數需要用 @Param 注解來指定
<!-- mapper -->
List<User> selectByuserNameAndAge(@Param("name") String userName, @Param("age") Integer age);
<!-- xml -->
<select id="selectByuserNameAndAge" resultMap="BaseResultMap" >
select * from t_user where user_name = #{name} and age = #{age}
</select>
List 類型參數默認值 list,Array 類型參數默認值 array,注意 Set 類型的默認值并不是 set 而是 collection,除此之外的集合默認值也是 collection,當然我們也可以用 @Param 注解來自己指定
<!-- mapper -->
List<User> selectByAgeList(List ages);
<!-- xml -->
<select id="selectByList" resultMap="BaseResultMap" >
SELECT * from t_user where age in
<foreach collection="list" open="(" separator="," close=")" item="age">
#{age}
</foreach>
</select>
使用 Map 參數時,可以直接用鍵名引用
Map params = new HashMap<>();
params.put("userName", "周小黑");
params.put("age", 18);
List<User> result = userMapper.selectByMapParams(params);
<!-- mapper -->
List<User> selectByMapParams(Map params);
<!-- xml -->
<select id="selectByMapParams" resultMap="BaseResultMap" parameterType="map">
select * from t_user where user_name = #{userName} and age = #{age}
</select>
和上面的 Map 比較類似,不過這里的 parameterType 要指定為對應的 Bean 實體類型:
<!-- mapper -->
List<User> selectByBeans(User user);
<!-- xml -->
<select id="selectByBeans" resultMap="BaseResultMap" parameterType="User">
select * from t_user where user_name = #{userName} and age = #{age}
</select>
和上面的 Map、Bean 參數類似,一般是直接把前端傳遞過來的 json 參數直接傳入 Mapper 中進行查詢,parameterType 為 JSONObject
<!-- mapper -->
List<User> selectByJSON(JSONObject params);
<!-- xml -->
<select id="selectByJSON" resultMap="BaseResultMap" parameterType="com.alibaba.fastjson.JSONObject">
select * from t_user where user_name = #{userName} and age = #{age}
</select>
常見屬性設置:
XML 文件和我們常見的 HTML 類似,都是通過標簽來定義數據,而尖括號本身就是表示標簽符號的開始和結束,所以在 mybatis 的 xml 文件中相關符號最好用轉義符,尤其小于符號 "<",這樣可以避免解析時報錯,常用轉義符:
字符名稱 sql符號 轉義字符
大于號 > >
小于號 < <
大于等于號 >= >=
小于等于號 <= <=
單引號 ' '
雙引號 " "
天學習了JS相關的基礎知識,了解了JS變量、常量的聲明,以及let、const的區別,今天學習了字符串模板,發現這真是一個好東西,非常實用,下面我把今天所學的內容總結梳理一下,把重點知識跟大家分享一下,也便于日后我復習所用。
模板字面量是在字符串中允許插入表達式的字符串字面量,我們可以使用多行字符串和字符串的插值功能。在ES2015(即:ES6)規范的先前版本中被稱為“模板字符串”。
` string `
` string ${expression} `
` string ${expression} string `
模板字符串是增強版的字符串(Plus+),使用反引號(` `)來替代普通字符串中的單雙引號,其中${expression}表示占位符。
注意在模板字符串中如果想使用反引號(`)需要加一個轉義符(\),即:\`
console.log('This is my first JS Code'); // This is my first JS Code
普通字符串
在以前的字符串中,如果我們想要多行字符串,需要用到換行符(\n),例如:
console.log('This is my first JS Code \n' +
'This is my second JS Code');
多行字符串
但是,現在可以利用模板字符串簡化這個問題:
console.log(`This is my first JS Code
This is my second JS Code`);
傳統的JS表達式需要這樣寫:
let num = 30;
let price = 100;
let res = '商品數量' + num + ', 單價:' + price + '元,總計:' + num * price;
使用上述傳統的表達式寫起來看著非常的亂,不直觀,有時候還容易把連接符(+)寫漏掉了,使用了ES6的模板字符串可以很好的避免這個問題:
res = `商品數量:${num},單價:${price},總計:${num * price}`;
console.log(res); // 商品數量:30,單價:100,總計:3000
以上結果都輸出:
商品數量:30,單價:100,總計:3000
標簽可以用函數來解析模板字符串。標簽函數的第一個參數是一個包含了字符串值的數組,剩余的參數與表達式相關。
let num = 10;
let price = 99;
function show(strings, var1, var2) {
console.log(strings);
console.log(var1, var2);
}
show `商品數量:${num}單價:${price}總計:${num * price}`;
由上圖可以看出,strings的值是一個由多組字符串組成的數組,va1,var2的值分別為num和price的值,由此結果可以很明顯的看到,在使用標簽函數時,模板字符串會被分割成多個部分,然后傳入標簽函數中進行處理,并且是以${expression}為分隔符進行分割的。從這個結論我們可以做一個總結:
以上就是我所學的模板字符串的幾個常用的方法,總體感覺還不算是太難,上手很容易,根據我所學的內容,我對模板字符串做了如下總結:
*請認真填寫需求信息,我們會在24小時內與您取得聯系。