framework: Eloquent unable to save Postgres arrays
- Laravel Version: v5.7.27
- PHP Version: 7.2.2
- Database Driver & Version: PostgreSQL 10.5
Description:
The eloquent code is treating a database array and a json object as if they are the same. But in PostGres the format for an array like an INTEGER[] needs formatting to be as
INSERT INTO schema.table ( field ) ( '{1,2,3}' );
but because of current setup using json_encode, the result is
INSERT INTO schema.table ( field ) ( '[1,2,3]' );
The minor but crucial difference being the [ and the {
Steps To Reproduce:
CREATE TABLE testschema.testtable (
arrayfield integer[]
);
with Model cast defining array:
use Illuminate\Database\Eloquent\Model;
class TestTable extends Model {
protected $casts = [
'arrayfield ' => 'array',
];
}
\App\Models\Incoming\TestSchema\Placement::updateOrCreate( [
'arrayfield' => [1,2,3]
] );
will generate…
insert into schema.testtable ( arrayfield ) values ([11])
which gives the error
Invalid text representation: 7 ERROR: malformed array literal: "[11]"
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 1
- Comments: 25 (11 by maintainers)
This is not supported. Eloquent can’t know whether you want to store a PostgreSQL array or a JSON string.
We could stop having the
arraycast as an alias forjsonand only use it for PostgreSQL arrays, but that would be a huge breaking change.You’ll have to add a custom accessor and mutator:
JSONandARRAYare specifically separate things. So yes the code that treats them the same never was correct. It was a never tested always broken scenario. Thejson_encodemethod cannot be used at all for a PostgresARRAY. Array’s can also be strings, example:CHARACTER VARYING[]which can contain those[ ] { }characters. It’s not just forINTEGER[]. And Eloquent specifically already knows by the$castwhether that field is anARRAYorJSON.So the lines like this…
from the
castAttributemethod inlaravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.phpwhich ignored the differences between those two data types, are the issue.
Since it seems that this isn’t really a bug but more of a request for more native Postgres support, I think it’s best that this is moved to the ideas repo.
ok but still this is not a conversation about
json, it’s about arrays. Not the Laravel specific idea to storejsoninto atextfield and call itarray. And anarrayfield is not injsonformat. Which is why this faked feature is breaking arrays.