这与之前我提出的问题有关:Replacing named 'parameters' within a string in PHP
那个曾经工作过的小课程,但似乎行为不端,现在我正试图把它作为扩展转移到新的Bolt CMS。
目的是从YML文件中获取数据。数据看起来像这样:
redirects:
contentToPage:
from: "content/(slug:any)"
to: "page/{slug}"
扩展循环遍历此数据,并将其与从适用的Symfony组件获取的当前Request URI进行比较。如果匹配,则将相应地重定向用户。因此,在这种情况下,如果用户尝试访问content/test
,则会将其重定向到page/test
。
但是有些东西似乎出错,转换的替换不正确,或者我被抛出错误。首先,这是有问题的块:
$convertedReplacements = preg_replace_callback("/^{$convertedPlaceholders}$/", function ($captures) {
$result = $this->destination;
for ($c = 1, $n = count($captures); $c < $n; ++$c) {
$value = array_shift($this->computedReplacements);
$result = str_replace("\{$value\}", $captures[$c], $result);
}
return $result;
}, $requestUri);
$convertedPlaceholders
包含from
值中的已替换参数。因此,(slug:any)
将替换为([a-z0-9\.\-\_\%\=]+)
。现在,这可行,但该函数抛出此异常:preg_replace_callback(): Unknown modifier '('
。
但是,如果我将正则表达式分隔符从/
更改为~
或#
,我就不会收到错误。相反,我在YML文件中获取to
属性的值。在这种情况下,我得到page/{slug}
而不是page/test
。
以下是整个扩展程序:
<?php
// Redirector Extension for Bolt
// Minimum version: 1.2
namespace Redirector;
use Silex\Application as Application;
use Symfony\Component\HttpFoundation\Request as Request;
use Symfony\Component\Yaml\Parser as Parser;
use Bolt\BaseExtension as BoltExtension;
class Extension extends BoltExtension
{
protected $placeholders = array(
':all' => '.*',
':alpha' => '[a-z]+',
':alphanum' => '[a-z0-9]+',
':any' => '[a-z0-9\.\-\_\%\=]+',
':num' => '[0-9]+',
':segment' => '[a-z0-9\-\_]+',
':segments' => '[a-z0-9\-\_\/]+'
);
protected $computedReplacements;
protected $destination;
/**
* Basic information about the extension. Shown in the Bolt Admin Environment.
*
* @return Array
*/
function info() {
$data = array(
'name' => 'Redirector',
'version' => '0.1',
'author' => 'Foundry Code - Mike Anthony',
'description' => 'An extension that allows you to perform any pre-app <code>301 Moved Permanently</code> redirects.',
'type' => 'Pre-app Hook',
'link' => 'http://code.foundrybusiness.co.za/extensions/bolt-redirector',
'first_releasedate' => '2013-08-28',
'latest_releasedate' => '2013-08-28',
'required_bolt_version' => '1.2',
'highest_bolt_version' => '1.2'
);
return $data;
}
/**
* Initialise the extension's functions
*
* @return void
*/
function initialize() {
$this->options = $this->config['options'];
$this->redirects = $this->config['redirects'];
$this->handleRedirects();
}
/**
* Check for a redirect. If it exists, then redirect to it's computed replacement.
*
* @return ? Response
*/
function handleRedirects()
{
$redirector = $this;
$this->app->before(function (Request $request) use ($redirector) {
if (empty($redirector->redirects)) {
return;
}
$requestUri = trim($request->getRequestUri(), '/');
$availablePlaceholders = '';
foreach ($this->placeholders as $placeholder => $expression) {
$availablePlaceholders .= ltrim("$placeholder|", ':');
}
$availablePlaceholders = rtrim($availablePlaceholders, '|');
//die($availablePlaceholders);
$pattern = '/\{(\w+):('.$availablePlaceholders.')\}/';
//die($pattern);
foreach ($this->redirects as $redirectName => $redirectData) {
$this->computedReplacements = array();
$this->destination = $redirectData['to'];
$from = rtrim($redirectData['from'], '/');
$to = rtrim($redirectData['to'], '/');
$convertedPlaceholders = preg_replace_callback($pattern, function ($captures) {
$this->computedReplacements[] = $captures[1];
return '(' . $this->placeholders[":{$captures[2]}"] . ')';
}, $from);
//die($convertedPlaceholders);
$convertedReplacements = preg_replace_callback("/^{$convertedPlaceholders}$/", function ($captures) {
$result = $this->destination;
for ($c = 1, $n = count($captures); $c < $n; ++$c) {
$value = array_shift($this->computedReplacements);
$result = str_replace("\{$value\}", $captures[$c], $result);
}
return $result;
}, $requestUri);
die($convertedReplacements);
if (preg_match("~^{$convertedPlaceholders}$~i", $requestUri)) {
return $this->app->redirect("/$convertedReplacements", 301);
}
}
}, Application::EARLY_EVENT);
}
}
关于我在这里可以做什么的任何想法?
答案 0 :(得分:0)
如果你想使用/
作为正则表达式分隔符,你应该转义正则表达式中的所有/
个字符,或者更好的是,使用另一个分隔符。
答案 1 :(得分:0)
是的,它似乎现在正在运作。出于某种原因,当我改变时,一切都跳了出来:
str_replace("\{$value\}", $captures[$c], $result);
到
str_replace('{' . $value . '}', $captures[$c], $result);
我认为它与逃避有关,这很奇怪。在第一个中,我使用双引号,并转义大括号,以便它呈现为{slug}
。但是,出于某种原因,这种情况并没有发生。关于为什么的任何想法?