Kontynuujemy prace nad DirectiveParserem. Dopisujemy do niego w elegancki sposób funkcję znaną z WordPressa – wp_unique_id. Do dzieła.

Przypomnijmy sobie, na czym skończyliśmy:

<?php

class DirectiveParser {
    protected static $patterns = [
            [
                "pattern" => "/@METHOD\('*(.*?)'*\)/i",
                "replace" =>  array(__CLASS__, 'method')
            ]
            
        ];

    public static function method($method){
            return '<input type="hidden" id="_method" name="_method" value="' . $method . '"/>';
        }

    public static function searchAndReplace($source){
        foreach(self::$patterns as $pattern ){
            $action = $pattern['replace'];
            $source = preg_replace_callback(
                $pattern['pattern'],
                function($m) use($action)  {
                    return $action($m[1]);
                },
                $source);
        }
        return $source;
    }
}

$txt = "@METHOD('PUT')";
echo htmlspecialchars(DirectiveParser::searchAndReplace($txt));
//<input type="hidden" id="_method" name="_method" value="PUT"/>

Funkcja wp_unique_id jest bardzo prosta:

function wp_unique_id( $prefix = '' ) {
	static $id_counter = 0;
	return $prefix . (string) ++$id_counter;
}

Jakoś to trzeba będzie przełożyć na OOP. Polecam trait:

trait UniqueID {
    public static $id_counter = 0;
    public static function unique_id($prefix=''){
        return $prefix . (string) ++static::$id_counter;
    }
}

Teraz użyjemy naszego trait:

<?php
trait UniqueID {
    public static $id_counter = 0;
    public static function unique_id($prefix=''){
        return $prefix . (string) ++static::$id_counter;
    }
}

class DirectiveParser {
    use UniqueID;
    protected static $patterns = [
            [
                "pattern" => "/@METHOD\('*(.*?)'*\)/i",
                "replace" =>  array(__CLASS__, 'method')
            ]
            
        ];

    public static function method($method){
            return '<input type="hidden" id="'.static::unique_id('_method-').'" name="_method" value="' . $method . '"/>';
        }

   //(...)
}

$txt = "@METHOD('PUT')";
echo htmlspecialchars(DirectiveParser::searchAndReplace($txt));
//<input type="hidden" id="_method-1" name="_method" value="PUT"/>

Okej, dodajmy jeszcze do naszych wzorców:

//(...)

class DirectiveParser {
    use UniqueID;
    protected static $patterns = [
            [
                "pattern" => "/@METHOD\('*(.*?)'*\)/i",
                "replace" =>  array(__CLASS__, 'method')
            ],
            [
                "pattern" => "/@ID\('*(.*?)'*\)/i",
                "replace" =>  array(__CLASS__, 'unique_id')
            ]
            
        ];

   //(...)
}

$txt = "@METHOD('PUT')";

echo htmlspecialchars(DirectiveParser::searchAndReplace($txt));

//<input type="hidden" id="_method-1" name="_method" value="PUT"/>

$txt2 = '<li id="@id(li-item-)">list item</li><li id="@id(li-item-)">list item2</li>';

echo htmlspecialchars(DirectiveParser::searchAndReplace($txt2));

//<li id="li-item-2">list item</li>
//<li id="li-item-3">list item2</li>

Działa jak należy!