Francisunoxx
Francisunoxx

Reputation: 1458

How to create two Foreign Key on pivot table linked to one Primary Key

I'm trying to implement where I need to insert or save the current user that logged in. Inserting the recipient into user_id column works well but I need to manipulate who send the data I need to get the user id. I have two tables users and documents with a pivot table document_user.

users table

 Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('email');
        $table->string('username');
        $table->string('password');
        $table->string('remember_token');
 });

documents table

Schema::create('documents', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->text('content');
        $table->integer('category_id')->unsigned();
        $table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
        $table->timestamps();
    });

document_user - pivot table

Schema::create('document_user',function (Blueprint $table)
    {
        $table->increments('id');
        $table->integer('user_id')->unsigned();
        $table->integer('document_id')->unsigned();

        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->foreign('document_id')->references('id')->on('documents')->onDelete('cascade');
        $table->dateTime('dateReceived')->default(DB::raw('CURRENT_TIMESTAMP'));
    });

DB Design:

DB

Note! I only insert few column in my users table migration just to save a line of text.

Model

User

public function documents()
{
    return $this->belongsToMany('App\Models\Document', 'document_user', 'user_id', 'document_id');
}

Document

public function recipients()
{
    return $this->belongsToMany('App\Models\User', 'document_user', 'document_id', 'user_id');
}

Inserting records based on the user's choice to pivot table works well. But when I try to rollback my migration and alter my pivot table to this.

$table->integer('sender_id')->unsigned();
$table->foreign('sender_id')->references('id')->on('users')->onDelete('cascade');

I get a error it says:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`webdev`.`document_user`, CONSTRAINT `document_user_sender_id_foreign` FOREIGN KEY (`sender_id`) REFERENCES `users` (`id`) ON DELETE CASCADE) (SQL: insert into `document_user` (`document_id`, `user_id`) values (34, 10))

How can I achieve inserting the current user in my pivot table? So I can track who sends and receive the data. Any help would appreciated! Cheers!

UPDATE 1:

Thanks to @Dastur for solving my issue.

document_user table

Schema::create('document_user',function (Blueprint $table)
    {
        $table->increments('id');
        $table->integer('user_id')->unsigned();
        $table->integer('document_id')->unsigned();

        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->foreign('document_id')->references('id')->on('documents')->onDelete('cascade');

        $table->unsignedInteger('sender_id')->nullable();
        $table->foreign('sender_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');


        $table->dateTime('dateReceived')->default(DB::raw('CURRENT_TIMESTAMP'));
    });

I'm just having a hard time getting the id of the current user and insert this into sender_id column. Still don't have any idea to do this because I need to tracked the created documents of the users.

DocumentController

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Models\Document;
use App\Models\User;
use DB;
use Auth;

class DocumentController extends Controller
{

public function getDocuments()
{
    //GETTING ALL THE ID OF THE USERS IN THE DATABASE EXCEPT THE ID OF CURRENT USER.
    $resultRecipient = DB::table('users')->where('id', '!=', Auth::id())->get();


    //GETTING ALL THE CATEGORIES.
    $resultCategory = DB::table('categories')->get();

    //VIEW
    return view ('document.create')->with('resultRecipient', $resultRecipient)->with('resultCategory', $resultCategory);
}

public function postDocuments(Request $request)
{

    $this->validate($request,
    [
        'title' => 'required|alpha_dash|max:255',
        'content' => 'required',
        'category_id' => 'required',
        'recipient_id' => 'required',
    ]);


    $document = new Document();
                                //Request in the form
    $document->title = $request->title;
    $document->content = $request->content;
    $document->category_id = $request->category_id;

    $document->save();
    $document->recipients()->sync($request->recipient_id, false);

    return redirect()->back();  
}

}

UPDATE 2: According to @Dastur I need to create a another Model for my pivot table which is document_user.

UserDocument (Model)

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class UserDocument extends Model
{
protected $table = 'document_user';
}

Upvotes: 2

Views: 1034

Answers (1)

Dastur
Dastur

Reputation: 714

I looked around a bit online, and found this post on laracasts: http://laravel.io/forum/09-18-2014-foreign-key-not-saving-in-migration. Also, this error is normally thrown when your trying to get a null value from another table and put it into a row that isn't nullable.

Edit:

What your doing here is very strange, I still think the pivot table isn't a smart option. Here's exactly what I would do:

Migrations:

First, I would create my users migration, simple enough:

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('email');
    $table->string('username');
    $table->string('password');
    $table->rememberToken();
});

Next I would create my documents table:

Schema::create('documents', function(Blueprint $table) {
    $table->increments('id');
    $table->string('title');
    $table->text('content');
    $table->integer('category_id');
    $table->integer('user_id');
    $table->integer('sender_id');
    $table->dateTime('dateRecieved')->default(DB::raw('CURRENT_TIMESTAMP'));
    $table->timestamps();
});

Models:

In your user and category model you need the following method:

public function documents() {
    $this->hasMany(/* Path to your document model */);
}

Finally, in your document model you need the following methods:

public function category() {
    $this->belongsTo(/* Path to your category model */);
}

public function user() {
    $this->belongsTo(/* Path to your user model */);
}

Document Controller

public function postDocuments(Request $request)
{

    $this->validate($request,
    [
        'title' => 'required|alpha_dash|max:255',
        'content' => 'required',
        'category_id' => 'required',
        'recipient_id' => 'required',
    ]);

    /*
     * This part not exactly sure what to do, because of I don't know what
     * know what the difference is between the sender and the user, please
     * elaborate.
     */

}

Upvotes: 2

Related Questions