Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8650037
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 12, 20262026-06-12T13:43:00+00:00 2026-06-12T13:43:00+00:00

SOLVED: Thanks to @SJFrK, my issue has been solved. The following class allows me

  • 0

SOLVED:

Thanks to @SJFrK, my issue has been solved. The following class allows me to do what I need. The question follows the class.

class Redirects
{
    /*
    |--------------------------------------------------------------------------
    | Placeholder Types
    |--------------------------------------------------------------------------
    |
    | An array of placeholder types thatalow specific characters in a source
    | route or URL.
    |
    */

    private static $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\-\_\/]+',
    );

    /*
    |--------------------------------------------------------------------------
    | Computed Replacements
    |--------------------------------------------------------------------------
    |
    | An array that contains converted source placeholders.
    |
    */

    private static $computed_replacements = array();

    /*
    |--------------------------------------------------------------------------
    | Computed Replacements
    |--------------------------------------------------------------------------
    |
    | Class-scoped string that contains a replacement route or URL from
    | site.redirects.
    |
    */

    private static $destination;

    /**
     * Check for a redirect. If it exists, then redirect to it's computed replacement.
     *
     * @return Response
     */
    public static function redirect()
    {
        // Only do this if redirects have been defined.
        if (Config::has('site.redirects') && count(Config::get('site.redirects') > 0))
        {
            $route = URI::current();

            // Get the available placeholders from static::$placeholders and
            // convert them into applicable options for the pattern.
            $available_placeholders = '';
            foreach (static::$placeholders as $placeholder => $expression)
                $available_placeholders .= ltrim("$placeholder|", ':');
            $available_placeholders = rtrim($available_placeholders, '|');

            // Define the pattern.
            $pattern = '/\((\w+):('.$available_placeholders.')\)/';

            // Get the redirects.
            $redirects = Config::get('site.redirects');

            // For each redirect, convert all the place holders and resulting
            // values, and check for a match. If one exists, then redirect to it.
            foreach ($redirects as $from => $to) {
                static::$computed_replacements = array();
                static::$destination = $to;
                $from = rtrim($from, '/');
                $to = rtrim($to, '/');

                // Convert the placeholders in $from (if any)
                $converted_placeholders = preg_replace_callback($pattern, function($captures) {
                    static::$computed_replacements[] = $captures[1];
                    return '('.static::$placeholders[":{$captures[2]}"].')';
                }, $from);

                // Get the replacements
                $converted_replacements = preg_replace_callback("#^{$converted_placeholders}$#i", function($captures) {
                    $output = static::$destination;
                    for ($c = 1, $n = count($captures); $c < $n; ++$c)
                    {
                        $value = array_shift(static::$computed_replacements);
                        $output = str_replace("<$value>", $captures[$c], $output);
                    }
                    return $output;
                }, $route);

                // If the current route matches the converted expression, then redirect.
                if (preg_match("!^{$converted_placeholders}$!i", $route))
                    return Redirect::to($converted_replacements, 301)
                        ->with('moved-from', $route)
                        ->with('moved-from-rule', "'$from': '".static::$destination."'");
            }
        }
        else return;
    }
}

INTRODUCTION

I’m in the process of writing a static website bundle in Laravel (FTW), and have come accross something I can’t seem to get around.

The app contains a configuration file (config/site.php), which – among other things – contains an array of redirect lookups. The idea is to check for a match in each lookup URI, and then redirect to the replacement URI (with a 301 redirect, of course) – useful for those moving a static HTML site over to my bundle.

The format of the array is:

'redirects' => array(
    '<source>' => '<destination>'
)

Within the <source>, the user can include the following:

  1. Regular Expressions
  2. Laravel-style placeholders: (:any), (:all), (:num), or (:alpha) – I added that last one.

For example, the user could use the following redirect (note that I have chosen to use angular parenthises for the <destination> as it a little more aesthetic – it is converted back down to its regex equivalent [see the class below]):

'(:all).html' => '<1>'

This would direct any page ending with .html to a route that does not contain it. Example: http://example.com/about.html would redirect to http://example.com/about.

THE PROBLEM

I would like to be able to ‘name’ each parameter for easy-reading (and pleasant coding). What I’d like to do is name each placeholder in <source> (this is optional, of course), AND define a placeholder-type. For example:

'(name:all).html' => '<name>'

Now, considering that the placeholders could be named, they could naturally be in any order within the <destination>, for example (note the order changes in the destination URI):

'Products/(name:any)-(category:any)-(id:num).html' => 'products/<category>/<id>/<name>/overview'

Using the regular placeholder syntax, I could interpret this as:

'Products/(:any)-(:any)-(:num).html' => 'products/<2>/<3>/<1>'

This is the fallback anyway – I’d need to find out how to replace the names with their corresponding capture groups using preg_replace. But it seems to not be possible using named parameters/captures:

NAMED PARAMETERS

An easy route would be by using named parameters in preg_replace, but (as I understand this) PHP does not support it.

Using this method would enable me to use the same kind of replacement tools to get the task done – so not having it available is a little disappointing.

Nonetheless, I am happy to revert to something a little more complex (which is a good thing, anyway). Thing is, I have no idea how – and a solution is just not coming to me. I have had a look at the Silex RouteCompiler class, but do not understand it fully. I feel that, considering the backbone of Laravel is built upon the Symfony component-set (much like Silex), there may be a better way to accomplish what I need.

Has anyone had the same kind of requirements, and perhaps found a solution? Any help here would be simply awesome! Thanks in advance.

CURRENT CLASS

Here’s the source to the class that handles the redirects. I simply call Redirects::handle() in my routes.php file.

class Redirects
{
    private static $placeholders = array(
        ':any' => '[a-zA-Z0-9\.\-_%=]+',
        ':num' => '[0-9]+',
        ':alpha' => '[a-z]+', //added
        ':all' => '.*',
    );

    private static $replacement_identifiers = array(
        '(\<([0-9]+)\>)' => '$$1',
    );

    /**
     * Create the applicable regex placeholders
     *
     * @param  string  &$from
     * @param  string  &$to
     * @return void
     */
    protected static function placeholders(string &$from, string &$to)
    {
        // Replace the <source> with a match expression
        foreach (static::$placeholders as $placeholder => $expression)
            $from = str_replace("({$placeholder})", "({$expression})", $from);

        // Replace the <destination> with a replacement expression
        foreach (static::$replacement_identifiers as $identifier => $expression)
            if (preg_match($identifier, $to))
                $to = preg_replace($identifier, $expression, $to);
    }

    /**
     * Return the response of any redirects, or void if none
     *
     * @return Response|void
     */
    public static function handle()
    {
        $route = URI::current();
        if (Config::has('site.redirects'))
        {
            $redirects = Config::get('site.redirects');
            foreach ($redirects as $from => $to) {
                $from = rtrim($from, '/');
                static::placeholders($from, $to);
                if (preg_match("!^{$from}$!i", $route))
                {
                    if (strpos($to, '$') !== false and strpos($from, '(') !== false)
                        $to = preg_replace("!^{$from}$!i", $to, $route);
                    return Redirect::to($to, 301)->with('Moved-From', $route);
                }
                else return;
            }
        }
        else return;
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-12T13:43:02+00:00Added an answer on June 12, 2026 at 1:43 pm

    This is a test-case case that does what you want, maybe you can incorporate this into your class?:

    <?php
    class Redirects {
    private static $placeholders = array(
        ':any' => '[a-zA-Z0-9\.\-_%=]+',
        ':num' => '[0-9]+',
        ':alpha' => '[a-z]+', //added
        ':all' => '.*',
    );
    
    private static $tmp;
    private static $tmpValue;
    
    public static function handle() {
        $case = array('Products/(name:any)-(category:any)-(id:num).html' => 'products/<category>/<id>/<name>/overview');
        $test = 'Products/productName-categoryName-123.html';       // products/categoryName/123/productName/overview
    
        $pattern = '/\(\s*?(\w*?)\s*?:\s*?(\w*?)\s*?\)/';
    
        foreach ($case as $k => $v) {
            self::$tmp = array();
            self::$tmpValue = $v;
    
            $step1 = preg_replace_callback($pattern, array(self, 'replace_step1'), $k);
            $step2 = preg_replace_callback('#' . $step1 . '#', array(self, 'replace_step2'), $test);
    
            print 'case: ' . $k . '<br>';
            print 'step1: ' . $step1 . '<br>';
            print 'step2: ' . $step2 . '<br>';
        }
    }
    
    private static function replace_step1($matches) {
        self::$tmp[] = $matches[1];
    
        return '(' . self::$placeholders[':' . $matches[2]] . ')';
    }
    
    private static function replace_step2($matches) {
        $str = self::$tmpValue;
    
        for ($i = 1, $n = count($matches); $i < $n; ++$i) {
            $value = array_shift(self::$tmp);
    
            $str = str_replace('<' . $value . '>', $matches[$i], $str);
        }
    
        return $str;
    }
    }
    
    Redirects::handle();
    

    It first replaces your named placeholders with the real PREG placeholders and stores them in an array $tmp. It then checks the test-string $test if it matches that pattern $step1 and replaces them according to the $tmp array.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

This problem has been solved! Thanks a lot to Brad, Denis and junkie! You're
This problem has been solved thanks to your suggestions. See the bottom for details.
EDIT: SOLVED Thanks Brooks. Your question led me to keep digging into if the
I understand the problem that OSGI solved thanks to this question.... What does OSGi
How to adjust the font for the following:(solved) fontSize 40 BOLD Italicized Thanks The
I've had an issue with Visual Studio that has been bugging me for some
UPDATE: Solved. Thanks BusyMark! EDIT: This is revised based on the answer below from
SOLVED I misspelled the property department -> Department. Thanks for the answers and a
SOLVED (Thanks Regexident) I have an app that passes the file path of a
Problem solved Thanks all for your engagement in my error searching! Thanks @Basile Starynkevitch

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.