3

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.

George
  • 3,757
  • 9
  • 51
  • 86
  • 1
    $uid = $data['uid']; <<< You've this on top and protected $fillable = array( 'user_id'); <<< this at bottom. – manshu Jan 02 '16 at 02:23
  • @manshu yep, I was actually using it to debug, but I do not think it changes anything, the user_id is filled through the relationship of user->emojis()->create() – George Jan 02 '16 at 02:26
  • @ErenArdahan I have checked the database and there is no field left out, when I change all the fields to allow null it inserts only user_id, created_date and updated_date, meaning that the other data passed through the array are not captured in the create method – George Jan 02 '16 at 02:33
  • @ErenArdahan I have added the value when I var_dump $data to the question, there are actual values and $data['name'] is not null – George Jan 02 '16 at 02:40
  • you are not saving any value to database.. –  Jan 02 '16 at 02:45
  • @ErenArdahan uh, I think the save() method is called when you are dealing with an object you filled, not with the create() function – George Jan 02 '16 at 02:48
  • @ErenArdahan It also does not work, the Exception is thrown when the create method is called, so nothing after it will run. – George Jan 02 '16 at 02:57
  • From what I can tell, your posted code looks fine. Do you have anything that messes with the `$fillable` or `$guarded` attributes that you have not posted here? What does `$emoji = new Emoji(); print_r($emoji->isFillable('name'));` show? – patricus Jan 02 '16 at 03:40
  • @patricus nothing that I can see, exactly what I posted is what I have in the files – George Jan 02 '16 at 04:03
  • Does `isFillable('name')` return true? – patricus Jan 02 '16 at 04:05
  • @patricus yes `isFillable('name')` returns true – George Jan 02 '16 at 04:09
  • Would you paste your `User` model ? It seems an issue with the emojis() relationship, and could be related with the fact you are trying to store it before setting the relationship. Also, do you identify -as far as you have analyzed- the `19` of the SQL error related to anything? – alariva Jan 02 '16 at 04:14
  • @alariva I have added the user model – George Jan 02 '16 at 04:17
  • If you do `$emoji = new Emoji(['name' => $data['name'], 'char' => $data['char'], 'category' => $data['category']]);`, are the attributes set correctly? – patricus Jan 02 '16 at 04:23
  • @patricus no they are not, I just tried that too – George Jan 02 '16 at 04:31
  • Can you post your `Emoji` and `Users` table definitios with foreigns? – alariva Jan 02 '16 at 04:36
  • @alariva I have placed my project on cloud 9 so as not to populate the question with too much detail https://ide.c9.io/ramos16/laravel-error – George Jan 02 '16 at 04:38
  • If you do `$emoji = new Emoji(); $emoji->forceFill(['name' => $data['name'], 'char' => $data['char'], 'category' => $data['category']]);`, are the attributes set correctly? – patricus Jan 02 '16 at 04:39
  • @patricus it says `Call to undefined method Illuminate\Database\Query\Builder::forceFill()` – George Jan 02 '16 at 04:41
  • `protected $table = 'emoji';` but your db definition creates an `emojis` table. It's weird that the commented code could work, I think. – alariva Jan 02 '16 at 04:42
  • @alariva at this point I do not know what is weird, have been up all night trying to work this out, my brain hurts and I can't think right now, might need to sleep a bit :) – George Jan 02 '16 at 04:44
  • 1
    Sounds good, some rest always helps. But, just for giving a try for tomorrow, then. http://laravel.io/bin/PXNRk – alariva Jan 02 '16 at 04:48
  • Can you post your `BaseModel`? – Thomas Kim Jan 05 '16 at 17:11

1 Answers1

2

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.

Thomas Kim
  • 15,326
  • 2
  • 52
  • 42