TL DR
I have queues with jobs that sometimes seem unsuccessful because a regular database query (using the standard Laravel query designer) does not reliably return PHP objects defined in fetch mode in my config/database.php . It seemed that sometimes an object or an array was returned, so somehow the sampling mode changes (and even changes back).
Detailed question
I am querying an external database using the Laravel query constructor. The sampling mode is set to return objects to config/database.php :
'fetch' => PDO::FETCH_OBJ,
... which basically works in many places of my application.
Sometimes, executing it as a job in a queue, it may happen that the query result is an array instead of an object. Tasks set the correct code, and I cannot reproduce why this happens sometimes.
Does anyone have an idea what could lead to this result?
This happens both using the usual get() method and chunk , for example. Restarting the command line helps to get rid of the error, but in the end it will return!
This is what my code looks like:
$assetData = DB::connection('connection_name')->table('system') ->whereIn('system_id', $this->system_ids)->orderBy('system_id'); $emlAssetData->chunk(5000, function ($assetDataChunk) { foreach ($assetDataChunk AS $assetData) { if (!is_object($assetData)) { \Log::warning(__CLASS__.': '.json_encode($assetData)); } } $assetData->field;
I use:
- PHP 7.0
- MySQL
v5.7.16 v5.1.49 - Laravel 5.5
My desktop is to add this to any places where I query an external database like this.
if (is_array($assetData)) { \Log::warning(__CLASS__." Converting array to object: ".json_encode($assetData)); $assetData = (object)$assetData; }
Debugging is quite difficult to do in such conditions, because it is performed only in the queue :(
Update: 2017-12-11: more detailed information on the used SQL / code
To summarize the more special things I'm doing here, this may be relevant to my problem:
- I do not request the default connection running on localhost, but an external database (on the internal network).
- I do not use Eloquent, but the usual Laravel query builder
- To accomplish the result, I use a self-written custom function that calls the callback function for each row
Background: imports various parts of the legacy MySQL v5.1.49 database into our project database. To make this easier, you specify some sort of column mapping (from old to new field / table names) such as
$columnMapping = collect([ 'system.system_id' => 'system_id', 'staud_colours.colour_name' => 'system_name', ]);
Then you execute your own query and map the old fields to the new fields using a helper function:
$items = \DB::connection('slave')->table('system') ->join('staud_colours', 'staud_colours.colour_id', '=', 'system.system_fremd_id') ->where('system.system_klasse', 'colours')->where('system.system_status', 1); $this->prepareQueryToBeInsertedToDB($items, $columnMapping, function ($insertData) { static::create($insertData); });
And a helper function, where you see all the if I added, because sometimes I get an array instead of objects:
protected function prepareEmlQueryToBeInsertedToDB( Builder $items, Collection $columnMapping, Closure $callback, $orderBy = 'system.system_id' ) {