0

これは、私が以前に尋ねた以前の質問に関連しています: PHP で文字列内の名前付き「パラメーター」を置き換える

その小さなクラスは以前は機能していましたが、動作がおかしいようです。現在、拡張機能として新しい Bolt CMS に移動しようとしています。

意図は、YML ファイルからデータを取得することです。データは次のようになります。

redirects:
    contentToPage:
        from: "content/(slug:any)"
        to: "page/{slug}"

拡張機能はこのデータをループし、該当する Symfony コンポーネントから取得した現在のリクエスト 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 '('.

ただし、正規表現区切り文字を/から~またはに変更する#と、エラーは発生しません。代わりにto、YML ファイル内のプロパティの値を取得します。この場合、 I get page/{slug}and not 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);
    }
}

ここで何ができるかについてのアイデアはありますか?

4

2 に答える 2

0

そうですね、今は動いているようです。何らかの理由で、私が変更したときにすべてがうまくいきました:

str_replace("\{$value\}", $captures[$c], $result);

str_replace('{' . $value . '}', $captures[$c], $result);

エスケープと関係があるようですが、これは奇妙です。最初のものでは、二重引用符を使用し、中括弧をエスケープして としてレンダリングしまし{slug}た。しかし、何らかの理由で、それは起こりませんでした。理由についてのアイデアはありますか?

于 2013-09-08T11:07:16.220 に答える