做PHP開發(fā)也四五年了坤塞,期間遇到無數(shù)的坑,填坑的過程中能力也得到了提升〕喊觯現(xiàn)在通過文章的形式把PHP摹芙,JS,SQL中一些有趣的用法記錄下來宛瞄,希望對剛剛?cè)腴T的同學(xué)有所幫助浮禾,還望老鳥手下留情,勿噴坛悉,哈哈伐厌。如果寫的有錯誤,還望指正。
不定期更新
1.PHP中switch的另類用法
比如下面if elseif 的判斷,當(dāng)判斷條件太復(fù)雜的時候,感覺會比較亂(PS:個人覺得)
if($a == 1){
}elseif ($b == 2) {
# code...
}elseif($c == 3){
}elseif ($d == 4) {
# code...
}else{
}
那么通過switch也能實現(xiàn)if elseif相同的功能,一般印象中,switch語句只能判別指定變量的不同的值,貌似JAVA的switch語句只能判斷指定變量的值裸影。
switch(true){
case $a == 1:
#code
break;
case $b == 2:
#code
break;
case $c == 3:
#code
break;
case $d == 4:
#code
break;
default:
#code
break;
}
結(jié)語:記得js也能使用這種結(jié)構(gòu)挣轨,可能弱類型的語言的原因吧
2.MySQL where field in ()的另類寫法
一般我們寫where field in都是類似于這樣:
select * from table where id in (1,2,3)
不過實際情況中,會有一張表中的多個類似的字段設(shè)定的值一樣轩猩。
一般我們的寫法可能會這樣
select * from table where a = 1 or b = 1 or c = 1
那我們可以用where in來實現(xiàn)相同的目的
select * from table where 1 in (a,b,c)
PS:這類用法可能應(yīng)用場景不大卷扮。哈哈
3.PHP foreach循環(huán)語句中使用引用,簡化對數(shù)組單元的操作,比方賦值操作,更改原單元指定鍵值的值
先列一下一般的操作方法
foreach($array as $key => $row){
$array[$key]['a'] = 1;
$array[$key]['b'] = 2;
}
通過使用引用操作符&,我們可以這樣操作
foreach($array as &$row){
$row['a'] = 1;
$row['b'] = 2;
}
PS:算偷點懶吧均践,哈哈
4.Thinkphp3.2.3使用中的一個坑
thinkphp在國內(nèi)的粉絲還是很多的,框架也很成熟,不過用的過程中會有碰到一些比較尷尬的bug,今天開發(fā)中就遇到了這樣的一個坑.使用模型里自動驗證+自動完成組合使用時碰到的一個小bug,自動驗證+自動完成都使用動態(tài)綁定操作.代碼如下:
$validate = array(
array("mobile","require","手機(jī)號必填"),
array("mobile","/^1[34578]\d{9}$/","手機(jī)號碼格式錯誤",1,"regex",3),
array("mobile","","該手機(jī)號已存在",1,"unique",1),
array("pwd","require","密碼不能為空"),
array("pwd","6,100","密碼長度不能少于6位",1,"length",1),
);
$auto = array(
array("pwd","md5",1,"function"),
array("name","小明",1),
array("create_time",I("server.REQUEST_TIME"),1),
);
if(!M("User")->validate($validate)->auto($auto)->create()){
#code
}
因為在validate中有個檢驗手機(jī)號是否唯一的條件,unique這步驗證會到用到Model類里的find操作,find操作后會清空Model中的屬性options,這樣就會導(dǎo)致模型的自動完成失效;
PS:所以有Model驗證操作中有用unique操作的,不要將自動驗證+自動完成合在一起操作,這樣會導(dǎo)致自動完成失效.不過在模型中定義了$_validate和$_auto屬性的不存在這個問題.
5.ThinkPHP3.2.3版本,憑自己的經(jīng)驗封裝一個分頁取數(shù)據(jù)的方法,其實就是為了偷個懶,少寫點代碼.
首先,先探究下Think\Model類中的select和count操作
select操作:
/**
* 查詢數(shù)據(jù)集
*
* @access public
* @param array $options 表達(dá)式參數(shù)
* @return mixed
*/
public function select($options=array()) {
$pk = $this->getPk();
if(is_string($options) || is_numeric($options)) {
// 根據(jù)主鍵查詢
if(strpos($options,',')) {
$where[$pk] = array('IN',$options);
}else{
$where[$pk] = $options;
}
$options = array();
$options['where'] = $where;
}elseif (is_array($options) && (count($options) > 0) && is_array($pk)) {
// 根據(jù)復(fù)合主鍵查詢
$count = 0;
foreach (array_keys($options) as $key) {
if (is_int($key)) $count++;
}
if ($count == count($pk)) {
$i = 0;
foreach ($pk as $field) {
$where[$field] = $options[$i];
unset($options[$i++]);
}
$options['where'] = $where;
} else {
return false;
}
} elseif(false === $options){ // 用于子查詢 不查詢只返回SQL
return $this->buildSql();
}
// 分析表達(dá)式
$options = $this->_parseOptions($options);
// 判斷查詢緩存
if(isset($options['cache'])){
$cache = $options['cache'];
$key = is_string($cache['key'])?$cache['key']:md5(serialize($options));
$data = S($key,'',$cache);
if(false !== $data){
return $data;
}
}
$resultSet = $this->db->select($options);
if(false === $resultSet) {
return false;
}
if(empty($resultSet)) { // 查詢結(jié)果為空
return null;
}
if(is_string($resultSet)){
return $resultSet;
}
$resultSet = array_map(array($this,'_read_data'),$resultSet);
$this->_after_select($resultSet,$options);
if(isset($options['index'])){ // 對數(shù)據(jù)集進(jìn)行索引
$index = explode(',',$options['index']);
foreach ($resultSet as $result){
$_key = $result[$index[0]];
if(isset($index[1]) && isset($result[$index[1]])){
$cols[$_key] = $result[$index[1]];
}else{
$cols[$_key] = $result;
}
}
$resultSet = $cols;
}
if(isset($cache)){
S($key,$resultSet,$cache);
}
return $resultSet;
}
count操作:
/**
* 利用__call方法實現(xiàn)一些特殊的Model方法
*
* @access public
* @param string $method 方法名稱
* @param array $args 調(diào)用參數(shù)
* @return mixed
*/
public function __call($method,$args) {
if(in_array(strtolower($method),$this->methods,true)) {
// 連貫操作的實現(xiàn)
$this->options[strtolower($method)] = $args[0];
return $this;
}elseif(in_array(strtolower($method),array('count','sum','min','max','avg'),true)){
// 統(tǒng)計查詢的實現(xiàn)
$field = isset($args[0])?$args[0]:'*';
return $this->getField(strtoupper($method).'('.$field.') AS tp_'.$method);
}elseif(strtolower(substr($method,0,5))=='getby') {
// 根據(jù)某個字段獲取記錄
$field = parse_name(substr($method,5));
$where[$field] = $args[0];
return $this->where($where)->find();
}elseif(strtolower(substr($method,0,10))=='getfieldby') {
// 根據(jù)某個字段獲取記錄的某個值
$name = parse_name(substr($method,10));
$where[$name] =$args[0];
return $this->where($where)->getField($args[1]);
}elseif(isset($this->_scope[$method])){// 命名范圍的單獨調(diào)用支持
return $this->scope($method,$args[0]);
}else{
E(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_'));
return;
}
}
發(fā)現(xiàn)count操作實際是調(diào)用類的方法getField
/**
* 獲取一條記錄的某個字段值
*
* @access public
* @param string $field 字段名
* @param string $spea 字段數(shù)據(jù)間隔符號 NULL返回數(shù)組
* @return mixed
*/
public function getField($field,$sepa=null) {
$options['field'] = $field;
$options = $this->_parseOptions($options);
// 判斷查詢緩存
if(isset($options['cache'])){
$cache = $options['cache'];
$key = is_string($cache['key'])?$cache['key']:md5($sepa.serialize($options));
$data = S($key,'',$cache);
if(false !== $data){
return $data;
}
}
$field = trim($field);
if(strpos($field,',') && false !== $sepa) { // 多字段
if(!isset($options['limit'])){
$options['limit'] = is_numeric($sepa)?$sepa:'';
}
$resultSet = $this->db->select($options);
if(!empty($resultSet)) {
$_field = explode(',', $field);
$field = array_keys($resultSet[0]);
$key1 = array_shift($field);
$key2 = array_shift($field);
$cols = array();
$count = count($_field);
foreach ($resultSet as $result){
$name = $result[$key1];
if(2==$count) {
$cols[$name] = $result[$key2];
}else{
$cols[$name] = is_string($sepa)?implode($sepa,array_slice($result,1)):$result;
}
}
if(isset($cache)){
S($key,$cols,$cache);
}
return $cols;
}
}else{ // 查找一條記錄
// 返回數(shù)據(jù)個數(shù)
if(true !== $sepa) {// 當(dāng)sepa指定為true的時候 返回所有數(shù)據(jù)
$options['limit'] = is_numeric($sepa)?$sepa:1;
}
$result = $this->db->select($options);
if(!empty($result)) {
if(true !== $sepa && 1==$options['limit']) {
$data = reset($result[0]);
if(isset($cache)){
S($key,$data,$cache);
}
return $data;
}
foreach ($result as $val){
$array[] = $val[$field];
}
if(isset($cache)){
S($key,$array,$cache);
}
return $array;
}
}
return null;
}
通過分析代碼我們發(fā)現(xiàn),select操作和count操作最后都是通過$this->db->select($options)這段代碼從數(shù)據(jù)庫里獲取數(shù)據(jù)的.而這個$options局部變量都是通過$this->_parseOptions($options);這個方法賦值的.
發(fā)現(xiàn)了這個共同點,那么我們就開始封裝一個分頁取數(shù)據(jù),返回總條數(shù)和指定的分頁數(shù)據(jù):
(1)定義一個BaseModel類繼承自Think\Model的基類
namespace Common\Model;
use Think\Model;
class BaseModel extends Model{
}
(2)實現(xiàn)分頁取數(shù)據(jù)的方法
namespace Common\Model;
use Think\Model;
class BaseModel extends Model{
/**
*
* 默認(rèn)獲取數(shù)據(jù)表10條記錄每次
* @param $print_return
* 默認(rèn)分頁取數(shù)據(jù) @param $needLimit
* @return array
*/
public function getList($needLimit = true,$print_return = false){
$options = $this->options;
$options['alias'] = isset($this->options['alias']) ? $this->options['alias'] : 'a';
if(isset($this->options['order']) && !empty($this->options['order'])){
$options['order'] = $this->options['order'];
}else{
if(in_array('create_time',$this->fields)){
$options['order'] = $options['alias'].".create_time desc";
}
}
/*沒限制分頁,則默認(rèn)每次取10條*/
if($needLimit){
if(empty($this->options['page']) && empty($this->options['limit'])){
$pindex = max(1,intval(I('p',1)));
$psize = C('PER_PAGE');
$limit = intval($pindex-1)*$psize.','.$psize;
$this->limit($limit);
$options['limit'] = $this->options['limit'];
}
}
$this->options = $options;
//統(tǒng)計數(shù)據(jù)不需要ORDER
unset($this->options['order']);
$total = $this->count();
$this->options = $options;
$rows = $this->select();
$return = array(
'total' => $total,
'rows' => $rows,
'list' => $rows,
'status' => 1,
'page' => max(1,intval(I('p',1))),
//'sql' => APP_DEBUG ? $this->_sql() : '',
'pages' => $total % C('PER_PAGE') == 0 ? $total / C('PER_PAGE') : ceil($total / C('PER_PAGE'))
);
//需要打印結(jié)果時
if($print_return){
var_dump($return);
}
return $return;
}
}
(3):開始在控制器里使用這個封裝好的類
不能直接使用D的助手函數(shù)直接實例化BaseModel,因為會找不到這個base這個表,所以如果用D方法就需要你操作的表的Model繼承自BaseModel;
或者可以自行封裝一個M方法差不多的助手函數(shù),只不過實例化的時候是實例化BaseModel而不是Think\Model;
下面我用User這個來示例:
public function index(){
$data = D("User")->field($field)->where($where)->join()->order("uid desc")->limit("1,10")->getList();
}
$data中包含滿足條件的總數(shù)和對應(yīng)分頁的數(shù)據(jù)
PS:封裝的時候默認(rèn)給被操作的主表設(shè)置了一個別名(a)為了兼容join操作,所以取主表字段或者設(shè)置主表字段條件的時候需要在字段前加個a,從表的別名根據(jù)自己的實際情況來設(shè).
6.Javascript簡化Ajax提交數(shù)據(jù)的封裝
比如,有時我們需要用Ajax提交的數(shù)據(jù)在一個表單中,而這個表單里有很多字段并且這些字段都需要提交到服務(wù)器,如果我們一個一個取組裝這些數(shù)據(jù),那么這個代碼量就會很大,也有可能產(chǎn)生遺漏的問題.
既然問題已經(jīng)提出來了,那么我們就來解決這個問題.
先了解下Jquery中封裝的$.ajax(),$.get(),$.post()的方法介紹,提交數(shù)據(jù)的格式支持a=1&b=2&c=3
和Object對象形式兩種.
對象形式如下:
{
a:1,
b:2,
c:3
}
使用簡便方法前,需要給指定的form標(biāo)簽設(shè)置一個ID(例如:id="form"),第一種數(shù)據(jù)格式我們可以直接使用Jquery自帶的方法serialize()方法得到;
代碼如下:
var form = $("#form").serialize();
而第二種方法則需要自己封裝一個方法,這個網(wǎng)上有很多,下面貼一個我自己平時常用的一段封裝好的代碼:
<script>
(function($){
$.fn.serializeJSON = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
})(jQuery);
</script>
上述代碼一定要寫在引入Jquery類庫文件之后,否則會報錯.
使用方法如下:
<script>
var form = $("#form").serializeJSON();
</script>
得到表單的數(shù)據(jù)為以表單元素name為建,value為值的數(shù)據(jù).
應(yīng)用到Ajax中:
<script type="text/javascript">
var form = $("#form").serialize();
//var form = $("#form").serializeJSON();
$.ajax({
url:"",
dataType:"json",
data:form,
success:function(res){
#code
}
});
$.post("",form,function(res){
#code
});
$.get("",form,function(res){
#code
});
</script>
這樣就能簡化封裝ajax需要提交的數(shù)據(jù)