如何仅 url 编码 url 的一部分?
How to urlencode part of the url only?
我有一个 WordPress 网站,有两个自定义 post 类型,book
和 article
。
由于设计需要,我想为 post 特色图片的 return
和 url
创建简码。我无法使用 built-in 函数 get_the_post_thumbnail_url()
,因为我将图像缓存在 wordpress.com
网络上(使用 Jetpack
),而此函数 returns 缓存 url
,这不符合我的设计要求。
我创建了以下简码:
function wp_featured_image_url( $atts ) {
global $post;
$url = get_the_post_thumbnail_url($post->ID);
if (is_singular($post_types = 'book')) {
if ( has_post_thumbnail() ) {
return $url;
}
else {
echo 'https://example.com/wp-content/uploads/year/month/generic-featured-image-for-books.png';
}
}
else
if (is_singular($post_types = 'article')) {
if ( has_post_thumbnail() ) {
return $url;
}
else {
echo 'https://example.com/wp-content/uploads/year/month/generic-featured-image-for-articles.png';
}
}
}
add_shortcode( 'featured_image_url', 'wp_featured_image_url' );
它工作正常,除了图像文件标题是阿拉伯语 (UTF-8),所以这个函数将 return url
像这样:
https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg
我只想要return图像文件名的urlencode
。但是,如果我将 return $url;
更改为 return urlencode($url);
或 return rawurlencode($url);
它将 return 整个 url 为 urlencode
:
https%3A%2F%2Fexample.com%2Fwp-content%2Fuploads%2F2019%2F10%2F%D9%83%D9%84%D8%A7%D9%85-%D8%B9%D8%B1%D8%A8%D9%8A-%D9%83%D8%AA%D9%8A%D8%B1.jpg
我希望能够调整函数,使 url
的第一部分保持不变,只有图像文件名得到 urlencode
,像这样:
https://example.com/wp-content/uploads/2019/10/%D9%83%D9%84%D8%A7%D9%85-%D8%B9%D8%B1%D8%A8%D9%8A-%D9%83%D8%AA%D9%8A%D8%B1.jpg
有人能给我指出正确的方向吗?
提前致谢。
将 url 分成两部分:第一部分 - 从开始到最后一个斜杠的所有内容,第二部分 - 其他所有直到结束都没有斜杠的内容。
然后将它们组合回去,url仅对第二部分进行编码。
<?php
function url_onlyfile_encode($url) {
if (preg_match('#^(.*/)([^/]+)$#u', $url, $res)) {
return $res[1] . urlencode($res[2]);
}
return urlencode($url);
}
// test
$s = 'https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg';
print url_onlyfile_encode($s);
// https://example.com/wp-content/uploads/2019/10/%D9%83%D9%84%D8%A7%D9%85-%D8%B9%D8%B1%D8%A8%D9%8A-%D9%83%D8%AA%D9%8A%D8%B1.jpg
已更新
如果您想要最快的代码,请尝试直接使用字符串,如下所示:
function url_onlyfile_encode($url) {
$p = strrpos($url, '/'); // Find the last slash
if ($p !== false) {
// Encode only the part after the last slash
return substr($url, 0, $p + 1) . urlencode(substr($url, $p + 1));
} else {
return urlencode($url);
}
}
我用这样的循环做了一个简单的测试:
// test string
$s = 'https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg';
$repeat_count = 1000000;
$tm = microtime(true);
for ($i = 0 ; $i < $repeat_count ; $i++) {
tested_func($s);
}
$tm = microtime(true) - $tm;
print "Time: " . round($tm * 1000) . " ms" . PHP_EOL;
完整代码为here
结果如下:
php 5.6.40:
(Blank): 17 ms
AterLux (regexp): 1907 ms
AterLux (str): 641 ms
Emanuele: 3583 ms
Petter Harsem: 1269 ms
Yeeooow: 1884 ms
(注:"Blank"是一个空循环,里面没有任何函数调用)
php 7.3.4 (x64):
(Blank): 9 ms
AterLux (regexp): 499 ms
AterLux (str): 284 ms
Emanuele: 2820 ms
Petter Harsem: 477 ms
Yeeooow: 804 ms
如您所见,strrpos
的变体在任何一种情况下都是最快的。
其中,Petter Harsem 的 explode
-> count
-> implode
显示出比正则表达式更好的结果,尽管在 php7 中差异并不大.
Yeeooow 的答案,它也使用 explode
和 count
,但使用 for
循环到 assemble 字符串返回,比 [= 上的正则表达式工作得更快61=]5 但在 php7 中显示两倍的时间。
Emanuele 的回答,涉及调用 parse_url
是最耗时的。
无论哪种方式,差异都在几微秒之内,这在现实世界中可以忽略不计。
另一种方式是粗鲁但更容易理解。
<?php
$url = "https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg";
$e = explode('/', $url); // seperate it ou using the /
$c = count($e); // get the number of elements
$ne = $c - 1; // the last element
$file = $e[$ne]; // كلام-عربي-كتير.jpg
$newURL = ''; // empty var
for ($i = 0; $i < $ne; $i++) {
$newURL .= $e[$i] . '/'; // rebuild the url
}
echo $newURL . urlencode($file); //put it all togeather again
响应将是
https://example.com/wp-content/uploads/2019/10/%D9%83%D9%84%D8%A7%D9%85-%D8%B9%D8%B1%D8%A8%D9%8A-%D9%83%D8%AA%D9%8A%D8%B1.jpg
简而言之,您需要拆分 url,将 urlencode
应用于文件名,然后将 URL 放回原处。有几种方法可以做到这一点,例如使用正则表达式来挑选最后一个 /
之后的部分。
或者另一个简单的解决方案,使用 explode
and implode
:
// Split the URL on '/'
$urlParts = explode('/', $url);
// URL encode the last part
$numParts = count($urlParts);
$urlParts[$numParts - 1] = urlencode($urlParts[$numParts - 1]);
// Put the parts back together to a string
$formattedUrl = implode('/', $urlParts);
试试这个:
$url = "https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg";
$parsed = parse_url($url);
$pathFragments = explode('/', $parsed['path']);
$fileAndExt = array_pop($pathFragments);
list($file, $ext) = explode(".", $fileAndExt);
return $parsed['scheme']."://".$parsed['host'].implode("/", $pathFragments)."/".urlencode($file).".".$ext;
我有一个 WordPress 网站,有两个自定义 post 类型,book
和 article
。
由于设计需要,我想为 post 特色图片的 return
和 url
创建简码。我无法使用 built-in 函数 get_the_post_thumbnail_url()
,因为我将图像缓存在 wordpress.com
网络上(使用 Jetpack
),而此函数 returns 缓存 url
,这不符合我的设计要求。
我创建了以下简码:
function wp_featured_image_url( $atts ) {
global $post;
$url = get_the_post_thumbnail_url($post->ID);
if (is_singular($post_types = 'book')) {
if ( has_post_thumbnail() ) {
return $url;
}
else {
echo 'https://example.com/wp-content/uploads/year/month/generic-featured-image-for-books.png';
}
}
else
if (is_singular($post_types = 'article')) {
if ( has_post_thumbnail() ) {
return $url;
}
else {
echo 'https://example.com/wp-content/uploads/year/month/generic-featured-image-for-articles.png';
}
}
}
add_shortcode( 'featured_image_url', 'wp_featured_image_url' );
它工作正常,除了图像文件标题是阿拉伯语 (UTF-8),所以这个函数将 return url
像这样:
https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg
我只想要return图像文件名的urlencode
。但是,如果我将 return $url;
更改为 return urlencode($url);
或 return rawurlencode($url);
它将 return 整个 url 为 urlencode
:
https%3A%2F%2Fexample.com%2Fwp-content%2Fuploads%2F2019%2F10%2F%D9%83%D9%84%D8%A7%D9%85-%D8%B9%D8%B1%D8%A8%D9%8A-%D9%83%D8%AA%D9%8A%D8%B1.jpg
我希望能够调整函数,使 url
的第一部分保持不变,只有图像文件名得到 urlencode
,像这样:
https://example.com/wp-content/uploads/2019/10/%D9%83%D9%84%D8%A7%D9%85-%D8%B9%D8%B1%D8%A8%D9%8A-%D9%83%D8%AA%D9%8A%D8%B1.jpg
有人能给我指出正确的方向吗? 提前致谢。
将 url 分成两部分:第一部分 - 从开始到最后一个斜杠的所有内容,第二部分 - 其他所有直到结束都没有斜杠的内容。 然后将它们组合回去,url仅对第二部分进行编码。
<?php
function url_onlyfile_encode($url) {
if (preg_match('#^(.*/)([^/]+)$#u', $url, $res)) {
return $res[1] . urlencode($res[2]);
}
return urlencode($url);
}
// test
$s = 'https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg';
print url_onlyfile_encode($s);
// https://example.com/wp-content/uploads/2019/10/%D9%83%D9%84%D8%A7%D9%85-%D8%B9%D8%B1%D8%A8%D9%8A-%D9%83%D8%AA%D9%8A%D8%B1.jpg
已更新
如果您想要最快的代码,请尝试直接使用字符串,如下所示:
function url_onlyfile_encode($url) {
$p = strrpos($url, '/'); // Find the last slash
if ($p !== false) {
// Encode only the part after the last slash
return substr($url, 0, $p + 1) . urlencode(substr($url, $p + 1));
} else {
return urlencode($url);
}
}
我用这样的循环做了一个简单的测试:
// test string
$s = 'https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg';
$repeat_count = 1000000;
$tm = microtime(true);
for ($i = 0 ; $i < $repeat_count ; $i++) {
tested_func($s);
}
$tm = microtime(true) - $tm;
print "Time: " . round($tm * 1000) . " ms" . PHP_EOL;
完整代码为here
结果如下:
php 5.6.40:
(Blank): 17 ms
AterLux (regexp): 1907 ms
AterLux (str): 641 ms
Emanuele: 3583 ms
Petter Harsem: 1269 ms
Yeeooow: 1884 ms
(注:"Blank"是一个空循环,里面没有任何函数调用)
php 7.3.4 (x64):
(Blank): 9 ms
AterLux (regexp): 499 ms
AterLux (str): 284 ms
Emanuele: 2820 ms
Petter Harsem: 477 ms
Yeeooow: 804 ms
如您所见,strrpos
的变体在任何一种情况下都是最快的。
其中,Petter Harsem 的 explode
-> count
-> implode
显示出比正则表达式更好的结果,尽管在 php7 中差异并不大.
Yeeooow 的答案,它也使用 explode
和 count
,但使用 for
循环到 assemble 字符串返回,比 [= 上的正则表达式工作得更快61=]5 但在 php7 中显示两倍的时间。
Emanuele 的回答,涉及调用 parse_url
是最耗时的。
无论哪种方式,差异都在几微秒之内,这在现实世界中可以忽略不计。
另一种方式是粗鲁但更容易理解。
<?php
$url = "https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg";
$e = explode('/', $url); // seperate it ou using the /
$c = count($e); // get the number of elements
$ne = $c - 1; // the last element
$file = $e[$ne]; // كلام-عربي-كتير.jpg
$newURL = ''; // empty var
for ($i = 0; $i < $ne; $i++) {
$newURL .= $e[$i] . '/'; // rebuild the url
}
echo $newURL . urlencode($file); //put it all togeather again
响应将是
https://example.com/wp-content/uploads/2019/10/%D9%83%D9%84%D8%A7%D9%85-%D8%B9%D8%B1%D8%A8%D9%8A-%D9%83%D8%AA%D9%8A%D8%B1.jpg
简而言之,您需要拆分 url,将 urlencode
应用于文件名,然后将 URL 放回原处。有几种方法可以做到这一点,例如使用正则表达式来挑选最后一个 /
之后的部分。
或者另一个简单的解决方案,使用 explode
and implode
:
// Split the URL on '/'
$urlParts = explode('/', $url);
// URL encode the last part
$numParts = count($urlParts);
$urlParts[$numParts - 1] = urlencode($urlParts[$numParts - 1]);
// Put the parts back together to a string
$formattedUrl = implode('/', $urlParts);
试试这个:
$url = "https://example.com/wp-content/uploads/2019/10/كلام-عربي-كتير.jpg";
$parsed = parse_url($url);
$pathFragments = explode('/', $parsed['path']);
$fileAndExt = array_pop($pathFragments);
list($file, $ext) = explode(".", $fileAndExt);
return $parsed['scheme']."://".$parsed['host'].implode("/", $pathFragments)."/".urlencode($file).".".$ext;