Skip to content
Advertisement

PHP – Preg Match All – WordPress Multiple short codes with multiple parameters

I’m trying to find a regex capable of capturing the content of short codes produces in WordPress.

My short codes have the following structure: [shortcode name param1=”value1″ param2=”value2″ param3=”value3″]

The number of parameters is variable.

I need to capture the shortcode name, the parameter name and its value.

The closest results I have achieved is with this:

/(?:[(.*?)|G(?!^))(?=[^][]*])h+([^s=]+)="([^s"]+)"/

If I have the following content in the same string:

[specs product="test" category="body"]

[pricelist keyword="216"]

[specs product="test2" category="network"]

I get this:

0=>array(

    0=>[specs product="test"
    1=> category="body"
    2=>[pricelist keyword="216"
    3=>[specs product="test2"
    4=> category="network")

1=>array(
    0=>specs
    1=>
    2=>pricelist
    3=>specs
    4=>)
2=>array(
    0=>product
    1=>category
    2=>keyword
    3=>product
    4=>category)
3=>array(
   0=>test
   1=>body
   2=>216
   3=>test2
   4=>network)
   )

I have tried different regex models but I always end up with the same issue, if I have more than one parameter, it fails to detect it.

Do you have any idea of how I could achieve this?

Thanks Laurent

Advertisement

Answer

You could make use of the G anchor using 3 capture groups, where capture group 1 is the name of the shortcode, and group 2 and 3 the key value pairs.

Then you can remove the first entry of the array, and remove the empty entries in the 1st, 2nd and 3rd entry.

This is a slightly updated pattern

(?:[(?=[^][]*])(w+)|G(?!^))h+(w+)="([^"]+)"

Regex demo | Php demo

Example

$s = '[specs product="test" category="body"]';
$pattern = '/(?:[(?=[^][]*])(w+)|G(?!^))h+(w+)="([^"]+)"/';

$strings = [
    '[specs product="test" category="body"]',
    '[pricelist keyword="216"]',
    '[specs product="test2" category="network" key="value"]'
];

foreach($strings as $s) {
    if (preg_match_all($pattern, $s, $matches)) {
        unset($matches[0]);
        $matches = array_map('array_filter', $matches);
        print_r($matches);
    }
}

Output

Array
(
    [1] => Array
        (
            [0] => specs
        )

    [2] => Array
        (
            [0] => product
            [1] => category
        )

    [3] => Array
        (
            [0] => test
            [1] => body
        )

)
Array
(
    [1] => Array
        (
            [0] => pricelist
        )

    [2] => Array
        (
            [0] => keyword
        )

    [3] => Array
        (
            [0] => 216
        )

)
Array
(
    [1] => Array
        (
            [0] => specs
        )

    [2] => Array
        (
            [0] => product
            [1] => category
            [2] => key
        )

    [3] => Array
        (
            [0] => test2
            [1] => network
            [2] => value
        )

)
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement