简体   繁体   中英

PHP: Slim Framework/Eloquent ORM mass assignment error

I am using eloquent with slim framework outside of laravel, I have controllers that help perform CRUD operations. When I try to perform mass assignment operation Eloquent throws an error saying:

SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed:
 emoji.name (SQL: insert into "emoji" ("user_id", "updated_at", "created_at") 
values (1, 2016-01-02 02:56:43, 2016-01-02 02:56:43))

Bellow is my controller and Model:

public function create(ServerRequestInterface $request, ResponseInterface $response)
{
    $data   =   $request->getParsedBody();
    $uid    =   $data['uid'];
    $keywords   =   $data['keywords'];

    $body   =   $response->getBody();

        $user   =   User::find($uid);
        $user->emojis()->create([
            'name'  =>  $data['name'],
            'char'  =>  $data['char'],
            'category'  =>  $data['category'],
        ]);
//            $emoji = new Emoji();
//            $emoji->name  =  $data['name'];
//            $emoji->char  =  $data['char'];
//            $emoji->category  =  $data['category'];
//            $emoji->save();
        return $response;
    }

The application works when I use the lines that are commented above, but not the other:

My model is below:

namespace BB8\Emoji\Models;
use BB8\Emoji\Models\BaseModel;

class Emoji  extends BaseModel
{
    protected $table    = 'emoji';
    protected $dates    = ['created_at', 'updated_at', 'deleted_at'];
    protected $fillable = array('name', 'char', 'category', 'created_at', 'updated_at', 'user_id');

public function user()
{
    return $this->belongsTo("BB8\Emoji\Models\User");
}

public function keywords()
{
    return $this->hasMany("BB8\Emoji\Models\EmojiKeyword");
}
}

When I var_dump($data) I get the below:

array (size=6)
  'name' => string 'Happy Face' (length=10)
  'char' => string ')' (length=1)
  'keywords' => 
    array (size=1)
      0 => string 'happy' (length=5)
  'category' => string 'Happy' (length=5)
  'created_by' => int 1
  'uid' => int 1

Below is my UserModel

namespace BB8\Emoji\Models;
use BB8\Emoji\Models\BaseModel;
class User extends BaseModel
{
public $timestamps = false;
protected $fillable = ['username', 'password', 'jit'];

public function emojis()
{
    return $this->hasMany('BB8\Emoji\Models\Emoji');
}

public static function auth($username, $password)
{
    $user       =   static::where('username', '=', $username)->first();

    if (isset($user->exists) && $user->exists) {
        if (strcmp(hash('sha256', $password), $user->password) == 0) {
            return $user;
        }
    }

    return false;
}



  public static function isAuthenticated($token)
    {
    }
  }

BaseModel.php :

 namespace BB8\Emoji\Models;
use BB8\Emoji\Database\Connection;

class BaseModel extends \Illuminate\Database\Eloquent\Model
{
    public function __construct()
    {
        $dotenv = new \Dotenv\Dotenv(__DIR__.'/../../');
        $dotenv->load();
    }
}

I have multi-triple checked my code without seeing what is wrong, yet it throws the constraint violation error. Is this a bug with eloquent or am I doing something wrong.

Looks like your BaseModel is the problem. Try changing your constuctor to this:

public function __construct(array $attributes = [])
{
    $dotenv = new \Dotenv\Dotenv(__DIR__.'/../../');
    $dotenv->load();

    parent::__construct($attributes);
}

Explanation:

Here is Laravel's original model's constructor.

public function __construct(array $attributes = [])
{
    $this->bootIfNotBooted();

    $this->syncOriginal();

    $this->fill($attributes);
}

It accepts an array of attributes and does a few things with it, but keep the fill method in mind.

Now, here is what you are doing to create your emoji:

$user->emojis()->create([
    'name'  =>  $data['name'],
    'char'  =>  $data['char'],
    'category'  =>  $data['category'],
]);

This calls the HasMany class' create method. I removed all but the line of code you want to focus on:

public function create(array $attributes)
{
    ...

    $instance = $this->related->newInstance($attributes);

    ...
}

This basically creates a new instance of your model and passing in the array of attributes. Essentially something like this:

new Emoji([
    'name'  =>  $data['name'],
    'char'  =>  $data['char'],
    'category'  =>  $data['category'],
]);

However, your constructor is not accepting an array of attributes like Laravel's models and that changes the actual behavior of models. The values are not being filled. The solution at the top should fix your problem. After you load the environment variables, it just defers back to Laravel's default behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM