Crud: PostgreSQL base64_image needs stream_get_contents

Created on 2 Mar 2020  路  8Comments  路  Source: Laravel-Backpack/CRUD

Bug report

base64_image Widget:
With PostgreSQL a $table->binary('image') is a of the bytea type. Saving an Image with that works as expected but reading it after, doesn't seem to work as I get this error:

htmlspecialchars() expects parameter 1 to be string, resource given (View: /var/www/vendor/backpack/crud/src/resources/views/crud/fields/base64_image.blade.php)

What I did

Defined a $table->binary('image1'); for PostgreSQL and used the base64_image widget on top of it, saving works as expected but reading it after doesn't seem to work.

What I expected to happen

Reopen the Data with a saved image works.

What happened

Open fails with error message above.

What I've already tried to fix it

I have added the following code to before line 36:

            @elseif(isset($field['value']) && is_resource($field['value']))
                @php
                    $data = stream_get_contents($field['value']);
                @endphp
                <img data-handle="mainImage" src="{{ $data }}">

For me this works, but i'm not sure if this is the right way to fix it(tm).

Backpack, Laravel, PHP, DB version

PHP VERSION:

PHP 7.4.3 (cli) (built: Feb 26 2020 12:17:01) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

LARAVEL VERSION:

laravel/framework v6.17.1 The Laravel Framework.

BACKPACK VERSION:

backpack/crud 4.0.41 Quickly build an admin interfaces using Laravel 6, CoreUI, Boostrap 4 and jQuery.
backpack/generators 2.0.6 Generate files for laravel projects
backpack/permissionmanager 5.0.6 Users and permissions management interface for Laravel 5 using Backpack CRUD.

Database

PostgreSQL 11.7 Docker

Most helpful comment

@pcdummy you're doing fine, but stream_get_contents should be placed in your model.
https://laravel.com/docs/6.x/eloquent-mutators

use function stream_get_contents;

class YourModel
{
    /**
     * @param resource $value
     * @return string
     */
    public function getYourAttributeName($value)
    {
        return stream_get_contents($value);
    }
}

Or in Laravel 7 you can use "custom casters" - https://laravel.com/docs/7.x/eloquent-mutators#custom-casts

All 8 comments

Hello there! Thanks for opening your first issue on this repo!

Just a heads-up: Here at Backpack we use Github Issues only for tracking bugs. Talk about new features is also acceptable. This helps _a lot_ in keeping our focus on improving Backpack. If you issue is not a bug/feature, please help us out by closing the issue yourself and posting in the appropriate medium (see below). If you're not sure where it fits, it's ok, a community member will probably reply to help you with that.

Backpack communication mediums:

  • Bug Reports, Feature Requests - Github Issues (here);
  • Quick help (_How do I do X_) - Gitter Chatroom;
  • Long questions (_I have done X and Y and it won't do Z wtf_) - Stackoverflow, using the backpack-for-laravel tag;

Please keep in mind Backpack offers no official / paid support. Whatever help you receive here, on Gitter, Slack or Stackoverflow is thanks to our awesome _awesome_ community members, who give up some of their time to help their peers. If you want to join our community, just start pitching in. We take pride in being a welcoming bunch.

Thank you!

--
Justin Case
The Backpack Robot

Hello @pcdummy , thanks for reporting in.

I am not a PostGres user, maybe you could help me out here.

$table->binary is an alias for BLOB (atleast mysql), what is produced in PostGres?

Why it return a resource instead of the usual value ? Is some switch you can have on your database to return a resource instead of the base64 encoded image?

Best,
Pedro

Hi @pxpm ,

I'm also not a PostGres Pro, but let's try to fix that. I didn't change anything on the Database Docker Image.

In PostGres is binary a bytea field.

Maybe this gives some info?

@pxpm

If you want I share you the code somewhere privat.

Hello! According to the PDO PGSQL documentation https://www.php.net/manual/en/ref.pdo-pgsql.connection.php The bytea fields are returned as streams (Note section). I think the casting of attributes is out of scope of this package. It should be done in the Model layer ($casts or in getter).

@codercms I'm doing it wrong?

@pcdummy you're doing fine, but stream_get_contents should be placed in your model.
https://laravel.com/docs/6.x/eloquent-mutators

use function stream_get_contents;

class YourModel
{
    /**
     * @param resource $value
     * @return string
     */
    public function getYourAttributeName($value)
    {
        return stream_get_contents($value);
    }
}

Or in Laravel 7 you can use "custom casters" - https://laravel.com/docs/7.x/eloquent-mutators#custom-casts

@codercms
Sorry for the long delay.

Thank you, this works nice for me.

Was this page helpful?
0 / 5 - 0 ratings