Big-man与PHP的交战(一)——阅读PHP代码
前言:
- Big-man在App的分析中就已经说到过了,Big-man现在所接触的以及所开发的App数据管理后台也就是用的PHP进行开发的,这令Big-man心生头痛的感觉。但是又不得不接触这门语言,并用这门语言进行开发。
PHP语言:
- 简单介绍一下:
- PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。
- PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。
- 用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。
Big-man分析的代码:
ads_add.php
:- 从这段代码的字面意思Big-man就可以理解得出它的大概意思,也就是所谓的广告添加的功能。
<?php
//author:cqq 2013-12-6
!defined('tbw_RP') && exit();
require R_P . 'template_ad.php';
require R_P . 'lib/uploadfile.php';
require R_P . 'models/cache_ads.php';
$table_items = cache_ads::$table_desc['items'];
$table_name = cache_ads::table_name;
$str_cur_ad = json_encode($g_current_ad);
$step = trim(S::getGP('step'));
$id = (int) S::getGP('id');
$ad = array();
if(!$step || $step === 'editview') {
//分类
require R_P . 'lib/backage_category_fun.php';
$category_single_arr = get_single_category($g_sub_company_id);
$site_category = array();
$site_category[0] = '无';
foreach ($category_single_arr as $val) {
$val['name'] = str_repeat(' ', 4 * (int) $val['depth']) . '|-' . $val['categoryname'];
$site_category[$val['id']] = $val['name'];
}
$g_provision['site_category'] = $site_category;
//广告所在页面
$g_current = array();
foreach ($g_current_ad as $key => $val) {
$g_current[$key] = $val['name'];
}
$g_provision['g_current_ad'] = $g_current;
}
if ($step === 'editview') {
if (!check_power('modify_ads')) {
echo NO_POWER;
return;
}
$step = 'edit';
$sql = ' select * from ' . $table_name . ' where id=' . $id .' and companyid = ' .$g_company_id;
$ad = $db->get_one($sql);
if (!$ad) {
$RET['code'] = 3;
$RET['msg'] = DATA_NOT_EXIST;
echo json_encode($RET);
return;
}
//广告显示位置
$ad_type = array();
if ($g_current_ad[$ad['ad_page']]['types']) {
foreach ($g_current_ad[$ad['ad_page']]['types'] as $key => $value) {
$ad_type[$key] = $value;
}
}
$g_provision['ad_type'] = $ad_type;
require tbw_TP . $relative_path_and_name . '.html';
pwOutPut();
} elseif($step === 'add' || $step === 'edit') {
header('Content-Type: application/json');
if ((($step === 'add') && !check_power('add_ads')) ||
(($step == 'edit') && !check_power('modify_ads'))) {
echo NO_POWER;
return;
}
$rreett = get_data_table($table_items,$ad);
if ($rreett['code'] > 0) {
echo json_encode($rreett);
return;
}
$ad['addtime'] = $timestamp;
if ($step === 'add') {
$ad['companyid'] = $g_company_id;
$ad['username'] = $g_tbwuser;
$sql = ' insert into '. $table_name . ' set ' . S::sqlSingle($ad);
$db->query($sql);
} else if ($step === 'edit') {
$sql = 'update '. $table_name . ' set ' . S::sqlSingle($ad) .
' where id = ' . $id . ' and companyid = ' . $g_company_id;
$db->query($sql);
}
$rows = $db->affected_rows();
if ($rows > 0) {
$RET['code'] = 0;
$RET['msg'] = OPERATE_SUCCESS;
echo json_encode($RET);
cache_ads::updateAds($ad['ad_page'], $ad['type']); //update all page
} else {
$RET['code'] = 0;
$RET['msg'] = OPERATE_FAIL;
echo json_encode($RET);
}
$logData = array(
'operation' => $sql,
'affected_rows' => $rows,
'type' => (($step === 'add') ? DATA_INSERT : DATA_UPDATE),
'description' => (($step === 'add') ? '添加广告' : '修改广告')
);
log::logger($logData);
} elseif ($step == 'uploadimg') {
if ((($step === 'add') && !check_power('add_ads')) ||
(($step === 'edit') && !check_power('modify_ads'))) {
echo NO_POWER;
return;
}
$maxSize = 600000;
if($_FILES['picture_file']['name'] == OPEN_PIC_NAME){
//$savePath = R_P . 'pic/open/';
$savePath = R_P . 'pic/' . date('Ymd', $timestamp) . '/ad/';
echo upload_pic($savePath, null, $maxSize);
}else{
$savePath = R_P . 'pic/' . date('Ymd', $timestamp) . '/ad/';
echo upload_pic($savePath, null, $maxSize);
}
} elseif ($step === 'deleteimg') {
if ((($step == 'add') && !check_power('add_ads')) ||
(($step == 'edit') && !check_power('modify_ads'))) {
$RET['code'] = 1;
$RET['msg'] = NO_POWER;
echo json_encode($RET);
return;
}
header('Content-Type: application/json');
$token = S::getGP('token', 'P');
if ($token !== $g_token) {
$RET['code'] = 2;
$RET['msg'] = IAMROBOT;
echo json_encode($RET);
return;
}
$key = trim(S::getGP('key', 'P'));
if ($key) {
echo delete_pic($key);
} else {
$RET['code'] = 5;
$RET['msg'] = DATA_NOT_EXIST;
echo json_encode($RET);
}
} else {
/*
if (!check_power('add_ads')) {
echo NO_POWER;
return;
}
//分类
require tbw_RP . 'lib/backage_category_fun.php';
$category_single_arr = get_single_category($g_sub_company_id);
$site_category = array();
$site_category[0] = '无';
if($category_single_arr){
foreach ($category_single_arr as $val) {
$val['name'] = str_repeat(' ', 4 * (int) $val['depth']) . '|-' . $val['categoryname'];
$site_category[$val['id']] = $val['name'];
}
}
$g_provision['site_category'] = $site_category;
//广告所在页面
$g_current = array();
foreach ($g_current_ad as $key => $val) {
$g_current[$key] = $val['name'];
}
$g_provision['g_current_ad'] = $g_current;
//广告显示位置
$ad_type = array();
$ad_type [0] = '无';
$g_provision['ad_type'] = $ad_type;
*
*/
$step = 'add';
$ad['bak_1'] = $timestamp;
require tbw_TP . $relative_path_and_name . '.html';
pwOutPut();
}
- 以上是代码的信息,解析来的话Big-man会一步一步地解析代码,方便像Big-man这样的小白驴可以很好的理解和认识。
<?php ?>
<?php ?>
:PHP 脚本以
<?php
开头,以?>
结尾:
<?php
// 此处是 PHP 代码
?>
!defined('tbw_RP') && exit();
!defined('tbw_RP') && exit();
这段代码Big-man刚开始理解起来非常的不靠谱,但是查阅了一些资源之后发现还是很需要的。
作用:
- 检查
tbw_RP
常量是否存在,如果不存在,就退出脚本。
- 检查
defined()
函数检查某常量是否存在,若常量存在,则返回true, 否则返回false。这也就说明define()
函数是一个Boolean
的函数类型。&&
:逻辑与符号;exit()
也就是exit() 函数输出一条消息,并退出当前脚本。- 该函数是 die() 函数的别名。
exit(status)
:- status 必需。规定在退出脚本之前写入的消息或状态号。状态号不会被写入输出。所以Big-man个人认为这个函数此处出现了问题,因为status是必须有的参数。
- 如果 status 是字符串,则该函数会在退出前输出字符串。
- 如果 status 是整数,这个值会被用作退出状态。退出状态的值在 0 至 254 之间。
- 状态 0 用于成功地终止程序。
上面的这段代码可以改写为下面这段代码:
if(!defined('tbw_RP')) {
exit()
}
require
require R_P . 'template_ad.php';
require R_P . 'lib/uploadfile.php';
require R_P . 'models/cache_ads.php';
require
:说到require
不得不提起它的竞争对手include
,所以接下来Big-man将会去对比它们两个进行讲解。在 PHP 中,您可以在服务器执行 PHP 文件之前在该文件中插入一个文件的内容。
include 和 require 语句用于在执行流中插入写在其他文件中的有用的代码。
include
和require
除了处理错误的方式不同之外,在其他方面都是相同的:- require 生成一个致命错误(E_COMPILE_ERROR),在错误发生后脚本会停止执行。
- include 生成一个警告(E_WARNING),在错误发生后脚本会继续执行。
因此,如果您希望继续执行,并向用户输出结果,即使包含文件已丢失,那么请使用 include。否则,在框架、CMS 或者复杂的 PHP 应用程序编程中,请始终使用 require 向执行流引用关键文件。这有助于提高应用程序的安全性和完整性,在某个关键文件意外丢失的情况下。
包含文件省去了大量的工作。这意味着您可以为所有网页创建标准页头、页脚或者菜单文件。然后,在页头需要更新时,您只需更新这个页头包含文件即可。
就好比大家像Big-man一样写第一个
hello world
的时候用C语言,printf("hello world!")
的时候,如果你不写#include <stdio.h>
就无法使用printf();
打印函数,require
以及include
都是类似的这样的做法。
变量声明以及静态方法、静态变量引用:
- 代码段:
$table_items = cache_ads::$table_desc['items'];
$table_name = cache_ads::table_name;
$str_cur_ad = json_encode($g_current_ad);
$step = trim(S::getGP('step'));
$id = (int) S::getGP('id');
$ad = array();
PHP声明变量:
- 1、定义变量:
define("CONSTANT", "Hello world.");
- 常量只能包含标量数据(Boolean, Integer, Float以及String);
- 调用常量时,只需要简单的用名称取得常量的值,而不能加”$”符号,如:
echo CONSTANT;
注意:常量和(全局)变量在不同的名字空间中。这意味着例如
TRUE
和$TRUE
是不同的。2、普通变量:
$a = "hello";
3、可变变量:
$$a = "world";
(这里是Big-man第一次见到声明变量用到了两个美元符号).- 结合2以及3的变量声明,两个变量都被声明了;
$a
的内容是”hello”, 并且$hello
的变量内容是”world”。 - 因此,Big-man觉得可以把以上的这种声明变量的输出书写为这样的
echo "$a${$a}";
或者echo "$a$hello";
它们都是会输出”hello world”的结果。 - 要将可变变量用于数组,必须解决一个模棱两可的问题:
- 就是写下
$$a[1]
时,解析器需要知道是想要$a[1]
作为一个变量呢?还是想要$$a
作为一个变量并取出该变量中索引为[1]的值。 - Big-man觉得解决这个问题的方法与方式无疑就是对第一种情况用
$$a[1]
,对第二种情况用${$a}[1]
。
- 结合2以及3的变量声明,两个变量都被声明了;
4、静态变量:
- 在函数内部:
static $a = 0;
- 在函数内部:
- 注意:声明中用表达式的结果对其赋值会导致解析错误,比如:
static $a = 3 + 3;(error);
静态变量仅在局部函数域中存在(函数内部),函数执行完成之后,变量值不会丢失,可用于递归调用。
5、全局变量:
- 在函数体内定义的
global
变量,函数体外可以使用,在函数体内定义的global
变量不能在函数体内使用,在全局范围内访问变量可以使用特殊的PHP自定义$GLOBAL数组。 - 如:
$GLOBAL["b"] = $GLOBAL["a"] + $GLOBAL["b"];
。 - 在一个函数区域内用
global
语句导入的一个真正的全局变量实际上是建立了一个到全局变量的引用。 global $obj;
- 在函数体内定义的
注意:对于变量的
static
和global
定义是以应用的方式实现的。6、给变量赋值:传地址赋值(简单引用);
$bar = &$foo; //加$(美元符号)到将要赋值的变量前;
- 改动新的变量将影响到原始变量,这种赋值操作更加快速。
- 注意:只有命名变量才可以传地址赋值。
再注意:如果
$bar = &$a; $bar = &$foo;
改变$bar的值只能改变变量foo
的值,而不改变a的值(引用改变了)。7.PHP 超全局变量
$GLOBALS
: 包含一个引用指向每个当前脚本的全局范围内有效的变量。该数组的键标为全局变量的名称。从 PHP 3 开始存在 $GLOBALS 数组。$_SERVER
: 变量由 Web 服务器设定或者直接与当前脚本的执行环境相关联。类似于旧数组$HTTP_SERVER_VARS
数组(依然有效,但反对使用)。$_GET
: 经由 HTTP GET 方法提交至脚本的变量。$_POST
: 经由 HTTP POST 方法提交至脚本的变量。$_COOKIE
: 经由 HTTP Cookies 方法提交至脚本的变量。$_FILES
: 经由 HTTP POST 文件上传而提交至脚本的变量。- 文件上传表单中要有
enctype="multipart/form-data
” $_ENV
: 执行环境提交至脚本的变量。$_REQUEST
:经由GET
,POST
和COOKIE
机制提交至脚本的变量,因此该数组并不值得信任。所有包含在该数组中的变量的存在与否以及变量的顺序均按照php.ini
中的variables_order
配置指示来定义。该数组没有直接模拟 PHP 4.1.0 的早期版本。参见import_request_variables()
。- 注意: 自 PHP 4.3.0 起,$_FILES 中的文件信息不再存在于
$_REQUEST
中。 $_SESSION
:当前注册给脚本会话的变量。8、如何禁用
phpinfo()
:php.ini
中disable_functions = phpinfo()
- 重启web服务器。
9、php中的常量(这里Big-man再次进行详细的讲解php中的常量):
- 常量只能用define(常量名,常量值);
- 常量只能包含标量数据(boolean,integer,float 和 string)。
- 可以简单的通过指定其名字来取得常量的值,不要在常量前面加上
$
符号。 - 如果常量名是动态的,也可以用函数
constant()
来读取常量的值。用get_defined_constants()
可以获得所有已定义的常量列表。
- 注: 常量和(全局)变量在不同的名字空间中。这意味着例如
TRUE
和$TRUE
是不同的。 - 如果使用了一个未定义的常量,PHP 假定想要的是该常量本身的名字,如同用字符串调用它一样(
CONSTANT
对应"CONSTANT"
)。 此时将发出一个
E_NOTICE
级的错误。参见手册中为什么$w3sky[bar]
是错误的?(除非事先用 define() 将 bar 定义为一个常量)。如果只想检查是否定义了某常量,用 defined() 函数。10、常量和变量不同:
- 常量前面没有美元符号($);
- 常量只能用
define()
函数定义,而不能通过赋值语句(比如: $a = 0; 类似于这样的); - 常量可以不用理会变量范围的规则而在任何地方定义和访问;
- 常量一旦定义就不能被重新定义或者取消定义;
- 常量的值只能是标量。
11、Big-man自行定义一段代码来尝试常量 :
<?PHP define("CONSTANT", "Hello world."); echo CONSTANT; // outputs "Hello world." echo Constant; // outputs "Constant" and issues a notice. ?>
- 1、定义变量:
- 当然Big-man也要在这里说明声明的变量名的话就像开始学C写代码一样,反复地强调去声明的变量的必须是标识符(可以使用大小写字母、下划线或者
$
美元符号、数字 ),但是就好像Big-man刚开始不理解C一样,为什么不能数字开头成为一个标识符了?Big-man个人觉得是数字作为标识符,让程序世界怎么识别了;另外一个原因就是Made in American
。标识符的四大规范:
1、标识符由26个英文字符大小写(a~zA~Z)、数字(0~9)、下划线(_)和美元符号($)组成。 { C语言中: int 我;这样的声明肯定是通不过的。}
2、不能以数字开头,不能是关键字;
3、严格区分大小写 { C语言中: int a; 和 int b; 是两个不同的变量 };
4、标识符的可以为任意长度(但是Big-man不建议过于太长,有的情况是变量会限制在256个字符长度,比这个还长的话, 就说明大家写的变量名存在问题了)。
- PHP中的类中静态方法以及静态属性的引用方法:Big-man在这里用口述感觉还不如写出一段代码进行分析了。
class Test {
public static $test = 1;
public static function test() {
}
}
- 精彩的地方来了,PHP中可以不用进行实例化进行静态方法以及静态变量的使用,那进行什么了?进行如下的书写:
Test::$test;
来取得$test属性的值。 那样你就可以像Big-man这样进行依次类推地去调用静态方法
Test::test();
,这样就可以直接调用静态方法test
了。Big-man给出的上述代码中就存在
cache_ads::$table_desc['items'];
和cache_ads::table_name;;
调用的就是类中的静态属性;S::getGP('step')
以及S::getGP('id')
调用的就是类中的静态方法。
json_encode:
$str_cur_ad = json_encode($g_current_ad);
PHP中的
json_encode()
方法,但是Big-man不得不在这里提出,涉及到了json_encode()
, 那必须去设计另外一个方法函数了,那就是json_decode()
方法。json_decode:
json_decode
: (PHP 5 >= 5.2.0, PECL json >= 1.2.0)json_decode
一对JSON格式的字符串进行编码。说明:
mixed json_decode(string $json [, bool $assoc])
接受一个JSON格式的字符串并且把它转换为PHP变量。
参数:
json
:待解码的json string 格式的字符串。
assoc
当该参数为TRUE时,将返回
array
而非object
。返回值:
Returns an object or if the optional assoc parameter is TRUE, an associative is instead returned。
范例:
- Example 1(
JSON_decode
)的实例:
<?php
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
var_dump(json_decode($json));
var_dump(json_decode($json, true));
?>
- 上例将输出:
object(stdClass)#1 (5) {
["a"] => int(1)
["b"] => int(2)
["c"] => int(3)
["d"] => int(4)
["e"] => int(5)
}
array(5) {
["a"] => int(1)
["b"] => int(2)
["c"] => int(3)
["d"] => int(4)
["e"] => int(5)
}
- Example 2(JSON_decode)
$data='[
{"Name":"a1","Number":"123","Contno":"000","QQNo":""},
{"Name":"a1","Number":"123","Contno":"000","QQNo":""},
{"Name":"a1","Number":"123","Contno":"000","QQNo":""}
]';
echo json_decode($data);
- 结果输出为:
Array(
[0] => stdClass Object ( [Name] => a1 [Number] => 123 [Contno] => 000 [QQNo] => )
[1] => stdClass Object ( [Name] => a1 [Number] => 123 [Contno] => 000 [QQNo] => )
[2] => stdClass Object ( [Name] => a1 [Number] => 123 [Contno] => 000 [QQNo] => )
)
现在Big-man他可以观察出
json_decode($data, true)
输出的一个关联数组,由此可知json_decode($data)
输出的是对象,而json_decode("$arr", true)
是把它强制生成PHP关联数组。json_encode()
json_encode()
: (PHP 5 >= 5.2.0, PECL json >= 1.2.0)json_encode
一对变量进行JSON编码。- Report a bug说明:
string json_encode(mixed $value [, int $options = 0 ])
返回value值的JSON形式。
参数:
value
:待编码的value, 除了resource类型以外,可以为任何数据类型。
该函数只能接受UTF-8编码的数据
options:
- 由以下编码组成的二进制掩码:
JSON_HEX_QUOT,
JSON_HEX_TAG,
JSON_HEX_AMP,
JSON_HEX_APOS,
JSON_NUMERIC_CHECK,
JSON_PRETTY_PRINT,
JSON_UNESCAPED_SLASHES,
JSON_FORCE_OBJECT,
JSON_UNESCAPED_UNICODE.
- 返回值:
编码成功则返回一个以 JSON 形式表示的 string 或者在失败时返回 FALSE 。
更新日志:
options
参数增加常量:(PHP 5.4.0)
JSON_PRETTY_PRINT,
JSON_UNESCAPED_SLASHES,
JSON_UNESCAPED_UNICODE
options
参数增加常量:(PHP 5.3.3)
JSON_NUMERIC_CHECK
- 范例:
- Example 1
<?php
$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
echo json_encode($arr);
?>
- 输出结果:
{"a":1,"b":2,"c":3,"d":4,"e":5}
- Example 2
<?php
$a = array('<foo>',"'bar'",'"baz"','&blong&', "\xc3\xa9");
echo "Normal: ", json_encode($a), "\n";
echo "Tags: ", json_encode($a, JSON_HEX_TAG), "\n";
echo "Apos: ", json_encode($a, JSON_HEX_APOS), "\n";
echo "Quot: ", json_encode($a, JSON_HEX_QUOT), "\n";
echo "Amp: ", json_encode($a, JSON_HEX_AMP), "\n";
echo "Unicode: ", json_encode($a, JSON_UNESCAPED_UNICODE), "\n";
echo "All: ", json_encode($a, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE), "\n\n";
$b = array();
echo "Empty array output as array: ", json_encode($b), "\n";
echo "Empty array output as object: ", json_encode($b, JSON_FORCE_OBJECT), "\n\n";
$c = array(array(1,2,3));
echo "Non-associative array output as array: ", json_encode($c), "\n";
echo "Non-associative array output as object: ", json_encode($c, JSON_FORCE_OBJECT), "\n\n";
$d = array('foo' => 'bar', 'baz' => 'long');
echo "Associative array always output as object: ", json_encode($d), "\n";
echo "Associative array always output as object: ", json_encode($d, JSON_FORCE_OBJECT), "\n\n";
?>
- 以上代码输出:
Normal: ["<foo>","'bar'","\"baz\"","&blong&","\u00e9"]
Tags: ["\u003Cfoo\u003E","'bar'","\"baz\"","&blong&","\u00e9"]
Apos: ["<foo>","\u0027bar\u0027","\"baz\"","&blong&","\u00e9"]
Quot: ["<foo>","'bar'","\u0022baz\u0022","&blong&","\u00e9"]
Amp: ["<foo>","'bar'","\"baz\"","\u0026blong\u0026","\u00e9"]
Unicode: ["<foo>","'bar'","\"baz\"","&blong&","é"]
All: ["\u003Cfoo\u003E","\u0027bar\u0027","\u0022baz\u0022","\u0026blong\u0026","é"]
Empty array output as array: []
Empty array output as object: {}
Non-associative array output as array: [[1,2,3]]
Non-associative array output as object: {"0":{"0":1,"1":2,"2":3}}
Associative array always output as object: {"foo":"bar","baz":"long"}
Associative array always output as object: {"foo":"bar","baz":"long"}
- Example 3
<?php
echo "连续数组".PHP_EOL;
$sequential = array("foo", "bar", "baz", "blong");
var_dump(
$sequential,
json_encode($sequential)
);
echo PHP_EOL."非连续数组".PHP_EOL;
$nonsequential = array(1=>"foo", 2=>"bar", 3=>"baz", 4=>"blong");
var_dump(
$nonsequential,
json_encode($nonsequential)
);
echo PHP_EOL."删除一个连续数组值的方式产生的非连续数组".PHP_EOL;
unset($sequential[1]);
var_dump(
$sequential,
json_encode($sequential)
);
?>
- 结果输出:
连续数组
array(4) {
[0] => string(3) "foo"
[1] => string(3) "bar"
[2] => string(3) "baz"
[3] => string(5) "blong"
}
string(27) "["foo","bar","baz","blong"]"
非连续数组
array(4) {
[1] => string(3) "foo"
[2] => string(3) "bar"
[3] => string(3) "baz"
[4] => string(5) "blong"
}
string(43) "{"1":"foo","2":"bar","3":"baz","4":"blong"}"
删除一个连续数组值的方式产生的非连续数组
array(3) {
[0] => string(3) "foo"
[2] => string(3) "baz"
[3] => string(5) "blong"
}
string(33) "{"0":"foo","2":"baz","3":"blong"}"
- Example 4:
$obj->Name= 'a1';$obj->Number ='123';
$obj->Contno= '000';
echo json_encode($obj);
- 输出结果为:
{
"Name":"a1",
"Number":"123",
"Contno":"000"
}
- Big-man总结可以看出
json_encode()
和json_decode()
是编译和反编译过程,注意json只接受utf-8编码的字符,所以json_encode()
的参数必须是utf-8编码,否则会得到空字符或者null。
$step = trim(S::getGP('step'));
- PHP之
trim()
函数方法:(PHP 4, PHP 5, PHP 7)
; trim
— 去除字符串首尾处的空白字符(或者其他字符);大家都知道Big-man是一个不了解清楚方法,不拿出来说论的人,所以Big-man今天要来写一下trim
方法。说明:
string trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] )
- 此函数返回字符串
str
去除首尾空白字符后的结果。如果不指定第二个参数,trim()
将去除这些字符:
" " (ASCII 32 (0x20))
,普通空格符。"\t" (ASCII 9 (0x09))
,制表符。"\n" (ASCII 10 (0x0A))
,换行符。"\r" (ASCII 13 (0x0D))
,回车符。"\0" (ASCII 0 (0x00))
,空字节符。"\x0B" (ASCII 11 (0x0B))
,垂直制表符。
这些字符大家如果不熟悉的话可以ASCII在线对照表上进行查询和总结。
参数说明:
str
: 待处理的字符串;character_mask
: 可选参数,过滤字符也可由character_mask
参数指定。一般要列出所有希望过滤的字符,也可以使用“..”列出一个字符的范围。返回值说明:
过滤后的字符串。
Example 1:
<?php
$text = "\t\tThese are a few words :) ... ";
$binary = "\x09Example string\x0A";
$hello = "Hello World";
var_dump($text, $binary, $hello);
print "\n";
$trimmed = trim($text);
var_dump($trimmed);
$trimmed = trim($text, " \t.");
var_dump($trimmed);
$trimmed = trim($hello, "Hdle");
var_dump($trimmed);
// 清除 $binary 首位的 ASCII 控制字符
// (包括 0-31)
$clean = trim($binary, "\x00..\x1F");
var_dump($clean);
?>
- 输出结果:
string(32) " These are a few words :) ... "
string(16) " Example string
"
string(11) "Hello World"
string(28) "These are a few words :) ..."
string(24) "These are a few words :)"
string(5) "o Wor"
string(14) "Example string"
- Example 2:
<?php
function trim_value(&$value)
{
$value = trim($value);
}
$fruit = array('apple','banana ', ' cranberry ');
var_dump($fruit);
array_walk($fruit, 'trim_value');
var_dump($fruit);
?>
- 输出结果:
array(3) {
[0]=>
string(5) "apple"
[1]=>
string(7) "banana "
[2]=>
string(11) " cranberry "
}
array(3) {
[0]=>
string(5) "apple"
[1]=>
string(6) "banana"
[2]=>
string(9) "cranberry"
}
- Big-man在这里采用的是PHPAPI文档上的范例,因为觉得这个范例实现和输出的结果都是比较不错的。所以可以查看这个实例继续扩展就可以了。
$id = (int) S::getGP('id');
- Big-man刚才才了解到, PHP的数据转换属于强制转换,允许转换的PHP类型数据有:
(int)
、(integer)
:转换成整形(float)
、(double)
、(real)
:转换成浮点型(string)
:转换成字符串(bool)
、(boolean)
:转换成布尔类型(array)
:转换成数组(object)
:转换成对象PHP数据类型有三种转换方式:
- 在要转换的变量之前加上用括号括起来的目标类型
- 使用3个具体类型的转换函数,
intval()
、floatval
、strval
- 使用通用类型转换函数
settype(mixed var, string type)
Example 1:
(int) (bool) (float) (string) (array) (object)
<?php
$num1=3.14;
$num2=(int)$num1;
var_dump($num1); //输出float(3.14)
var_dump($num2); //输出int(3)
?>
- Example 2:
intval() floatval() strval()
<?php
$str="123.9abc";
$int=intval($str); //转换后数值:123
$float=floatval($str); //转换后数值:123.9
$str=strval($float); //转换后字符串:"123.9"
?>
- Example 3:
settype();
<?php
$num4=12.8;
$flg=settype($num4,"int");
var_dump($flg); //输出bool(true)
var_dump($num4); //输出int(12)
?>
$category_single_arr = get_single_category($g_sub_company_id);
这里刚接触
PHP
的, 像Big-man这样的小白也是一头的雾水,但是不要忘记了前面还存在一个require R_P . 'lib\backage_category_fun.php';
当然方法也是写在这个外部引用的文件里面的,至于require
的作用请参看以上的require
模块。get_single_category();
函数:
/* get shop single category from db */
function get_single_category( $company_id, $depth = 3, $order_by = ' order by sortid asc, id asc '){
global $db;
$company_id = (int)$company_id;
$depth = (int)$depth + 1;
$where = ' where companyid = ' . $company_id .' and depth < ' . (int)$depth;
$sql = 'select * from w_category ' . $where . $order_by;
$category = $db->query( $sql );
$single = array();
while($li = $db->fetch_array($category)){
$li['categoryname'] = pinyin( $li['categoryname']). $li['categoryname'];
$single[] = $li;
}
//while( ($li = $db->fetch_array($category)) && ($single[] = $li) );
return order_by_parent($single);
}
- 分析
get_single_category();
函数; - 从字面理解,这是获取单个种类的方法;
大家可以看到在
get_single_category();
中分别写了三个参数,但是为什么Big-man传过去的时候就只是传递一个参数了,先不要激动啊,且听Big-man慢慢地分析;传递参数分析:
$company_id
:公司的主键值,也就是传递过来标识是那家公司的标识值;$depth = 3
: 这个值在函数的过程中已经定义了,大家可以重新传递一个值过来将其覆盖,但是你也可以不用传递这个值过来,那这个值的作用是什么了?请看$where = ' where companyid = ' . $company_id .' and depth < ' . (int)$depth;
以及$sql = 'select * from w_category ' . $where . $order_by;
目的是为了组合成一个sql
语句, 进行数据的操作,通过这样的操作我们也就可以查询到数据库中不同的数据,用同一段代码,这就是其神奇之处。$order_by = ' order by sortid asc, id asc '
: 这个参数也是sql
语句当中的一部分,首先asc
是升序,那么desc
就是降序,大家可能又会非常的郁闷了,排序把为什么要加两个字段了?一般都是对主键值id
进行 降序 和 升序 的处理就可以了,这里Big-man进行了查询在自己不肯定的情况下,在这种需要排序的查询中需要新增一个字段来解决排序查询慢的问题:- SQL1:
CREATE TABLE [dbo].[CMPP_SendCentre] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[SendType] [varchar] (10) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[SendDate] [datetime] NOT NULL ,
[Port] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[Service_ID] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[FeeType] [varchar] (2) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[FeeCode] [varchar] (6) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[Msg_Content] [varchar] (1024) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[SendCount] [int] NOT NULL ,
[SucceedCount] [int] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[CMPP_SendCentreMo] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[SendCentreID] [int] NOT NULL ,
[Mo] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[Stat] [varchar] (10) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO
CMPP_SendCentreMo.SendCentreID
与CMPP_SendCentre.ID
成外建关系。- 于是建立了一个视图:
CREATE VIEW dbo.ViewCMPP_SendCentreMo
AS
SELECT
dbo.CMPP_SendCentreMo.id,
dbo.CMPP_SendCentreMo.SendCentreID,
dbo.CMPP_SendCentreMo.Mo,
dbo.CMPP_SendCentreMo.Stat,
dbo.CMPP_SendCentre.SendType,
dbo.CMPP_SendCentre.SendDate,
dbo.CMPP_SendCentre.Port,
dbo.CMPP_SendCentre.Service_ID,
case dbo.CMPP_SendCentre.FeeType when '01' then '免费' when '02' then '点播' else '包月' end as FeeType,
cast(dbo.CMPP_SendCentre.FeeCode as smallint) as FeeCode,
dbo.CMPP_SendCentre.Msg_Content
FROM dbo.CMPP_SendCentre INNER JOIN
dbo.CMPP_SendCentreMo ON
dbo.CMPP_SendCentre.id = dbo.CMPP_SendCentreMo.SendCentreID
- 那这样一开始的查询语句,比如像Big-man这样的就会直接写上:
select top 6*from [ViewCMPP_SendCentreMo]
where SendType = '扣费'
order by id desc
这样的查询语句进行处理。
但是有的大神就会思考这样的查询处理语句花费的时间怎么那么多了?像Big-man这样的大白倒是没有想到这样的深度,因为在本地所写的项目所需要的数据也不是很多,更不用说关联度了。经过大神们的仔细排查终于发现:order by id desc/asc的查询是一行一行的找数据,所以非常的慢。于是把
sql
语句该为:
select top 6*from [ViewCMPP_SendCentreMo]
where SendType = '扣费'
order by SendCentreID desc, id desc
- 这样的查询就相当的快了。详情请参考[sql查询].(https://yq.aliyun.com/ziliao/136110)。
- Big-man在脑海中想象出了一种解释的形式,有可能大家会对于这个解释存在些许迷茫,Big-man想到了一个例子:
- 比如说军训: 如果是教官给军训的同学排序的话,一个教官肯定是先点名(遍历一下人数)查看人是否到期,然后才开始进行由高到低进行排序; 但是如果两个教官处理的话就会快很多的,一个教官负责清点人数而另一个教官负责排序,这样且不是更方便些,但是如果再增加一个教官了?这时候大家可以马上想到增加这个教官干嘛啊?在旁边指点吗?根本没有这个必要的,所以说多了反而会起到不好的效果,所以这也就是上面的一个记录遍历的过程,一个记录排序的过程。
Jackdan9 Thinking