简体   繁体   中英

Laravel Eloquent Relationships - Integrity constraint violation

I have 3 models: Priority, Task and User

Priority

  • can be assigned to many tasks
  • belongs to one user

Code ...

class Priority extends Model
{
    protected $fillable = ['name', 'hexcolorcode'];

    protected $casts = [
        'user_id' => 'int',
    ];

    public function task()
    {
        return $this->hasMany(Task::class);
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Task

  • has one priority assigned
  • belongs to one user

Code ...

class Task extends Model
{
    protected $fillable = ['name'];

    protected $casts = [
        'user_id' => 'int',
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function priority()
    {
        return $this->hasOne(Priority::class);
    }
}

User

  • can have many tasks
  • can have many priorities

Code ...

class User extends Authenticatable
{

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    public function tasks()
    {
        return $this->hasMany(Task::class);
    }

    public function priorities()
    {
        return $this->hasMany(Priority::class);
    }
}

TaskController

class TaskController extends Controller
{
    protected $tasks;

    private $priorities;

    public function __construct(TaskRepository $tasks, PriorityRepository $priorities)
    {
        $this->middleware('auth');
        $this->tasks = $tasks;
        $this->priorities = $priorities;
    }

    public function index(Request $request)
    {
        return view('tasks.index', [
            'tasks' => $this->tasks->forUser($request->user()),
            'priorities' => $this->priorities->forUser($request->user())
        ]);
    }

    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required|max:255',
            'description' => 'required',
            'priority' => 'required'
        ]);

        $request->user()->tasks()->create([
            'name' => $request->name,
            'description' => $request->description,
            'priority_id' => $request->priority
        ]);

        return redirect('/tasks');
    }

    public function edit(Task $task)
    {
        $this->authorize('edit', $task);

        return view('tasks.edit', compact('task'));
    }

    public function update(Request $request, Task $task)
    {
        $this->validate($request, [
            'name' => 'required|max:255',
        ]);

        $task->update($request->all());
        return redirect('/tasks');
    }

    public function destroy(Request $request, Task $task)
    {
        $this->authorize('destroy', $task);

        $task->delete();

        return redirect('/tasks');
    }
}

Error

Now when I want to store a task it gives me following error:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails ( tasks . tasks , CONSTRAINT tasks_priority_id_foreign FOREIGN KEY ( priority_id ) REFERENCES priorities ( id )) (SQL: insert into tasks ( name , user_id , updated_at , created_at ) values (test task, 1, 2016-05-01 14:11:21, 2016-05-01 14:11:21))

Is it possible with this construct or do I have to use Polymorphic Relations between priority table and tasks table?

My Tables

Database Model Picture: http://picpaste.de/mysql-kBH4tO5T.PNG

class CreatePrioritiesTable extends Migration
{

    public function up()
    {
        Schema::create('priorities', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned();
            $table->char('name');
            $table->char('hexcolorcode', 7);
            $table->timestamps();
            $table->foreign('user_id')->references('id')->on('users');
        });
    }
}


class CreateTasksTable extends Migration
{

    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned();
            $table->string('name');
            $table->text('description');
            $table->integer('priority_id')->unsigned();
            $table->timestamps();
            $table->foreign('priority_id')->references('id')->on('priorities');
            $table->foreign('user_id')->references('id')->on('users');
        });
    }
}

UPDATE

PriorityController

class PriorityController extends Controller
{

    protected $priorities;

    public function __construct(PriorityRepository $priorities)
    {
        $this->middleware('auth');
        $this->priorities = $priorities;
    }

    public function index(Request $request)
    {
        return view('priority.index', [
            'priorities' => $this->priorities->forUser($request->user()),
        ]);
    }

    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required|max:255',
            'hexcolorcode' => 'required|max:7'
        ]);

        $request->user()->priorities()->create($request->all());

        return redirect('/priorities');
    }

    public function edit(Priority $priority)
    {
        $this->authorize('edit', $priority);

        return view('priority.edit', compact('priority'));
    }

    public function update(Request $request, Priority $priority)
    {
        $this->validate($request, [
            'name' => 'required|max:255',
            'hexcolorcode' => 'required|max:7'
        ]);

        $priority->update($request->all());
        return redirect('/priorities');
    }

    public function destroy(Request $request, Priority $priority)
    {
        $this->authorize('destroy', $priority);

        $priority->delete();

        return redirect('/priorities');
    }
}

In your store method. The create method it says :

user->tasks(). This bit will only inserting data in user and tasks table. Thats why you have foreign key error. As you are not updating one of your tables(priority) and also you have added foreign keys in tables as i csn see from migration.

What you are trying to achieve is right if you had a pivot table called task_user where you had userid, taskid and a priority_id. That would be perfect as you would simply update the priority column with userid and taskid. Thats one way but it will require few changes OR you can insert data into user and tasks table seperately for which you will need to just change the query. What do you prefer? I can show you an example for which you like.

    //for Priority
        // store
        $priorities = new Priority;
        $priorities->name       = Input::get('priority_name');
        $priorities->hexcolorcode      = Input::get('hexcolorcode');
        $priorities->save();

        $priority = Priority::select('id')->orderBy('created_at', 'desc')->first();

    //for Task
    $tasks = new Task;
        $tasks->name       = Input::get('task_name');
        $tasks->priority_id      = Input::get('priority');
        $priorities->save();

        // redirect
        return Redirect::to('some view please change this');

Please explain views or show screenshots, how are you handling it. For now, I have given you the solution with one controller handling priorities and tasks.

SOLUTION

I added the priority_id attribute to the fillable array inside the task model.

protected $fillable = ['name', 'description', 'priority_id'];

I had an understanding problem, because user_id is assigned automatically from the framework, but it isn't specified in fillable array. That's because I say $request->user->tasks->create(); it is assigned from the framework, but priority_id is assigned through the user, so it is mass assigned and need to be specified in the fillable array.

@Murlidhar Fichadia

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