学习PHP中的URL相关操作函数

学习PHP中的URL相关操作函数

在日常的业务开发过程中,我们经常会有处理 URL 链接的需求,所以今天学习的函数其实都是大家经常会使用的一些函数。在之前的工作过程中,其实我对这些函数都只是有一个模糊的概念,知道,但是真要用得时候还是要看下文档才能确定真正要使用的是哪一个函数。因此,今天我们就当做是一次复习练习,主要是区分和搞清楚每个函数真正的用处。

编码操作函数

首先来看就是 URL 编码相关的函数。有些浏览器在我们复制粘贴一个网址后,就会自动地对网址进行 URL 编码,也就是有很多百分号那种形式的。在 PHP 中,自然也有对应的编解码函数。

$url = "https://www.zyblog.net?opt=dev&mail=zyblog@net.net&comments=aaa bbb ccc %dfg &==*() cdg&value=“中文也有呀,还有中文符号!!”";

echo $url, PHP_EOL;
// https://www.zyblog.net?opt=dev&mail=zyblog@net.net&comments=aaa bbb ccc %dfg &==*() cdg&value=“中文也有呀,还有中文符号!!”

$enurl = urlencode($url);
echo $enurl, PHP_EOL;
// https%3A%2F%2Fwww.zyblog.net%3Fopt%3Ddev%26mail%3Dzyblog%40net.net%26comments%3Daaa+bbb+ccc+%25dfg+%26%3D%3D%2A%28%29+cdg%26value%3D%E2%80%9C%E4%B8%AD%E6%96%87%E4%B9%9F%E6%9C%89%E5%91%80%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%AD%E6%96%87%E7%AC%A6%E5%8F%B7%EF%BC%81%EF%BC%81%E2%80%9D

echo urldecode($enurl), PHP_EOL;
// https://www.zyblog.net?opt=dev&mail=zyblog@net.net&comments=aaa bbb ccc %dfg &==*() cdg&value=“中文也有呀,还有中文符号!!”

这两个函数估计是大家使用最多的函数了。urlencode() 就是用于 URL 的编码操作,可以看到,我们准备好的链接已经被编码成了包含各种百分号的内容。特别是对于中文字符来说,如果是 GET 方式这种在链接中的中文参数,编码之后的内容就会让链接变得非常长。urldecode() 则是相对应的解码功能的函数,可以把编码过的链接解码回原始的状态。

$rawenurl = rawurlencode($enurl);
echo $rawenurl, PHP_EOL;
// https%253A%252F%252Fwww.zyblog.net%253Fopt%253Ddev%2526mail%253Dzyblog%2540net.net%2526comments%253Daaa%2Bbbb%2Bccc%2B%2525dfg%2B%2526%253D%253D%252A%2528%2529%2Bcdg%2526value%253D%25E2%2580%259C%25E4%25B8%25AD%25E6%2596%2587%25E4%25B9%259F%25E6%259C%2589%25E5%2591%2580%25EF%25BC%258C%25E8%25BF%2598%25E6%259C%2589%25E4%25B8%25AD%25E6%2596%2587%25E7%25AC%25A6%25E5%258F%25B7%25EF%25BC%2581%25EF%25BC%2581%25E2%2580%259D

echo rawurldecode($rawenurl), PHP_EOL;
// https%3A%2F%2Fwww.zyblog.net%3Fopt%3Ddev%26mail%3Dzyblog%40net.net%26comments%3Daaa+bbb+ccc+%25dfg+%26%3D%3D%2A%28%29+cdg%26value%3D%E2%80%9C%E4%B8%AD%E6%96%87%E4%B9%9F%E6%9C%89%E5%91%80%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%AD%E6%96%87%E7%AC%A6%E5%8F%B7%EF%BC%81%EF%BC%81%E2%80%9D

echo rawurlencode($url), PHP_EOL;
// https%3A%2F%2Fwww.zyblog.net%3Fopt%3Ddev%26mail%3Dzyblog%40net.net%26comments%3Daaa%20bbb%20ccc%20%25dfg%20%26%3D%3D%2A%28%29%20cdg%26value%3D%E2%80%9C%E4%B8%AD%E6%96%87%E4%B9%9F%E6%9C%89%E5%91%80%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%AD%E6%96%87%E7%AC%A6%E5%8F%B7%EF%BC%81%EF%BC%81%E2%80%9D

echo rawurldecode($enurl), PHP_EOL;
// https://www.zyblog.net?opt=dev&mail=zyblog@net.net&comments=aaa+bbb+ccc+%dfg+&==*()+cdg&value=“中文也有呀,还有中文符号!!”

紧接着我们看到的是 rawurlencode() 和 rawurldecode() 。很多小伙伴会搞不清楚它们和普通的 urlencode() 、 urldecode() 有什么区别。其实,它们的区别主要体现在一些特殊的字符上,比如说空格。在 urlencode() 中,空格被编码为 + 号,而在 urlrawencode() 中,空格是 %20 。在我们的第三段测试代码中就可以看出来。

前两段测试代码是针对前面已经编码过的 \$enurl 进行的操作。第三段测试代码是对原始的 $url 进行的编码。这两个函数是实现了 RFC3986 规范的函数。而 urlencode() 则是由于历史原因而保留了一些类似于空格转换成 + 号这样的特殊情况。

最后我们再看两个非常简单的 Base64 相关的编解码函数。

$base64url = base64_encode($enurl);
echo $base64url, PHP_EOL;
// aHR0cHMlM0ElMkYlMkZ3d3cuenlibG9nLm5ldCUzRm9wdCUzRGRldiUyNm1haWwlM0R6eWJsb2clNDBuZXQubmV0JTI2Y29tbWVudHMlM0RhYWErYmJiK2NjYyslMjVkZmcrJTI2JTNEJTNEJTJBJTI4JTI5K2NkZyUyNnZhbHVlJTNEJUUyJTgwJTlDJUU0JUI4JUFEJUU2JTk2JTg3JUU0JUI5JTlGJUU2JTlDJTg5JUU1JTkxJTgwJUVGJUJDJThDJUU4JUJGJTk4JUU2JTlDJTg5JUU0JUI4JUFEJUU2JTk2JTg3JUU3JUFDJUE2JUU1JThGJUI3JUVGJUJDJTgxJUVGJUJDJTgxJUUyJTgwJTlE

echo base64_decode($base64url), PHP_EOL;
// https%3A%2F%2Fwww.zyblog.net%3Fopt%3Ddev%26mail%3Dzyblog%40net.net%26comments%3Daaa+bbb+ccc+%25dfg+%26%3D%3D%2A%28%29+cdg%26value%3D%E2%80%9C%E4%B8%AD%E6%96%87%E4%B9%9F%E6%9C%89%E5%91%80%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%AD%E6%96%87%E7%AC%A6%E5%8F%B7%EF%BC%81%EF%BC%81%E2%80%9D

其实 Base64 最大的用处不是体现在对这种普通的字符串的编码上,而是体现于 二进制 字符串在编码后传输的作用上。这个想必用过的同学自然心里有数。主要是对于接口开发来说,如果我们使用 Base64 对数据进行编码,一是没有什么加密的效果,二是还有可能增大数据的长度,所以除非有特殊需求,否则普通传输中真的没有太大的必要来对数据进行 Base64 的编码。

URL 解析操作

除了对于 URL 链接中的字符进行编解码之外,解析链接参数也是我们经常会使用的功能。比如:

$urls = parse_url($url);
var_dump($urls);
// array(3) {
//     ["scheme"]=>
//     string(5) "https"
//     ["host"]=>
//     string(14) "www.zyblog.net"
//     ["query"]=>
//     string(119) "opt=dev&mail=zyblog@net.net&comments=aaa bbb ccc %dfg &==*() cdg&value=“中文也有呀,还有中文符号!!”"
//   }

通过 parse_url() 这个函数,我们就可以将链接的各个部分拆解开来。

$parseTestUrl = 'http://username:password@hostname/path?arg=value#anchor';

print_r(parse_url($parseTestUrl));
// Array
// (
//     [scheme] => http
//     [host] => hostname
//     [user] => username
//     [pass] => password
//     [path] => /path
//     [query] => arg=value
//     [fragment] => anchor
// )

上面这个测试链接更加地标准规范,我们也可以看到 parse_url() 可以拆解出 协议、地址、用户名、密码、路径、查询语句、片断 这些内容,这些也是构成一个 URL 链接的规范标准。我们也可以指定我们需要的内容。

echo parse_url($parseTestUrl, PHP_URL_PATH); // /path

像这样添加第二个参数,就可以只获取我们需要的部分内容。当然,对于整个 URL 链接来说,我们最关心的其实是 query 这部分的内容,能不能将它们再拆解出来呢?就像 $_GET 一样获得全部的查询数据结果。

$querys = [];
parse_str($urls['query'], $querys);
var_dump($querys);
// array(4) {
//     ["opt"]=>
//     string(3) "dev"
//     ["mail"]=>
//     string(14) "zyblog@net.net"
//     ["comments"]=>
//     string(15) "aaa bbb ccc �g "
//     ["value"]=>
//     string(48) "“中文也有呀,还有中文符号!!”"
//   }

parse_str() 这个函数就是解析这种 URL 链接查询语句的函数。需要注意的是,这个函数的第二个参数是可选的,如果不使用一个变量来接收这个函数所解析出来的结果的话,那么所有解析的结果将直接转换成变量形式。说得可能有点晕,直接看看代码。

parse_str($urls['query']);
echo $value, PHP_EOL; // “中文也有呀,还有中文符号!!”

这下就看明白了吧。为了防止变量污染问题的出现,最好还是有第二个参数来让解析的结果存储到我们指定的地方。最后,我们再看看如何将数组组合成一段 URL 查询语句。

echo http_build_query($querys), PHP_EOL;
// opt=dev&mail=zyblog%40net.net&comments=aaa+bbb+ccc+%DFg+&value=%E2%80%9C%E4%B8%AD%E6%96%87%E4%B9%9F%E6%9C%89%E5%91%80%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%AD%E6%96%87%E7%AC%A6%E5%8F%B7%EF%BC%81%EF%BC%81%E2%80%9D

echo http_build_query($querys, null, '$||$', PHP_QUERY_RFC3986), PHP_EOL;
// opt=dev$||$mail=zyblog%40net.net$||$comments=aaa%20bbb%20ccc%20%DFg%20$||$value=%E2%80%9C%E4%B8%AD%E6%96%87%E4%B9%9F%E6%9C%89%E5%91%80%EF%BC%8C%E8%BF%98%E6%9C%89%E4%B8%AD%E6%96%87%E7%AC%A6%E5%8F%B7%EF%BC%81%EF%BC%81%E2%80%9D

http_build_query() 其实只要做过对接外部接口开发的同学都不会陌生。因为它太方便了。不过需要注意的是,这个函数自带地就会将数据进行 rawurlencode() 编码。另外,它还有几个可选参数的,比如说我们第二段测试代码中修改了连接符号,将原本的 & 符号替换成我们自定义的符号来进行 URL 查询语句的拼接。

解析文件或远程地址的响应头及 meta 信息

对于远程文件的请求来说,响应头信息也是非常重要的内容。其实在 URL 相关的组件中也有直接获取响应头的函数。

$url = 'https://www.sina.com.cn';

print_r(get_headers($url));
// Array
// (
//     [0] => HTTP/1.1 200 OK
//     [1] => Server: nginx
//     [2] => Date: Mon, 25 Jan 2021 02:08:35 GMT
//     [3] => Content-Type: text/html
//     [4] => Content-Length: 530418
//     [5] => Connection: close
//     [6] => Vary: Accept-Encoding
//     [7] => ETag: "600e278a-7c65e"V=5965C31
//     [8] => X-Powered-By: shci_v1.13
//     [9] => Expires: Mon, 25 Jan 2021 02:09:12 GMT
//     [10] => Cache-Control: max-age=60
//     [11] => X-Via-SSL: ssl.22.sinag1.qxg.lb.sinanode.com
//     [12] => Edge-Copy-Time: 1611540513080
//     [13] => Age: 24
//     [14] => Via: https/1.1 cmcc.guangzhou.union.82 (ApacheTrafficServer/6.2.1 [cRs f ]), https/1.1 cmcc.jiangxi.union.175 (ApacheTrafficServer/6.2.1 [cRs f ])
//     [15] => X-Via-Edge: 1611540515462770a166fee55a97524d289c7
//     [16] => X-Cache: HIT.175
//     [17] => X-Via-CDN: f=edge,s=cmcc.jiangxi.union.166.nb.sinaedge.com,c=111.22.10.119;f=edge,s=cmcc.jiangxi.union.168.nb.sinaedge.com,c=117.169.85.166;f=Edge,s=cmcc.jiangxi.union.175,c=117.169.85.168
// )

print_r(get_headers($url, 1));
// Array
// (
//     [0] => HTTP/1.1 200 OK
//     [Server] => nginx
//     [Date] => Mon, 25 Jan 2021 02:08:35 GMT
//     [Content-Type] => text/html
//     [Content-Length] => 530418
//     [Connection] => close
//     [Vary] => Accept-Encoding
//     [ETag] => "600e278a-7c65e"V=5965C31
//     [X-Powered-By] => shci_v1.13
//     [Expires] => Mon, 25 Jan 2021 02:09:12 GMT
//     [Cache-Control] => max-age=60
//     [X-Via-SSL] => ssl.22.sinag1.qxg.lb.sinanode.com
//     [Edge-Copy-Time] => 1611540513080
//     [Age] => 24
//     [Via] => https/1.1 cmcc.guangzhou.union.82 (ApacheTrafficServer/6.2.1 [cRs f ]), https/1.1 cmcc.jiangxi.union.175 (ApacheTrafficServer/6.2.1 [cRs f ])
//     [X-Via-Edge] => 1611540515593770a166fee55a97568f1a9d6
//     [X-Cache] => HIT.175
//     [X-Via-CDN] => f=edge,s=cmcc.jiangxi.union.165.nb.sinaedge.com,c=111.22.10.119;f=edge,s=cmcc.jiangxi.union.175.nb.sinaedge.com,c=117.169.85.165;f=Edge,s=cmcc.jiangxi.union.175,c=117.169.85.175
// )

通过 get_headers() 函数就可以直接拿到目标地址服务器返回的响应头信息。它的第二个参数可以以键值下标的方式返回数据。除了响应头之外,我们还可以拿到网站的所有 meta 标签里的内容。

var_dump(get_meta_tags($url));
// array(11) {
//     ["keywords"]=>
//     string(65) "新浪,新浪网,SINA,sina,sina.com.cn,新浪首页,门户,资讯"
//     ["description"]=>
//     string(331) "新浪网为全球用户24小时提供全面及时的中文资讯,内容覆盖国内外突发新闻事件、体坛赛事、娱乐时尚、产业资讯、实用信息等,设有新闻、体育、娱乐、财经、科技、房产、汽车等30多个内容频道,同时开设博客、视频、论坛等自由互动交流空间。"
//     ["referrer"]=>
//     string(6) "always"
//     ["stencil"]=>
//     string(10) "PGLS000022"
//     ["publishid"]=>
//     string(8) "30,131,1"
//     ["verify-v1"]=>
//     string(44) "6HtwmypggdgP1NLw7NOuQBI2TW8+CfkYCoyeB8IDbn8="
//     ["application-name"]=>
//     string(12) "新浪首页"
//     ["msapplication-tileimage"]=>
//     string(42) "//i1.sinaimg.cn/dy/deco/2013/0312/logo.png"
//     ["msapplication-tilecolor"]=>
//     string(7) "#ffbf27"
//     ["baidu_ssp_verify"]=>
//     string(32) "c0e9f36397049594fb9ac93a6316c65b"
//     ["sudameta"]=>
//     string(20) "dataid:wpcomos:96318"
//   }

这个函数不仅是对远程的链接网站有用,而且还可以直接查看一个本地的静态文件中的所有 meta 标签的内容,我们只需要将参数的远程链接换成本地文件的路径就可以了,大家可以自己尝试一下。

总结

今天的内容还是比较简单的,主要这些函数大家在日常的工作中会经常用到。不过有些参数的使用情况可能许多朋友并不清楚,比如 parse_str() 函数的第二个参数的问题。所以就像开头说的,这篇文章就是个复习巩固,另外也起到加深理解的作用,深入学习之后融汇贯通实际运用就能掌握得更加手到擒来。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/2021/01/source/9.学习PHP中的URL相关操作函数.php

参考文档:

https://www.php.net/manual/zh/book.url.php

(0)

相关推荐

  • PHP中命名空间是怎样的存在(一)?

    命名空间其实早在PHP5.3就已经出现了.不过大部分同学可能在各种框架的使用中才会接触到命名空间的内容,当然,现代化的开发也都离不开这些能够快速产出的框架.这次我们不从框架的角度,仅从简单的代码角度来 ...

  • 标梵学习PHP的压缩工具扩展包

    PHP的zip压缩工具扩展包学习 总算到了 PHP 的拿手好戏上场了,前面我们学习过 Bzip2 . LZF . Phar 和 rar 这些压缩相关扩展在 PHP 中的使用,不过它们要么是太冷门,要么 ...

  • 关于php的ini文件相关操作函数浅析

    关于php的ini文件相关操作函数浅析 在小公司,特别是创业型公司,整个服务器的搭建一般也是我们 PHP 开发工程师的职责之一.其中,最主要的一项就是要配置好服务器的 php.ini 文件.一些参数会 ...

  • [PHP小课堂]关于php的ini文件相关操作函数浅析

    [PHP小课堂]关于php的ini文件相关操作函数浅析 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[xiaoyuezigonggong/149844827]免费得PHP.项目管理学 ...

  • 一起学习PHP中断言函数的使用

    一起学习PHP中断言函数的使用 原来一直以为断言相关的函数是 PHPUnit 这些单元测试组件提供的,在阅读手册后才发现,这个 assert() 断言函数是 PHP 本身就自带的一个函数.也就是说,我 ...

  • PHP中的PDO对象操作学习(一)初始化PDO及原始SQL语句操作

    PHP中的PDO对象操作学习(一)初始化PDO及原始SQL语句操作 PDO 已经是 PHP 中操作数据库事实上的标准.包括现在的框架和各种类库,都是以 PDO 作为数据库的连接方式.基本上只有我们自己 ...

  • PHP中的MySQLi扩展学习(五)MySQLI_STMT对象操作

    PHP中的MySQLi扩展学习(五)MySQLI_STMT对象操作 就像 PDO 中的 PDO_Statment 对象一样,MySQLI_STMT 对象也是一个预处理语句所形成的对象,专门用来操作 M ...

  • PHP中的MySQLi扩展学习(六)MySQLI_result对象操作

    PHP中的MySQLi扩展学习(六)MySQLI_result对象操作 在之前的文章中,我们就已经接触过 MYSQLI_result 相关的内容.它的作用其实就是一个查询的结果集.不过在 PDO 中, ...

  • 学习PHP中的目录操作

    学习PHP中的目录操作 对于编程语言来说,文件和目录的操作是其最最基础的功能.就像我们日常中最常见的图片上传.文件上传之类的功能,都需要文件和目录操作的支持.今天我们先来简单地学习一下 PHP 中关于 ...

  • [PHP小课堂]一起学习PHP中断言函数的使用

    [PHP小课堂]一起学习PHP中断言函数的使用 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[xiaoyuezigonggong/149844827]免费得PHP.项目管理学习资料 ...

  • 学习PHP中好玩的Gmagick图像操作扩展的使用

    学习PHP中好玩的Gmagick图像操作扩展的使用 在 PHP 的图像处理领域,要说最出名的 GD 库为什么好,那就是因为它不需要额外安装的别的什么图像处理工具,而且是随 PHP 源码一起发布的,只需 ...