Laravel中->toArray()转换Raw模型集合返回空数组问题
Hey there! The issue you're facing is because of how Laravel's toArray() method interacts with private properties in your Raw model. Let me break it down and show you how to fix it.
Why This Happens
Your Raw class uses private properties for its data fields, but Laravel's base Model class (which your Raw extends) can't access private properties from outside the Raw class itself.
When you look at the Collection without calling toArray(), your debug tool is probably showing you the raw instance objects (which can reflect private properties), but when you call toArray(), Laravel's default implementation only includes:
- Attributes stored in the model's internal
$attributesarray - Properties that are
protectedorpublicand marked as visible
Since your properties are private, they don't get included in the array output.
Fixes to Try
1. Use Laravel's Native Attribute System (Recommended)
This is the most "Laravel way" to handle model data. Ditch the explicit private properties and let Laravel manage your attributes:
Update your Raw class:
class Raw extends Model { protected $table = 'raws'; protected $casts = [ 'time' => 'datetime' ]; public $timestamps = ["time"]; // List attributes that can be mass-assigned protected $fillable = [ 'operationId', 'meterId', 'consoProd', 'timestep', 'unit', 'timestamp', 'value' ]; }
Update how you create Raw instances:
Instead of passing individual parameters, pass an associative array of attributes to the constructor:
collect($measures)->chunk(1000)->each(function ($raws) use ($meter) { $raws = $raws->map(function ($raw) use ($meter) { return new \App\Models\Raw([ 'operationId' => $meter['OperationID'], 'meterId' => $meter['ID'], 'consoProd' => $meter['ConsoProd'], 'timestep' => $meter['Timestep'], 'unit' => $meter['Unit'], 'timestamp' => $raw['t'], 'value' => $raw['d'] ]); })->toArray(); dd($raws); });
2. Convert Private Properties to Protected and Mark as Visible
If you want to keep explicit property declarations, change them to protected (so the parent Model can access them) and add them to the $visible array:
class Raw extends Model { protected $table = 'raws'; protected $casts = [ 'time' => 'datetime' ]; public $timestamps = ["time"]; // Switch from private to protected protected string $operationId; protected string $meterId; protected string $consoProd; protected string $timestep; protected string $unit; protected string $timestamp; protected string $value; // Tell Laravel to include these properties in serialization protected $visible = [ 'operationId', 'meterId', 'consoProd', 'timestep', 'unit', 'timestamp', 'value' ]; // Add a constructor to set these properties public function __construct( string $operationId, string $meterId, string $consoProd, string $timestep, string $unit, string $timestamp, string $value, array $attributes = [] ) { parent::__construct($attributes); $this->operationId = $operationId; $this->meterId = $meterId; $this->consoProd = $consoProd; $this->timestep = $timestep; $this->unit = $unit; $this->timestamp = $timestamp; $this->value = $value; } }
3. Override the toArray() Method
Explicitly define what gets included when converting the model to an array by overriding toArray():
class Raw extends Model { protected $table = 'raws'; protected $casts = [ 'time' => 'datetime' ]; public $timestamps = ["time"]; private string $operationId; private string $meterId; private string $consoProd; private string $timestep; private string $unit; private string $timestamp; private string $value; // Constructor to set private properties public function __construct( string $operationId, string $meterId, string $consoProd, string $timestep, string $unit, string $timestamp, string $value, array $attributes = [] ) { parent::__construct($attributes); $this->operationId = $operationId; $this->meterId = $meterId; $this->consoProd = $consoProd; $this->timestep = $timestep; $this->unit = $unit; $this->timestamp = $timestamp; $this->value = $value; } // Override toArray() to include your private properties public function toArray() { return [ 'operationId' => $this->operationId, 'meterId' => $this->meterId, 'consoProd' => $this->consoProd, 'timestep' => $this->timestep, 'unit' => $this->unit, 'timestamp' => $this->timestamp, 'value' => $this->value, // Include default model attributes if needed ...parent::toArray() ]; } }
Any of these approaches should fix the issue and make toArray() return the data you expect.
内容的提问来源于stack exchange,提问作者Juliatzin

