-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Description
Laravel Version
11.43.2
PHP Version
8.3.6
Database Driver & Version
Mysql
Description
I had the following problem:
- I had a Model called PunchRegistry like follows:
<?php
class PunchRegistry extends Model
{
public $timestamps = false;
protected $guarded = [];
public function pair()
{
return $this->belongsTo(PunchRegistry::class, 'punch_registry_id');
}
}
- I needed to find all registries that have a pair to check the hours diference between then, so I created the following query:
<?php
$registries = PunchRegistry::whereHas('pair', function (Builder $query) {
$driver = DB::getDriverName(); // Get Database
$query->where('punch_registries.type', 1);
if ($driver === 'mysql') {
$query->whereRaw('TIMESTAMPDIFF(HOUR, punch_registries.record_at, laravel_reserved_0.record_at) >= 8');
} elseif ($driver === 'pgsql') {
$query->whereRaw('EXTRACT(HOUR FROM (laravel_reserved_0.record_at - punch_registries.record_at)) >= 8' );
}
})
->with(['pair'])
->orderBy('record_at', 'asc')
->lazy();
- As you can see, I'm using the
laravel_reserved_0
table to refer to the pair.
That works normally in dev mode, but when I launched it in the test enviroment with laravel octane, I got error 500 in my logs because the table 'laravel_reserved_0' is not defined. Reading the source you can find the following lines in \Illuminate\Database\Eloquent\Relations\Relation
class:
framework/src/Illuminate/Database/Eloquent/Relations/Relation.php
Lines 79 to 85 in 50828e2
/** | |
* The count of self joins. | |
* | |
* @var int | |
*/ | |
protected static $selfJoinCount = 0; | |
framework/src/Illuminate/Database/Eloquent/Relations/Relation.php
Lines 273 to 284 in 50828e2
/** | |
* Get a relationship join table hash. | |
* | |
* @param bool $incrementJoinCount | |
* @return string | |
*/ | |
public function getRelationCountHash($incrementJoinCount = true) | |
{ | |
return 'laravel_reserved_'.($incrementJoinCount ? static::$selfJoinCount++ : static::$selfJoinCount); | |
} | |
As we can see, each new call to this request increases the table number. For the development environment, this can be ignored, since the value of the static variable is always reset to zero. However in octane, according to this docs, static variables are not reset every request, so Relation::$selfJoinCount
keeps increasing every request.
I can suggest three possible fixes for this problem, and send a PR if it is needed:
- Create an extra parameter to whereHas to add the alias name to that table. (Hard to code I think, but the best solution)
- Add a way to make
Relation::$selfJoinCount
unique for each complete query (Principal query and sub queries). - Add a way to reset
Relation::$selfJoinCount
manually.
Steps To Reproduce
1- Create a self reference model;
2- Create a query with whereHas that has a condition that need to use laravel_reserved_0
table.
3- Start octane.
4- Make multiple requests to the same route, the first will work as intented and the next ones will throw a error.