PHP开发笔记

时间:2022-06-11 10:10:56

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:\yuloreCode\src_portal\admin\mytest.php

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

E:\yuloreCode\src_portal\admin

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标签增加默认图片和实际图片的属性:

PHP开发笔记

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

出错替换机制:

PHP开发笔记

多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 Regu\Regulation;

use Other\Regulation 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:\xampp\php\ext\php_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