Francisunoxx
Francisunoxx

Reputation: 1458

Sync method won't work using many to many relationship Laravel 5.2

I'm trying to attach the array of items that I have in my form to my junction table. I already given all the values stored in my tables using foreach loop. I loop this all in my select list.

Retrieve all records in tables:

$resultRecipient = DB::table('users')->where('id', '!=', Auth::id())->get();
return view ('document.create')->with('resultRecipient', $resultRecipient);

Form:

<div class = "form-group">

    <label for = "recipient_id" class = "control-label">To:</label>

    <select name = "recipient_id[]" multiple class = "form-control" id = "myUserList">

            @foreach ($resultRecipient as $list)
                <option value = "{{ $list->id }}">{{ $list->username }}</option>
            @endforeach

    </select>

</div>

Migration:

users

-id

-username

-password

documents

-id

-title

-content

-category_id - FK

recipients_documents (junction table)

-id

-senderUserId - FK reference to users

-recipientUserId - FK reference to users

-docu_id - FK reference to documents

My Models:

Document

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Document extends Model
{    

public function recipients()
{
    return $this->belongsToMany('Models\User');
}
}

User:

<?php

namespace App\Models;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;

class User extends Model implements AuthenticatableContract
{
use Authenticatable;

public function documents()
{
    return $this->belongsToMany('Models\Document');
}
}

DocumentController:

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();  
}

When I'm trying to attach the request in my form which is recipient_id but it error says. I just created a new folder in app named Models

Class 'Models\User' not found

Can anyone tell why I get this error? Any help would appreciated!

Cheers

UPDATE 1

I solved this error followed steps by @jaysingkar. But when I try to sync this after hitting the submit button it gives me a error.

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'webdev.document_user' doesn't exist (SQL: select user_id from document_user where document_id = 15)

But it insert in the document tables but in my juction table won't insert that I want to attach.

UPDATE 2 Thanks @jaysingkar and @mydo47 for the help and tips that you given. I already create document_user table (junction) I added a another Foreign Key which refenreces to users table.

Screenshot:

Many to many

As you can see here I linked two foreign key in the junction table. I want to insert the current user that logged-in in the user_id column. I have a form here which loop through my database records except the id of the current user that logged in.

Form:

<div class = "form-group">

<label for = "recipient_id" class = "control-label">To:</label>

<select name = "recipient_id[]" multiple class = "form-control" id = "myUserList">

        @foreach ($resultRecipient as $list)
            <option value = "{{ $list->id }}">{{ $list->username }}</option>
        @endforeach

</select>

Migration for junction table:

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

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

Document Controller:

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();  
}

But when I try to submit it says. Is this valid that I can linked PK to two FK? I can insert the selected list in the document_user table but how can I insert the current user? Thanks for the help

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

UPDATE 3

I already get rid of the error so I created a unsignedInteger this column where the current user id will insert name sender_id

Migration update:

 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');


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

I can get the id of the current user that logged in. But I'm thinking how can I insert the id based on the submit of the user.

DocumentController:

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);

    if(\Auth::user()->id)
    {
        echo "You get the id";
    }
    else
    {
        echo "Failed";
    }

}

Database Screenshot:

enter image description here

Upvotes: 0

Views: 3014

Answers (3)

mydo47
mydo47

Reputation: 379

  1. Add classmap in composer.json :

    "classmap" : [ "database", "app\Models" ]

  2. Change in config\auth.php :

    'model' => 'App\Models\User' ,

  3. In User model :

    namespace App\Models;

  4. Update composer

Update Create new table document_user with document_id FK to documents and user_id FK to users.

Fix function recipients():

return $this->belongsToMany('App\Models\User', 'document_user', 'document_id', 'user_id');

Fix function document() :

return $this->belongsToMany('App\Models\Document', 'document_user', 'user_id', 'document_id');

Upvotes: 1

jaysingkar
jaysingkar

Reputation: 4435

Along with @Marcin 's answer,
You would need to use "App\Models\User" instead of "Models\User"

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

Update for

Base table or view not found:


You would need document_user table to be present in DB in order to work with many-to-many relationship. The table must contain the document_id and user_id columns.

Laravel's documents have explained this here

To define this relationship, three database tables are needed: users, roles, and role_user. The role_user table is derived from the alphabetical order of the related model names, and contains the user_id and role_id columns.

Upvotes: 2

Marcin Nabiałek
Marcin Nabiałek

Reputation: 111829

There might be many reasons for that, I would assume you moved User model into Models directory but you haven't changed namespace.

The beginning of file should look like this:

<?php

namespace App\Models;

class User
{
  // ...

Upvotes: 0

Related Questions