I'm working on a Laravel 12 project that connects to a Microsoft Dynamics CRM SQL Server database through a custom connection. I've run into a puzzling issue: Laravel's Schema::hasColumn()
returns false for columns that definitely exist in the database.
Configuration
Here is my database connection from config/database.php
:
'external_db' => [
'driver' => 'sqlsrv',
'host' => env('DB_EXTERNAL_HOST', '127.0.0.1'),
'port' => env('DB_EXTERNAL_PORT', '1433'),
'database' => env('DB_EXTERNAL_DATABASE', 'forge'),
'username' => env('DB_EXTERNAL_USERNAME', 'forge'),
'password' => env('DB_EXTERNAL_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => '',
'strict' => true,
],
Here is an example model:
class CRMProject extends Model
{
protected $connection = 'external_db';
protected $table = 'deviproj_projectBase';
public $timestamps = false;
protected $primaryKey = 'psa_projectId';
public $incrementing = false;
protected $fillable = ['psa_number', 'psa_name', 'CreatedOn'];
}
Diagnostic Code
When I log all columns using Schema::getColumnListing()
, it returns an empty array:
$model = $query->getModel();
\Log::info(
"Available columns " . get_class($model),
Schema::getColumnListing($model->getTable())
);
Also, when I check for a specific field:
$field = 'statecode';
\Log::info([
'model' => get_class($model),
'table' => $model->getTable(),
'hasColumn' => Schema::hasColumn($model->getTable(), $field),
]);
I get:
hasColumn => false
But the field definitely exists in the SQL Server table. I can confirm this through:
- SQL Server Management Studio
- Direct DB query in Laravel (
Model::select('statecode')->first()
works)
Question
Why does Schema::hasColumn()
return false for valid SQL Server columns in Laravel?
Is it a limitation of the SQL Server driver in Laravel? Is there a workaround or configuration needed when working with external CRM-based SQL schema?
I want to avoid hard-coding field names, but currently I’m forced to work around this.
More Context
The feature I'm working is a dynamic filter, so I gotta be able to send field, operator and value in the request to be able to filter the results.
$query->getModel()->getTable()
return the expected table name/value? ... also, there is aSchema::getColumns()
function too, which also needs a table name.getFillable()
on the model