PHP开发笔记

PHP开发笔记

JSON数据的解析

$json_data = isset($_GET['json_data']) ? $_GET['json_data'] : null;
$json_data=str_replace("",'',$json_data);

从前台接收到的json字符串,在json_decode的时候需要先将多余的反斜线字符处理掉,才能正确转换成对象或数组。

JQuery支持的数组去重方法

var yearArray = new Array(2009, 2009, 2010, 2010, 2009, 2010);
$.unique(yearArray);
返回 2009, 2010, 2009, 2010

php字符串替换

php字符串与变量的混合时,可以使用双引号,内部嵌套php变量。从而省去以.为分割的书写方式。

$sql = "UPDATE ".TABLE_MOBILE_APP_DEVICES."
SET app_name='{$req_client}',app_version='{$req_cv}',device_os='{$device_os}'

比较适合长字符串的sql拼接。

关于全局变量

PHP 中全局变量在函数中使用时必须声明为 global
且使用时若对其进行修改,则影响全局变量的值。
也可以使用超全局变量$GLOBALS['var']来访问。
要深入理解函数的作用范围

PHP 中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可用。在函数或方法中无需执行 global $variable; 就可以访问它们。

这些超全局变量是:

$GLOBALS $_SERVER $_GET $_POST $_FILES $_COOKIE $_SESSION $_REQUEST $_ENV

JS获取随机数

function RandNum(n){
var rnd="";
for(var i=0;i<n;i++)
rnd+=Math.floor(Math.random()*10);
return rnd;
}

字符串的输出

echo <<< EOF
this is a text;

输出的html大段代码。。

EOF;

要求起始标记和结束标记要相同。

关于双引号和单引号的问题:

双引号有变量解析功能!

PHP中尽量用单引号,HTML代码全部用双引号

在包含变量的时候,用双引号可以简化操作

复杂的情况下用大括号包起来

几个 PHP 的“魔术常量”

FILE 文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。自 PHP 4.0.2 起,FILE 总是包含一个绝对路径(如果是符号连接,则是解析后的绝对路径),而在此之前的版本有时会包含一个相对路径。
E:yuloreCodesrc_portaladminmytest.php

DIR 文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。它等价于 dirname(FILE)。除非是根目录,否则目录中名不包括末尾的斜杠。(PHP 5.3.0中新增)
E:yuloreCodesrc_portaladmin

JS Ajax返回数据字符串提前转换

if (typeof data === 'string') {
data = JSON.parse(data);
}

第三方服务的异步调用

(小米外卖)对于和第三方的接口调用,只要我们自己的服务没有出现异常或错误,返回给用户的信息应该均为成功。推第三方改为“异步调用”,即使有个别订单出现问题,可以通过人为干预或者后台运维解决。不应该因为比较小的第三方服务不稳定而拖垮我们的系统。否则严重影响用户体验。

MySql分页的简单实现

select * from table limit (pagenum*pagesize-pagesize),pagesize

static function getPushList($pagesize, $pagenum, $status, $begintime, $endtime) {
        global $db_mysql;
        $sql_select = "SELECT p.user_id,p.template_id,p.status,ud.mobile_system,p.add_time,a.owner,a.id as apikeyid ,p.title,p.content,ua.mobile,case when ud.client_type='Getui' then '个推' end as client_type ";
        $sql_count = 'SELECT count(*) ';
        $sql = "FROM push_info p left join user_device ud on p.user_id=ud.user_id
                left join yulore.dict_user_accounts ua on p.user_id=ua.id
                left join yulore.admin_apikey a on a.id=ua.apikeyid  where 1=1 ";

        if ($status !== 'all') {
            $sql .= " and p.status='$status' ";
        }
        if (!empty($begintime)) {
            $sql .= " and p.add_time>='$begintime' ";
        }
        if (!empty($endtime)) {
            $endtime = date("Y-m-d", strtotime($endtime . " +1 day"));
            $sql .= " and p.add_time<='$endtime' ";
        }
        $sql .= ' order by p.add_time desc';


        $page = " limit " . ($pagenum * $pagesize - $pagesize) . "," . $pagesize;

        $sql_query = $sql_select . $sql . $page;
        //var_dump($sql_query);
        $stmt = $db_mysql->query($sql_query);
        $data = $stmt->fetchAll();
        $rs = $db_mysql->query($sql_count . $sql);
        $count = $rs->fetchAll();
        return array(
            'data' => $data,
            'max_count' => (int)$count[0][0],
        );
    }

跨域的问题

对外提供js接口的时候要考虑是否在同一个域里,或者返回jsonp的结构。

数据传输和提交的数据量不同有不同的解决方案

页面间数据传输要考虑数据量的大小,数据量超过一定程度的时候就不应该使用cookie了。
可以使用html5的storage存储。
对于大数据量ajax调用的时候不应该使用get方式,否则会出现连接字符串超长的情况。
后台php接收的时候也需要做相应的调整。

在HTML5中,本地存储是一个window的属性,包括localStorage和sessionStorage,从名字应该可以很清楚的辨认二者的区别,前者是一直存在本地的,后者只是伴随着session,

窗口一旦关闭就没了(刷新和后退是存在的)。二者用法完全相同,这里以localStorage为例。

if(window.localStorage){
alert('This browser supports localStorage');
}else{
alert('This browser does NOT support localStorage');
}

localStorage.a = 3;//设置a为"3"
localStorage["a"] = "sfsf";//设置a为"sfsf",覆盖上面的值
localStorage.setItem("b","isaac");//设置b为"isaac"
var a1 = localStorage["a"];//获取a的值
var a2 = localStorage.a;//获取a的值
var b = localStorage.getItem("b");//获取b的值
localStorage.removeItem("c");//清除c的值

任何格式存储的时候都会被自动转为字符串,所以读取的时候,需要自己进行类型的转换。

CSS控制数据长度溢出

text-overflow: ellipsis;(省略号,或者自定义符号)

php服务器错误信息的显示

在php.ini中需要打开出错开关:display_errors:On

其次,如果在生产环境中,不能打开这种开关的情况下,也可以通过编程的形式来临时打开这个开关(但是有局限性)

需要执行这样的设置:

ini_set('display_errors', '1');

前端调试,使用Fiddler调试生产环境JS

参考:http://www.aliued.cn/2010/04/25/use-fiddler-to-improve-efficiency-of-front-development-example.html

http://www.open-open.com/lib/view/open1375954572906.html

生产环境的log日志级别要分清

一般的记成info,debug,真正严重的才记成error

controller里尽量只做简单的事情

多线程神马的不要在controller中做。

ajax相关:

调用时要考虑跨域的问题。
ajax调用时会自动携带cookie信息(fiddler中可以查看到)

HTML5页面规范

文件头要规范书写:

图片延迟加载及出错替换机制

延迟加载:参考jquery的lazyload插件

实际使用的:滚动加载插件。参考地址:

http://www.zhangxinxu.com/wordpress/2010/11/jquery页面图片等元素滚动动态加载实现/

使用步骤:

1.引用jquery,js

2.img标签增加默认图片和实际图片的属性:

3.调用方法: $(".scrollLoading").scrollLoading();

出错替换机制:

多Ajax请求异步顺序出错调试

多个ajax请求有时候后者的请求数据需要前者的支持,因此可能会出现返回的时间和代码书写的顺序不一致的情况。典型的情况是,反复刷新页面多次,偶尔会有bug的发生,可以利用firebug的console.log(number)的方法把ajax回调函数分别按顺序log下来,看执行时候的输出情况,便可以发现这个问题,从而解决问题。

解决方案:在controller中把多个请求合并成一个返回给页面。

mysql 插入更新语法

insert语句后加
ON DUPLICATE KEY UPDATE + 列名=新值,列名=新值
使用场景:
这个语法和适合用在需要 判断记录是否存在,不存在则插入存在则更新的场景.
往有唯一键表中插入数据时,如果不存在该记录则插入,存在则更新已存在的记录。
省去了使用ifelse来判断是否有值的情况,但是性能会稍差一些
示例
INSERT INTO admin_tel_check_config VALUES('test_a','test','http://www.baidu.com','new',NOW())
ON DUPLICATE KEY UPDATE check_id='test_b',check_desp='test1',api='abc',STATUS='old',date_added=NOW()

mysql文档:http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#insert

isset/empty区别

empty

如果 变量 是非空或非零的值,则 empty() 返回 FALSE。换句话说,""、0、"0"、NULL、FALSE、array()、var $var、未定义; 以及没有任何属性的对象都将被认为是空的,如果 var 为空,则返回 TRUE。

isset
如果 变量 存在(非NULL)则返回 TRUE,否则返回 FALSE(包括未定义)。变量值设置为:null,返回也是false;unset一个变量后,变量被取消了。注意,isset对于NULL值变量,特殊处理。
is_null
检测传入值【值,变量,表达式】是否是null,只有一个变量定义了,且它的值是null,它才返回TRUE . 其它都返回 FALSE 【未定义变量传入后会出错!】.

PHP导出CSV

function export_csv($filename, $data)
{
header("Content-type:text/csv");
header("Content-Disposition:attachment;filename=" . $filename);
header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
header('Expires:0');
header('Pragma:public');
$data = iconv('utf-8', 'gb2312', $data);
echo $data;
}

生成html绑定

对于生成的html绑定事件,需要这样
参考:
http://www.cnblogs.com/coffeedeveloper/archive/2013/04/19/3029922.html

//操作事件绑定
$('#dataContent').on('change', '.ddl_error_type', function () {
var val = $(this).val();
//alert(val);
if (val == 'others') {
$(this).parent().find(".txt_desp").show();
$(this).parent().find(".btn_submit").show();
}
else if (val == 'none') {
$(this).parent().find(".txt_desp").hide();
$(this).parent().find(".btn_submit").hide();
} else {
$(this).parent().find(".txt_desp").hide();
$(this).parent().find(".btn_submit").show();
}
});

条件sql

select c.condition_id,city_name,category_name,real_count,error_count,if ((select condition_id from admin_tel_check_condition_user WHERE condition_id=tb.condition_id) IS NULL,'false','true') as test_flag from admin_tel_check_condition c left join (select condition_id,count(condition_id)as error_count from admin_tel_check_result where error_type!='none' group by condition_id ) tb
on tb.condition_id=c.condition_id 
where c.check_id='test_20140611v1' order by city

设置table从0开始自增

alter table tablename auto_increment=0

PHP命名空间

require_once('regulation.class.php');
require_once('test.class.php');

use ReguRegulation;
use OtherRegulation as Regulation1;

$t=new Regulation();
$t->test();
//Regu test function

$s=new Regulation1();
$s->test();
//Other test function

对象转数组(深层,快速)

$array = json_decode(json_encode($nested_object), true);

Mysql返回影响的行数

mysql_select_db("mydb");
mysql_query("DELETE FROM mytable WHERE id < 5");
$rc = mysql_affected_rows();
echo "Records deleted: " . $rc;

PHP字符串拆分,连接函数

$id_arr = explode(",", $shopIds);//根据逗号分隔成数组
$id_str = implode("-", $id_arr);//数组连接成字符串

JQuery下拉菜单绑定选中项。

通用,兼容,简单的方法:
$("#select_id").val('选中项的值');

JS写入cookie

var date=new Date();
var expiresDays=10;
date.setTime(date.getTime()+expiresDays243600*1000);
document.cookie="auth_id=ede87c9a1d083f557acb02f1a3b862036263938f2f6dc7838252ddc022d9ed06; path=/;domain=.dianhua.cn;expires="+date.toGMTString();

PHP预处理SQL防止注入(PDO方式)

define("PDO_DSN", "mysql:dbname={$dbname};host={$host}");
define("PDO_USER", $user);
define("PDO_PASS", $pwd);

$this->db = new PDO(PDO_DSN, PDO_USER, PDO_PASS);

try {
$sql = "INSERT INTO ".self::TABLE_CLIENTS." (appname, client_secret, redirect_uri) VALUES (:appname, :client_secret, :redirect_uri)";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(":appname", $appname, PDO::PARAM_STR);
$stmt->bindParam(":client_secret", $client_secret, PDO::PARAM_STR);
$stmt->bindParam(":redirect_uri", $redirect_uri, PDO::PARAM_STR);
$stmt->execute();
} catch (PDOException $e) {
$this->handleException($e);
}

$uid = '%|' . $uid;
$db = new PDO("mysql:dbname={$dbname};host={$host}", $user, $pwd);
try {
$sql = "select id from dict_user_accounts where apikeyid =:apikeyid and account like :uid ";
$stmt = $db->prepare($sql);
$stmt->bindParam(":apikeyid", $apikeyid, PDO::PARAM_INT);
$stmt->bindParam(":uid", $uid, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchALL();
} catch (PDOException $e) {
die('{"status":"202","msg":"Invalid Request"}');
}

PHPStorm调试配置

[XDebug] 
; Only Zend OR (!) XDebug 
zend_extension="D:xamppphpextphp_xdebug-2.2.5-5.5-vc11.dll"
xdebug.auto_trace=On
xdebug.collect_params=On
xdebug.collect_return=On
xdebug.trace_output_dir="d:/xampp/php/debuginfo"
xdebug.profiler_enable=On
xdebug.profiler_output_dir="d:/xampp/php/debuginfo"
xdebug.idekey=PhpStorm
xdebug.remote_enable=on
xdebug.remote_host=api.dev.dianhua.cn
xdebug.remote_port=9000
xdebug.remote_handler=dbgp

php生成get参数方法

http_build_query($data);

php 重定向(无回退跳转)

header("HTTP/1.1 301 Moved Permanently");
header("Location:$url");

或者使用iframe
<iframe style="margin: 0; padding: 0" width="100%" height="100%" frameBorder="no" src="<?php echo $url;?>" target="_top">
</iframe>
可以实现浏览器不记住跳转页

去掉input控件的历史输入
autocomplete="off"
可用于input控件或者form表单
<input AUTOCOMPLETE ="off">
<form action="./list.php" method="get" autocomplete="off">

php数据库插入json等有反斜杠的字符时,需要进行转义(参数转义)

可用mysql_real_escape_string,addslashes(good) 函数

switch条件语句或的运用

switch($val){
case 'test1':
case 'test2':
echo 333333;
break;
case 'test5':
echo 55555;
break;
default:
echo '0000';
break;
}

JS检测数据是否是JSON

if (typeof data === 'string') {
data = JSON.parse(data);
}

php打印url

echo '
page url:'.$_SERVER["REQUEST_URI"];
echo '
http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
echo '
http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
echo '

';
print_r($_SERVER);
echo '
';

PHP时间处理,转换&比较

//原生方法进行日期比较
//mysql:SELECT FROM_UNIXTIME(1422522566), UNIX_TIMESTAMP('2015-01-29 17:09:26')
$exp_time_raw=strtotime('2015-01-29 16:38:01');
echoFormat('$exp_time_raw unixtime:' . $exp_time_raw);

$time= date('Y-m-d H:i:s',$exp_time_raw);
var_dump($time);
使用时间戳进行大小判断!

register_shutdown_function

函数可实现当程序执行完成后执行的函数,其功能为可实现程序执行完成的后续操作
register_shutdown_function('api::fatal_error');
可用于错误处理。

//捕获语法错误
public static  function fatal_error() {
    if ($e = error_get_last()) {
        switch($e['type']){
          case E_ERROR:
          case E_PARSE:
          case E_CORE_ERROR:
          case E_COMPILE_ERROR:
          case E_USER_ERROR:
            self::_server_error($e['message'].' '.$e['file'].' '.$e['line']);
            break;
        }
    }
}

不同系统的路径分隔符

define('SYSTEM_PATH',DIR.DIRECTORY_SEPARATOR);
include SYSTEM_PATH.'inc/init.php';

记住登录状态的实现

1.生成一个随机的,唯一的字符串(可通过userid生成)token,保存在服务端(数据库/缓存),并与当前用户绑定。
2.将这个token写入cookie,并设置一个过期时间(7天)
3.用户登录时,拿着用户id和cookie中的token去服务端验证,比对。相等则认为是合法用户。
4.比对成功后,服务端和客户端cookie同时做刷新操作(重新生成一个新的token)

PHP定时任务需要注意的

1.进行try catch异常捕获
try{}
catch (Exception $e) {
$e->getCode() . ' message:' . $e->getMessage() . ' line:' . $e->getLine() . ' trace:' . $e->getTraceAsString());
}
2.设置脚本的执行时间为无限制:set_time_limit(0);
3.引用文件使用绝对路径,即用__DIR__.'/../'方式
4.考虑变量的回收效率,防止长时间运行占用过多内存。可以将程序模块化,在function里执行。

json_encode扩展

//json_encode扩展,增加php低版本中文乱码的问题
function json_encode_extension($arr) {
 if (defined('JSON_UNESCAPED_UNICODE')) {
 return json_encode($arr, JSON_UNESCAPED_UNICODE);
 }
 return urldecode(json_encode(urlencode_arr($arr)));
}

//json_encode扩展
function urlencode_arr($arr) {
 if (empty($arr)) {
 return null;
 }
 $result_arr = array();
 foreach ($arr as $k => $v) {
 if (is_array($v)) {
 $result_arr[$k] = urlencode_arr($v);
 } else {
 $result_arr[$k] = urlencode($v);
 }
 }
 return ($result_arr);
}

CURL设置超时时间及判断

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 6);//低版本curl不支持毫秒级超时
if (!empty($data)) {
 curl_setopt($ch, CURLOPT_POST, 1);
 $postStr = http_build_query($data);
 curl_setopt($ch, CURLOPT_POSTFIELDS, $postStr);
}
if (!empty($headers)) {
 curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$output = curl_exec($ch);
// log curl error.
if(curl_errno($ch)){
 $error_num=curl_errno($ch);
 if($error_num==28){
 $logger->error('curl post timeout! url:'.$url,$data);
 }else{
 $logger->error('curl post error:'.curl_errno($ch).' url:'.$url,$data);
 }
}
curl_close($ch);

PHP获取毫秒时间戳

function getMsecTime(){
$time = explode ( " ", microtime () );
$time = $time [1] . ($time [0] * 1000);
$time2 = explode ( ".", $time );
$time = $time2 [0];
return $time;
}

对象序列化和反序列化

方便把php对象或数组转换成字符串存储
$test_arr=array('name'=>'wj','value'=>111);
$re= serialize($test_arr);
var_dump($re);
var_dump(unserialize($re));

//result:
string 'a:2:{s:4:"name";s:2:"wj";s:5:"value";i:111;}' (length=44)

array (size=2)
'name' => string 'wj' (length=2)
'value' => int 111

PHP异常处理回调函数及页面完成回调函数

set_exception_handler为出现异常的回调函数
register_shutdown_function为页面退出前执行的回调函数
使用这两个函数可以用于框架中集中处理错误及业务带来帮助

function catch_exception_callback($e){
 echo 'catch exception<br>';
 echo $e->__toString();
}

function shutdown_callback(){
 echo '<br>begin shutdown<br>';
}

set_exception_handler('catch_exception_callback');
register_shutdown_function('shutdown_callback');
throw new Exception('errorR',101);
die();

php禁用页面缓存

header('Cache-Control: max-age=0');
header("Cache-Control: no-cache, must-revalidate"); //HTTP 1.1
header("Pragma: no-cache");//http 1.0

获取当前调用的信息

debug_backtrace();

类的方法重载

在对象中调用一个不可访问方法时,__call() 会被调用。
用静态方式中调用一个不可访问方法时,__callStatic() 会被调用。/** PHP 5.3.0之后版本 */
可用于类中多个方法功能类似的单一入口,在call方法中进行判断即可,防止复制多个方法。

php设置url中某参数

function url_set_value($url, $key, $value) {
$a = explode('?', $url);
$url_f = $a[0];
$query = $a[1];
parse_str($query, $arr);
$arr[$key] = $value;
return $url_f . '?' . http_build_query($arr);
}
$new url=url_set_value(HOST_NAME . $_SERVER['REQUEST_URI'], 'page', '2');

php自带验证/过滤函数

$url = filter_var(trim($_GET['url']), FILTER_VALIDATE_URL);
if(!$url){
throw new Exception('跳转URL格式错误');
}
类似的Email验证,IP验证FILTER_VALIDATE_EMAIL,FILTER_VALIDATE_IP

php字符串查找

$pos = strrpos($mystring, "b");
if ($pos === false) { // 注意: 三个等号
// 未发现...
}

========
update 2015-04-22

原文地址:https://www.cnblogs.com/dannywang/p/4448045.html