admin管理员组

文章数量:1129151

I am storing ASCII plain-text content as zlib compressed BLOB in a pgsql BYTEA column.

My laravel schema definition for the table:

$table->binary('data')->nullable();

Here's my eloquent model class:

protected function casts(): array
{
    return [
        'data' => Compressed::class,
    ];
}

The custom casts attribute:

class Compressed implements CastsAttributes
{
    public function get(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        return blank($value) ? null : gzinflate($value);
    }

    public function set(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        return blank($value) ? null : gzdeflate($value);
    }
}

However, when I try to save the model, I get the following error:

SQLSTATE[22021]: Character not in repertoire: 7 ERROR: invalid byte sequence for encoding "UTF8": 0x82 CONTEXT: unnamed portal parameter $1 (Connection: pgsql, SQL: update "table" set "data" =.... 

I thought eloquent/PDO would automatically escape the bytea data. Anyways, I have updated the casting code to explicitly escape the data:

class Compressed implements CastsAttributes
{
    public function get(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        if (blank($value)) {
            return null;
        }

        $my_bytea = stream_get_contents($value);
        //$my_bytea = pg_unescape_bytea($my_bytea);

        return gzinflate($my_bytea);
    }

    public function set(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        return blank($value) ? null : pg_escape_bytea(gzdeflate($value));
    }
}

Now, I can save the data. But I cannot read it back. I'm getting the following error:

gzinflate(): data error

What am I doing wrong?

I am storing ASCII plain-text content as zlib compressed BLOB in a pgsql BYTEA column.

My laravel schema definition for the table:

$table->binary('data')->nullable();

Here's my eloquent model class:

protected function casts(): array
{
    return [
        'data' => Compressed::class,
    ];
}

The custom casts attribute:

class Compressed implements CastsAttributes
{
    public function get(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        return blank($value) ? null : gzinflate($value);
    }

    public function set(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        return blank($value) ? null : gzdeflate($value);
    }
}

However, when I try to save the model, I get the following error:

SQLSTATE[22021]: Character not in repertoire: 7 ERROR: invalid byte sequence for encoding "UTF8": 0x82 CONTEXT: unnamed portal parameter $1 (Connection: pgsql, SQL: update "table" set "data" =.... 

I thought eloquent/PDO would automatically escape the bytea data. Anyways, I have updated the casting code to explicitly escape the data:

class Compressed implements CastsAttributes
{
    public function get(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        if (blank($value)) {
            return null;
        }

        $my_bytea = stream_get_contents($value);
        //$my_bytea = pg_unescape_bytea($my_bytea);

        return gzinflate($my_bytea);
    }

    public function set(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        return blank($value) ? null : pg_escape_bytea(gzdeflate($value));
    }
}

Now, I can save the data. But I cannot read it back. I'm getting the following error:

gzinflate(): data error

What am I doing wrong?

Share Improve this question asked Jan 8 at 13:51 masrooremasroore 10.1k4 gold badges27 silver badges31 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I figured out the solution. Based on this repository (which ironically uses hex2bin/bin2hex)

Here's my casts class:

class Compressed implements CastsAttributes
{
    public function get(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        if (blank($value)) {
            return null;
        }

        if (is_resource($value)) {
            rewind($value);
            $value = stream_get_contents($value);
        }
        // $value = pg_unescape_bytea($value);

        return gzinflate($value);
    }

    public function set(Model $model, string $key, mixed $value, array $attributes): mixed
    {
        return blank($value) ? null : pg_escape_bytea(gzdeflate($value));
    }
}

本文标签: laravelCompressed data in binary column in eloquent phpStack Overflow