Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jackMutsers's avatar

function inside of a blade functions in the blade view file causes ParseError: Unclosed '(' error

i am using the latest version of Laravel (laravel/framework: 10.38.0)

I think that this is an unintended bug with the laravel blade views, because if i use a

@if(count($items) > 1)
@endif

inside of my blade view (like how it is shown in the documentation, "/docs/10.x/blade#if-statements"), then when i try to load my page the content will be passed through a function called "hasEvenNumberOfParentheses" in the following path: "vendor/laravel/framework/src/Illuminate/View/Compilers/BladeCompiler.php".

in the function "compileStatements" which calls the "hasEvenNumberOfParentheses" function it will perform a regex search for anything that start with a @ function until the first closing bracket ")" is found, so the result that comes back out of the regex will be

@if(count($items)

which means its unclosed and incomplete from the actual line which in turn triggers errors to be thrown around.

this is the function with the regex "vendor/laravel/framework/src/Illuminate/View/Compilers/BladeCompiler.php::compileStatements"

 /**
     * Compile Blade statements that start with "@".
     *
     * @param  string  $template
     * @return string
     */
    protected function compileStatements($template)
    {
        preg_match_all('/\B@(@?\w+(?:::\w+)?)([ \t]*)(\( ( [\S\s]*? ) \))?/x', $template, $matches);

        $offset = 0;

        for ($i = 0; isset($matches[0][$i]); $i++) {
            $match = [
                $matches[0][$i],
                $matches[1][$i],
                $matches[2][$i],
                $matches[3][$i] ?: null,
                $matches[4][$i] ?: null,
            ];

            // Here we check to see if we have properly found the closing parenthesis by
            // regex pattern or not, and will recursively continue on to the next ")"
            // then check again until the tokenizer confirms we find the right one.
            while (isset($match[4]) &&
                   Str::endsWith($match[0], ')') &&
                   ! $this->hasEvenNumberOfParentheses($match[0])) { // this is where the errors occurs
                if (($after = Str::after($template, $match[0])) === $template) {
                    break;
                }

                $rest = Str::before($after, ')');

                if (isset($matches[0][$i + 1]) && Str::contains($rest.')', $matches[0][$i + 1])) {
                    unset($matches[0][$i + 1]);
                    $i++;
                }

                $match[0] = $match[0].$rest.')';
                $match[3] = $match[3].$rest.')';
                $match[4] = $match[4].$rest;
            }

            [$template, $offset] = $this->replaceFirstStatement(
                $match[0],
                $this->compileStatement($match),
                $template,
                $offset
            );
        }

        return $template;
    }

but this also causes errors if i try to do something like this

@if((condition1 || condition2) && condition3)
@endif

or

@if(is_string($value))
@endif

or

 @if (count($errors) > 0) // regex return:  "@if (count($errors)"
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error) // regex return: "@foreach ($errors->all()"
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
0 likes
8 replies
Snapey's avatar

Please take care to format your code blocks if you want anyone to take your question seriously.

Snapey's avatar

An issue like that would wreck 95% of sites, so unlikely to be an issue unless it was on the latest point release, in which case it would be patched in days.

Try composer update just in case.

jackMutsers's avatar

@Snapey the main reason i bring it up, is that the error is only visible in a php debugger, regardless of the error being thrown or not it still continues, so its not a breaking bug and for some reason it also does not show up in the logs, that is probably why it was overlooked in the first place. another thing to note is that as soon as the view has been cached it wont run the function anymore that gives the error until there are new changes to the view itself.

that is why i dont know if it will be fixed soon unless someone points it out, which is the whole reason for my post because seeing the error popup when trying to debug my code is very anoying, so i changed the functions back to

<?php if((condition1 || condition2) && condition3): ?>

im using the xdebug extension of visual studio code as my php debugger

1 like
Martin17's avatar

@jackMutsers Hello! ANy update of this issue? Im using xdebug in VS code too, and the problem only appears that way, if i run the laravel server from the terminal only, the page loaded well. I think the solution will be some settings in vs code. If there any updates, or solution for this please inform me. Thanks in advance!

jackMutsers's avatar

@Martin17 Nothing has become of this notification yet, but the error is not breaking because it just throws an error into a try-catch, after which it changes all blade functions into PHP alternatives before saving the converted file into the view cache.

Now that the file exists in the cache, it won't try to open the original file again, meaning that you won’t run into the problem anymore since it got changed to regular php which has no problems.

I don't know if anything changes if you run the site from the terminal, since I use Mamp pro to host my device, but I also don't know if xdebug from VS Code works (the same) in the terminal version of running the project

SpiZeak's avatar

Thought I'd bump this as I'm running in to it now in illuminate/view version 12.8.1. I'm using PHP 8.4.5, Xdebug 3.4.2, Nginx 1.27.4, VSCODE 1.100.

martinbean's avatar

@SpiZeak Create your own thread, and post your actual error message and related Blade code.

Please or to participate in this conversation.