-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Description
Laravel Version
12.27.1
PHP Version
8.3
Database Driver & Version
PortgresSQL 15
Description
After updating to Laravel 12 from version 11, my table prefix refuse to work when using a model.
The action I'm trying to achieve is to create an entry in my table, which is called "zoho_contacts".
Models\Contact::create([ 'field1' => '1', 'field2' => '2', ]);
My Contact model is just an empty class, extending a custom Model class
<?php
namespace App\DataRepositories\Zoho\Testing\Models;
use App\DataRepositories\Testing\DB;
use App\DataRepositories\Testing\Model as BaseModel;
abstract class Model extends BaseModel
{
public function getConnection()
{
return DB::mockConnectionUsing('pgsql', 'zoho');
}
}
The mockConnectionUsing method is called from the DB class
namespace App\DataRepositories\Testing;
use Illuminate\Database\Connection;
use Illuminate\Support\Facades\DB as BaseDB;
use Illuminate\Support\Str;
class DB
{
/** @var array<string, Connection> The cached database connection instances */
protected static $connections = [];
/**
* Get a connection to the testing database for a given existing connection.
*/
public static function mockConnection(string $name): Connection
{
if (isset(static::$connections[$name])) {
return static::$connections[$name];
}
$dbDriver = BaseDB::connection($name)->getDriverName();
return static::mockConnectionUsing($dbDriver, Str::replace('-', '_', $name));
}
/**
* Get a connection to the testing database for a given driver and with a given table prefix.
*/
public static function mockConnectionUsing(string $driver, string $prefix): Connection
{
if (! in_array($driver, ['pgsql', 'mysql'])) {
trigger_error("Database mock connection unavailable for driver '{$driver}'", E_USER_ERROR);
}
return (clone BaseDB::connection("testing.{$driver}"))->setTablePrefix("{$prefix}_");
}
/**
* Drop tables of a given data repository (by prefix) in the testing database.
*/
public static function wipeRepository(string $driver, string $prefix): void
{
$schema = static::mockConnectionUsing($driver, $prefix)->getSchemaBuilder();
$allTables = collect($schema->getAllTables())->map->tablename;
foreach ($allTables as $table) {
if (Str::startsWith($table, "{$prefix}_")) {
$schema->drop(Str::after($table, "{$prefix}_"));
}
}
}
}
In this case, what this code is supposed to do is set a prefix to the name of the table for each model using this custom Model class. However, it does not seem to work, as when trying to create an entry, an error is thrown
SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "contacts" does not exist
Here, we can see that the "zoho_" prefix was not set in the table name, thus failing. This is very weird, because the very same code works perfectly on Laravel version 11.45.3. Simply upgrading the laravel/framework version to 12.27.1 is enough to make the error trigger.
What's even weirder is that forcing the table name like this
namespace App\DataRepositories\Zoho\Testing\Models;
use Illuminate\Support\Str;
use App\DataRepositories\Testing\DB;
use App\DataRepositories\Testing\Model as BaseModel;
abstract class Model extends BaseModel
{
public function getTable()
{
return $this->getConnection()->getTablePrefix() . parent::getTable();
}
public function getConnection()
{
return DB::mockConnectionUsing('pgsql', 'zoho');
}
}
will result in the following error
SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "zoho_zoho_contacts" does not exist.
Does anyone know why this code suddenly won't work under Laravel 12 ?
Thank you very much for your time.
Steps To Reproduce
With Laravel version 12, creating an entry in a table using a prefix like detailed in the description.