CodeSleeve / laravel-stapler

Stapler-based file upload package for the Laravel framework.
MIT License
557 stars 109 forks source link

Object of class Codesleeve\Stapler\Attachment could not be converted to string #64

Open numnine opened 9 years ago

numnine commented 9 years ago

Hi,

I use Laravel 4.2, Laravel-stapler 1.0.03. I got this error when saving model that use laravel-stapler:

exception 'ErrorException' with message 'Object of class Codesleeve\Stapler\Attachment could not be converted to string' in /src/vendor/laravel/framework/src/Illuminate/Support/helpers.php:900

Here is my model:

use Codesleeve\Stapler\ORM\StaplerableInterface;
use Codesleeve\Stapler\ORM\EloquentTrait;

class Article extends Elegant implements StaplerableInterface{

    use EloquentTrait;

    /**
     * Fillable 
     */
    protected $fillable = ['image', 'title', 'summary', 'content'];

   public function __construct(array $attributes = array()) {
        $this->hasAttachedFile('image', [
            'styles' => [
                'medium' => '300x300',
                'thumb' => '100x100'
            ]
        ]);

        parent::__construct($attributes);
    }

}

The request info:

chrisatomix commented 9 years ago

Me too, this has killed one of my sites, I'm currently trying to rollback and figure out what update has caused this. Edit: Rolling back to codesleeve/laravel-stapler 1.0.0 in Composer caused codesleeve/laravel to rollback from 1.0.04 to 1.0.0, this seems to have fixed the problem for me.

    "require": {
        "laravel/framework": "4.2.*",
        "loic-sharma/profiler": "1.1.*",
        "nesbot/Carbon": "*",
        "anahkiasen/former": "3.5.6",
        "artdarek/oauth-4-laravel": "dev-master",
        "codesleeve/laravel-stapler": "1.0.0",
        "laravelbook/ardent": "dev-master"
    },
tabennett commented 9 years ago

So this is happened when you weren't uploading a file? Is there anyway I can see what's going on in your controller method where you're saving the record at? Can you give me a dd() of your model object right before you save? Off the top of my head I don't know what's causing this to happen, but I certainly don't want to have regression errors like this floating around in the codebase. Thx!

chrisatomix commented 9 years ago

It's quite possible this is a compatibility issue against the Ardent library I'm using for Models. It essentially takes Input::all() and binds it against the Model ("Auto Hydration"), runs validation, then saves it or returns an error.

The RESTful controller code looks like this:

public function store($slug) {

  $user = new User;

  if($user->save()) {
    // Success
    $msgtype = 'success';
    $msg     = 'User has been Created';
    return Redirect::to('users/'.$user->id.'/edit')->with($msgtype, $msg);
  }
  else {
    // Failed
    $msg     = 'User could not be Created';
    $msgtype = 'error';
    $errors  = $user->errors()->toArray();
    return Redirect::to('users/create')->withErrors($errors)->withInput()->with($msgtype, $msg);
  }
}

The save() method on the User model (which extends Ardent and implements Stapler) does everything at once (bind input, run validation, save to DB, return success/failure with errors).

@numnine may have something similar, his Article class extends "Elegant". I'm guessing he's implemented something like this for his models: http://daylerees.com/trick-validation-within-models

jaxx05 commented 7 years ago

Is a fix already available for this?

I am using php 7 laravel 5, but still got this error...

YulKard commented 7 years ago

Yes, a similar problem. If the image was not loaded when creating the record, then the error "Object of class Codesleeve \ Stapler \ Attachment could not be converted to string". What to do?

mcerezo2012 commented 7 years ago

I have the same issue, any update on this?

tabennett commented 7 years ago

Which version of Laravel are you folks using? Are you all using Ardent or is this a compatibility issue with 5.5?

YulKard commented 7 years ago

@tabennett I'm using version 5.5

brunodevel commented 7 years ago

I have the same problem in Laravel 5.5

mcerezo2012 commented 7 years ago

@tabennett I am using "laravel/framework": "5.5.*"

jaxx05 commented 7 years ago

Same, laravel 5.5

jaxx05 commented 7 years ago

by the way, I am not using ardent

tabennett commented 7 years ago

Ok, I thought that was weird that you would all be suing Ardent. I'm going to patch this tomorrow evening when I get off work, but I may not be able to get it out until this weekend. PR's are always welcome too. Regardless, I'll have a fix out as soon as I can.

Newsourcing-R commented 7 years ago

I using laravel 5.5 but it gives the same error. i am stuck with the code

tabennett commented 7 years ago

This is happening because Eloquent\Model (as of 5.5) is now using $this->getAttributes() instead of $this->attributes when generating the attributes array that will be used to update a model (this issue only seems to be happening when performing updates; When performing inserts $this->attributes is still used and that's a bit inconsistent/weird too).

For reference purposes, the EloquentTrait that comes with Stapler has a method on it that overrides the getAttributes() method to included any attached files that are defined on the model so that they appear as properties: https://github.com/CodeSleeve/stapler/pull/94

I feel like this is more an issue with consistency regarding Eloquent, not Stapler and atm I'm not quite sure the best way to go about resolving this. I may try and talk to Taylor about this and see if he'd be open to a PR to resolve this. If not, I may have to drop a major release that only supports 5.5 going forward, but I would rather not do that right now.

Regardless, for the time being you can just override the getAttributes() method on your model to not include the attachments defined on it (this effectively bypasses the method defined on the EloquentTrait):

/**
     * Get all of the current attributes on the model.
     *
     * @return array
     */
    public function getAttributes()
    {
        return parent::getAttributes();
    }

Or you can just write your own trait that doesn't include that method and then just use your trait in place of the EloquentTrait.

mostafaznv commented 6 years ago

thanks, fix worked for me.

lookitsatravis commented 6 years ago

Another fix is to modify the results of getDirty and remove Codesleeve\Stapler\Attachment instances on models which use attachments. getDirty is only run on updates and is where the issue is originating. So, something like:

    public function getDirty()
    {
        $dirty = parent::getDirty();

        return array_filter($dirty, function ($var) {
            return !($var instanceof \Codesleeve\Stapler\Attachment);
        });
    }

Used this in a project and was able to keep the decorated getAttributes() result. I put it into a trait along with other Stapler specific code and was able to update without much trouble.