skip to Main Content

I’m trying to extract all the queries from a PHP file. I use PHP reflection to retrieve the content of a method.

When I use reflection the string looks a bit like this:

        DB::statement('n
            ALTER TABLE `activity` n
            ADD `deleted_at` TIMESTAMP NULLn
        ');n
        DB::statement('n
            ALTER TABLE `activity_recurrence` n
            ADD `deleted_at` TIMESTAMP NULLn
        ');n

I’m trying to capture anything inside the statement() function. I’ve been trying a lot of different regex options but I’m unable to crack the case.

I’m now using this regex: ()(([^)]*)). It grabs anything between parenthesis but does not check if it has a statement suffix. I’ve been playing around with this answer, but I don’t get it working.

Thanks in advance!

2

Answers


  1. Chosen as BEST ANSWER

    So arkascha set me in the right direction. Below is a vanilla PHP solution.

     /**
     * Get everything between 2 string parts
     *
     * @param  string  $body
     * @param  string  $startString
     * @param  string  $endString
     * @return array
     */
    public function findBetween(string $body, string $startString, string $endString): array
    {
        // Create an array where we can store everything
        $result = [];
    
        // Clean-up the string a bit
        $body = trim(preg_replace('/s+/', ' ', $body));
    
        while (true) {
            // Find the first occurrence of the start string
            $start = strpos($body, $startString);
    
            // If we can not find any recurrence of the start string we break-out of the loop
            if (! $start) {
                break;
            }
    
            // The start is actually the first occurrence + the length of the start
            $start = $start + strlen($startString);
    
            // Find the end of the string
            $end = strpos($body, $endString);
    
            // Add anything in between the start and end inside the array
            $result[] = substr($body, $start, ($end - $start));
    
            // Chop the first part of the body
            $body = substr($body, ($end + strlen($endString)));
        }
    
        return $result;
    }
    

    In my case I will be using it like this:

    findBetween($body, 'statement(', ');');
    

  2. If you want to anything inside the statement function, you might use a recursive pattern with 2 capture groups.

    Then you can take the group 2 value.

    bDB::statement((((?>[^()]++|(?1))*)))
    

    Explanation

    • bDB::statement
    • ( Capture group 1
      • ( Match (
      • ( Capture group 2
        • (?>[^()]++|(?1))* Atomic group, match either 1 or more chars other than parenthesis, or recurse the first subpattern using (?1)
      • ) Close group 2
      • ) Match )
    • ) Close group 1

    See a regex101 demo.

    Note that can still be a brittle solution as you want to match sql statements.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search