2

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.

5
  • 1
    Does the call to $query->getModel()->getTable() return the expected table name/value? ... also, there is a Schema::getColumns() function too, which also needs a table name.
    – Paul T.
    Commented yesterday
  • 2
    A possible workaround if you only need the fillable columns might be to use getFillable() on the model
    – Alex
    Commented 20 hours ago
  • @PaulT. I verified the table name it gives me and when I copy pasted it into SSMS I get do SELECT * on it and it works, so it should be good. And good idea for the Schema::getColumns(), but it returns 'columns' => array (),
    – Dolotboy
    Commented 19 hours ago
  • @Alex Yeah I figured a work around like that, but instead of using the fillables (Since I do not want them to be fillable), I created a new array "knownColumns" in my model using the Dynamics SQL Database and I manually filled the fields. It works, but I still would like to find the bottom of this problem haha
    – Dolotboy
    Commented 19 hours ago
  • 1
    @Dolotboy: To get to the bottom I'd highly suggest you to get Xdebug to work and then step into your diagnostic code with a breakpoint. You can then follow what happens behind the scenes. What I wonder about - because I don't know - is for example whether or not the schema routines have support for sqlsrv in general or this is due to a specific server version. For the routine it is not important whether the column is there or not but if it has an implementation for the connection. Increate the "debugability" with a better debugger. Works wonders. xdebug.org
    – hakre
    Commented 19 hours ago

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.