PHP的基础知识(三)

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 = "HelloHello";
 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

原文地址:https://www.cnblogs.com/hld123/p/14268877.html