PHP的基础知识(三)
一、url编码
1、PHP中,我们经常用到urlencode()和urldecode()这一对针对url编码和解码的函数
urlencode的作用:
1)将字符串编码并将其用于 URL 的请求部分,同时它还便于将变量传递给下一页。
2)经常用来编码URL中的中文字符串,避免在URL调用中出错。
返回值:返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)
2、其实,还有另外一对函数rawurlencode()和rawurldecode()和上面讲的函数作用是很相似的
urlencode和rawurlencode的区别主要在于对空格的处理:
1)urlencode 将空格则编码为加号(+)
2)rawurlencode 将空格则编码为加号(%20)
3、urlencode和rawurlencode这两者在使用中如何选择
1)如果与其他系统的互操作性很重要,使用rawurlencode
2)一个例外是遗留系统,它希望查询字符串遵循编码为+而不是%20的空格的形式编码样式,在这种情况下,使用urlencode
总结: 一般情况下,建议使用rawurlencode()来对url进行编码
二、比较两个字符串
如果要比较两个字符串是否相等,一般我们首先想到的是使用“===”来实现,其实这里我们还可以用strcmp()函数来实现
我们来看下“===","==",strcmp(),strncmp()的区别
1、“===”和“==”的区别
“===”强调用于比较的两个对象的值和类型都要相同,而“==”只要求值相同就可以了。之所以说是两个对象,是因为他们不一定全部为字符串,也能为整型等等
2、strcmp()和strncmp()的区别
1)strcmp(string1,string2)是二进制安全的,用于区分大小写 (即大小写敏感)的字符串比较。
2)strncmp(string1,string2,length):该函数与strcmp()类似,也是二进制安全的,不同的是,通过 strncmp() ,可以指定每个字符串用于比较的字符数。
刚才提到strncmp和strncmp都是二进制安全的函数,那自然就有二进制不安全的函数,比如strcoll()函数就是二进制不安全的。
那么“二进制安全”是什么? 先看一段代码:
1 <?php 2 $string1 = "Hello"; 3 $string2 = "Hello Hello"; 4 echo strcoll($string1, $string2); /*返回0, 由于是非二进制安全,误判为相等 */ 5 echo PHP_EOL; 6 echo strcmp($string1, $string2); /*返回<0,不相等*/ 7 8 //输出结果 9 //0 10 //-6
这是为什么呢?PHP是基于C实现的,PHP代码都会被zend引擎编译成opcode,最终作为C语言去执行。 而对于c语言‘ ’是字符串的结束符,它读到’ ’就会默认字符读取已经结束,从而抛掉后面的字符串。
2)再来看下二进制安全的定义:
程序不会对其中的数据做任何限制、过滤、或者假设 —— 数据在写入时是什么样的, 它被读取时就是什么样。
PHP是如何实现二进制安全的?
那么,既然PHP是基于C实现的,C 字符串类型不是二进制安全的,PHP又是如何实现的呢?这就是数据结构的功劳了。
PHP的内核中,是如此定义字符串类型的,如下图:
由上图我们可以看出:val是指向字符串内存的指针,len表示该字符串的长度,无论是否遇到“ ”字符,C都按照len长度读取该字符串。
三、call_user_func 与call_user_func_array
这两个方法也是经常会用到的,先看下代码:
1 <?php 2 //大部分mvc框架,调起程序运行,都是基于这个思想 3 public function run() 4 { 5 $this->setReporting();//检测开发环境 6 $route = new Router();//解析路由 7 //加载类 8 $controllerClass = 'App\Controllers\' . $route->controller; 9 if (!class_exists($controllerClass)) { 10 die('404,Controller not Found'); 11 } 12 $controller = new $controllerClass(); 13 $action = $route->action; 14 if (!method_exists($controller, $action)) { 15 die('404,Action not Found'); 16 } 17 //执行控制器里面的方法 18 call_user_func_array(array($controller, $action), []); 19 }
1、call_user_func — 把第一个参数作为回调函数调用
2、call_user_func_array(callable $callback , array $param_arr):调用回调函数,并把一个数组参数作为回调函数的参数
call_user_func_array函数和call_user_func很相似,只不过是换了一种方式传递了参数,让参数的结构更清晰
参考代码一:
1 <?php 2 function func($a, $b){ 3 echo $a." "; 4 echo $b." "; 5 } 6 call_user_func('func', 1, 2);//第一个是函数名,后面是参数列表 7 call_user_func_array("func", array(3, 4));//区别于call_user_func只是参数传递的方式不同 8 //输出结果 9 //1 10 //2 11 //3 12 //4
参考代码二:
1 <?php 2 3 class A { 4 function b($b) { 5 echo $b." "; 6 } 7 8 static function c($c) { 9 echo $c." "; 10 } 11 } 12 13 //在 php5.3 之后如果调用类的实例方法,必须通过类的实例调用,如下 14 $a = new A; 15 call_user_func(array($a, "b"), "b"); 16 // 类的静态方法是可以通过如下两种方式调用的 17 call_user_func(array("A", "c"), "c"); 18 call_user_func("A::c", "c"); 19 20 //call_user_func_array 调用类的静态函数和实例函数 21 call_user_func_array(array($a, "b"), array("bb")); 22 call_user_func_array("A::c", array("cc"));
参考链接:
http://wuxinjie.github.io/php-02/
https://www.jianshu.com/p/07c3f1e4c309