laravel / octane

Supercharge your Laravel application's performance.
https://laravel.com/docs/octane
MIT License
3.79k stars 296 forks source link

Swoole + `defer()`, function already exists. #948

Closed tobz-nz closed 2 months ago

tobz-nz commented 2 months ago

Laravel Version

11.23.4

PHP Version

8.3.10

Database Driver & Version

mysql5.7:latest docker

Description

Laravel Sail v1.32.0.

When using the Cache::flexible() method I get the following error:

defer() expects exactly 1 argument, 2 given at /var/www/html/vendor/laravel/framework/src/Illuminate/Cache/Repository.php:521)

I noticed this error only happens in the browser not the CLI - which I usually run form my host, not sail/docker. So I tried it in the sail container - same error.

So dumping a reflection of the function reveals:

$reflFunc = new ReflectionFunction('defer');
dd($reflFunc);

1 ReflectionFunction {#4 ▼
  +name: "defer"
  returnType: "void"
  parameters: {▼
    $callback: ReflectionParameter {#19 ▼
      +name: "callback"
      position: 0
      typeHint: "callable"
    }
  }
  extra: {▼
    extension: "swoole"
    isInternal: true
  }
}

Printing phpinfo() shows that Sail has Swoole installed. and I assume from this Swoole adds a global defer() function, so the Lavavel helper funciton is never defined - and would error if it did - when Swoole is installed.

Steps To Reproduce

Create a new Laravel 11.23+ project using Laravel Sail (or install Swoole).

run a controller or tinker:

// call it twice
Cache::flexible('test', [1, 5], fn () => 'test');
Cache::flexible('test', [1, 5], fn () => 'test');
mihaileu commented 2 months ago

I couldn't reproduce it, I run in a controller with swoole enabled and cache driver array.

crynobone commented 2 months ago

cleanshot_2024-09-13_at_21.38.09.png

This seem related

AbdullahALT commented 2 months ago

I ran into the same issue when I tried Cache::flexible in a project using Sail, and sure enough it was using swoole's helper instead of Laravel's

ReflectionFunction {#1618 // app/Http/Controllers/Lookup/LookupsController.php:36
  +name: "defer"
  returnType: "void"
  parameters: {
    $callback: ReflectionParameter {#1625
      +name: "callback"
      position: 0
      typeHint: "callable"
    }
  }
  extra: {
    extension: "swoole"
    isInternal: true
  }
}

my cache driver is redis in case this is related

puklipo commented 2 months ago

It is not related to Octane. This occurs in environments where the Swoole extension is installed.

There is a conflict between Laravel's global defer() and Swoole's global defer().

defer() is used in Cache::flexible(). Swoole's defer() is being used here.

        if (function_exists('defer')) {
            defer($refresh, "illuminate:cache:refresh:{$key}");
        } else {
            $refresh();
        }

https://github.com/laravel/framework/blob/da28aabb597ec4ea6f43bcaf82e263a0fad8737f/src/Illuminate/Cache/Repository.php#L520

sy-records commented 2 months ago

defer is a short named function in swoole that you can turn off via php.ini.

swoole.use_shortname=off
tobz-nz commented 2 months ago

Sorry I don't know how I created this on the Octane repo.

I can create a PR on Sail adding this to the all the php.ini's...

defer is a short named function in swoole that you can turn off via php.ini.

swoole.use_shortname=off
BassemN commented 2 months ago

I believe the defer function name is already registered with the Swoole extension, which could cause conflicts with existing projects that rely on Swoole’s defer function or have the Swoole extension enabled. Unfortunately, I think Laravel should consider renaming the defer function to avoid these conflicts.

taylorotwell commented 2 months ago

I have no plans to rename defer at this time. Swoole is used by a very small portion of the Laravel user base so I'd like to find alternative solutions.

dash8x commented 2 months ago

Running into this issue on a default Laravel installation on Forge

marco-silvestri commented 2 months ago

Running into this issue on an upgraded Laravel 11 project with Sail, where Swoole is clearly installed by default:

/docker/8.3/Dockerfile:33-34 && pecl install swoole-5.1.2 \ && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/20-swoole.ini \

AbdullahALT commented 2 months ago

@marco-silvestri Swoole is included in sail, I've managed to fix it by doing the following

bogusbd commented 2 months ago

Hello,

I use Forge Laravel Octane is disabled

I'm trying to use Cache::flexible()

And get this error:

defer() expects exactly 1 argument, 2 given {"exception":"[object] (ArgumentCountError(code: 0): defer() expects exactly 1 argument, 2 given 

I assume that Forge pre-installs Swoole (so that it is always ready to be turned on) .... and as a result there is a naming conflict

marco-silvestri commented 2 months ago

@marco-silvestri Swoole is included in sail, I've managed to fix it by doing the following

  • create a file in your project ./docker/php/sail-php.ini
  • paste this into the file
swoole.use_shortname=off
  • map it to the container in docker-compose.yml
       volumes:
            - '.:/var/www/html'
            - './docker/php/sail-php.ini:/etc/php/8.3/cli/conf.d/99-sail.ini'
  • shut sail down and run it again, it should be fixed then
sail down
sail up -d

It works flawlessly, thanks!

Rattone commented 2 months ago

I have no plans to rename defer at this time. Swoole is used by a very small portion of the Laravel user base so I'd like to find alternative solutions.

So why install it with Sail?

jordanhavard commented 2 months ago

I also rolled out Cache::flexible updates (hosted on forge not using octane) and ran into the same issue as described.

Updating the php.ini as per @sy-records fixed the issue after a php-fpm restart.

sy-records commented 2 months ago

Fixed via https://github.com/laravel/framework/pull/52801