skip to Main Content

Regexr Link

(?<Namespace>[^@]*)?[\/](?<ClassName>[wd]*)@?(?<ClassMethod>[^@]*)?

I’m trying to Capture Namespace, ClassName and ClassMethod from a string in which Namespace and ClassMethod are optional.

This pattern handles capturing the three well if all three are present. But fails if ClassName is the only thing present.

The only solution I found was to make the last slash optional

(?<Namespace>[^@]*)?[\/]?(?<ClassName>[wd]*)@?(?<ClassMethod>[^@]*)?

But this does not catch the ClassName at all and captures it in Namespace instead.

What am I doing wrong?

String: ApiBlahBlahCarController@doStuff

Pattern: (?<Namespace>[^@]*)?[\/]?(?<ClassName>[wd]*)@?(?<ClassMethod>[^@]*)?

Expecting:
Namespace: ApiBlahBlah
ClassName: CarController
ClassMethod: doStuff

2

Answers


  1. Chosen as BEST ANSWER

    I solved it by using a non-capturing group.

    (?:(?<Namespace>[wd\/]*)[\/])?(?<ClassName>[wd]*)@?(?<ClassMethod>[^@]*)?
    

    Regexr link has been updated with the pattern that worked for me.


  2. The class name is the mandatory part, so you have to build the pattern around it. The namespace is a repeat of strings ending with a backslash. The class method is separated by an @ but the separator is not part of the method name. A non capturing group allows to make it optional.

    <?php
    
    $pattern = '(
      (?<Namespace>(?:[^\\]+\\)*) # any amount of chars ending with backslash
      (?<ClassName>[^\\@]+) # chars expect backslash or @
      (?:@(?<ClassMethod>.+))? # chars after @ - optional
    )x';
    
    $subjects = [
      'ApiBlahBlahCarController@doStuff',
      'CarController@doStuff',
      'CarController'    
    ];
    
    foreach ($subjects as $subject) {
        preg_match($pattern, $subject, $match);
        var_dump(array_filter($match, 'is_string',  ARRAY_FILTER_USE_KEY));
    }
    

    Output:

    array(3) {
      ["Namespace"]=>
      string(14) "ApiBlahBlah"
      ["ClassName"]=>
      string(13) "CarController"
      ["ClassMethod"]=>
      string(7) "doStuff"
    }
    array(3) {
      ["Namespace"]=>
      string(0) ""
      ["ClassName"]=>
      string(13) "CarController"
      ["ClassMethod"]=>
      string(7) "doStuff"
    }
    array(2) {
      ["Namespace"]=>
      string(0) ""
      ["ClassName"]=>
      string(13) "CarController"
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search