I'm trying to insert the username for the author from the users table into the posts table, but it's not letting me. I'm using Backpack for my CRUD, and I'm not sure what I'm doing wrong. I'm also not sure as to why the ID is appearing for the username instead of the username itself, as the correct username(s) are appearing in the select box. I am getting the following error:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails (idf.posts,
CONSTRAINT posts_author_foreign FOREIGN KEY (author) REFERENCES
users (username)) (SQL: insert into posts (title, content,
author, updated_at, created_at) values (aasdasd, asdasda,
1, 2018-12-24 04:25:23, 2018-12-24 04:25:23))
I'm running SQL 8, Laravel 5.7, and PHP 7.1.19. So far I've tried clearing the cache via the artisan command and performing a migrate:refresh (which is fine because I have no legitimate data).
In App\Models\Post:
protected $table = 'posts';
protected $primaryKey = 'id';
protected $foreignKey = 'author';
public $timestamps = true;
protected $guarded = ['id'];
protected $fillable = [
'title', 'content', 'author'
];
protected $hidden = [];
protected $dates = [];
public function user()
{
return $this->hasOne('App\Models\User');
}
Posts Table Creation:
Schema::create('posts', function (Blueprint $table) {
$table->increments('id')->unique();
$table->string('title')->required();
$table->longtext('content')->required();
$table->string('author');
$table->foreign('author')->references('username')->on('users');
$table->timestamps();
});
Select Box on PostCrudController:
$this->crud->addField([
'label' => "Author",
'type' => 'select2',
'name' => 'author', // the db column for the foreign key
'entity' => 'user', // the method that defines the relationship in your Model
'attribute' => 'username', // foreign key attribute that is shown to user
'model' => "App\Models\User", // foreign key model
'options' => (function ($query) { //limit to only admins
return $query->orderBy('username', 'ASC')->where('admin', 1)->get();
}),
]);
In all, I just need to allow the username from the select dropdown to be inserted into the author column, which would be the username for the user itself.
What I understood from your problem is that you are trying to add a relation between your posts table and users.
So from my point of view, instead of using foreign migration like
$table->foreign('author')->references('username')->on('users');
you should make the foreign key like this
$table->unsignedInteger('user_id')
$table->foreign('user_id')
->references('id')
->on('users')
->onUpdate('CASCADE')
->onDelete('CASCADE');
And then you can pass the id of the user in the user_id column to establish the relationship between these two.
The benefits of using the foreign key like this are
The id column is a primary key in users table so it will uniquely Identify your user
and it is an unsigned integer so it will be easy for the SQL engine to index this.
Now for fatching your data you can definitely the following eloquent relation in your Post model
public function user() {
return $this->belongsTo('App/User');
}
And while fatching posts you can use eager loading (with() eloquent method) something like
$posts = Post:::with('user)->get();
Now with all of the posts you can access any associated user information for example:
forach ($posts as $post){
$userName = $post->user->name;
}
Hope this will help.
Related
I have been facing a problem in my project. I have a belongsto many relation with additional field.
For example I have two table User and Social table and a pivot table named social_user. Here my user model is
public function socialinfos() {
return $this->belongsToMany(Social::class)->withPivot('id')->whereNull('deleted_at');
}
And my social_user table is
Schema::create('social_user', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id');
$table->string('social_id')->nullable();
$table->string('url')->nullable();
});
Here I my belongs to many relation has an additional url field which is submitted by user. When I want to add this information in my database it is not working well. It shows error
Array to string conversion (SQL: insert into `social_user` (`social_id`, `url`, `user_id`) values (2, jahid56, 9))
Here is What I tried
$user = Auth::user();
$speakers = $request->get('provider'); // related ids
$pivotData = array_fill(0, count($speakers), ['url' => $request->get('social')]);
$syncData = array_combine($speakers, $pivotData);
if ($request->get('provider')) {
$user->socialinfos()->sync($syncData);
} else {
$user->socialinfos()->sync([]);
}
Please help me solving this
I assume you have this:
Social <--> Social-User['id', 'social_id', 'user_id', 'url'] <--> User
In order to attach a Social to User you need could do this:
Auth::user()->socialInfos()->attach($social_id, ['url' => 'facebokk.com/user']);
Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (projects.posts, CONSTRAINT posts_user_id_foreign FOREIGN KEY (user_id) REFERENCES users (id))
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->engine ='InnoDB';
$table->increments('id');
$table->string('jobtitle');
$table->string('location');
$table->string('jobtype');
$table->string('jobdesc');
$table->string('companyname');
$table->string('howto');
$table->integer('user_id')->unsigned();
$table->timestamps();
});
Schema::table('posts', function($table) {
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
Post model
class Posts extends Model
{
//
protected $fillable =[
'jobtitle',
'location',
'jobtype',
'jobdesc',
'companyname',
'howto',
'user_id'
];
protected $guarded = array();
public static $rules = array();
public function users()
{
return $this->belongsTo('App\User');
}
}
user model
public function posts()
{
return $this->hasMany('App\Posts','user_id ');
}
You don't need to declare a foreign key in the MySQL side, you have at least to create a user_id column (which you do have) that will be used by Laravel as a foreign key.
To get user who created the post simply reference the relationship.
$owner = \App\Post::user->name; // get the user who created the post.
Your table definition is telling MySQL that it must have a value in posts.user_id and that value must exist in the id column in the users table. This is basic referential integrity.
Assuming that table users has the following :
| id | name |
| 1 | Josie |
| 2 | Jeff |
Then the following insert into table posts will fail because table users does not have the corresponding user with id 5.
INSERT INTO posts
(`jobtitle`,
`location`,
`jobtype`,
`jobdesc`,
`companyname`,
`howto`,
`user_id`)
VALUES (
'manager',
'some city',
'cook',
'cooks food',
'Very good restaurants',
'How we do things',
5)
To solve this, you must determine the user before you attempt to insert into table posts and set the user_id column correctly.
I'm using Laravel 5.2 and MySQL.
I'm developing a project to get used to Laravel. My project is a phonebook, where you can store contact info on a table. But to do this, you need to be logged in the system, which I made using the make:auth command. Simplicity, it seems.
In my "Users" table I have the field ID. This table is used to store the user info so they can login and access the contact stuff.
In my "Contacts" table, which is where I store my contacts, is a column named "Created By" that is supposed to take the field ID from the users table, just to reference who was the creator of said contact.
But here is the thing:
The contacts table isn't migrating, it doesn't matter what I do.
I already dropped both tables and made them from scratch, the USERS first, because it has the referenced primary key, and then the CONTACTS, with the foreign field set. I even dropped my models and created them using the same order above, because who knows what might work.
Here is my migration files:
USERS MIGRATION
----- ... -----
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email', 191)->unique();
$table->string('password', 191);
$table->timestamp('updated_at');
$table->timestamp('created_at');
$table->rememberToken();
});
}
----- ... -----
As stated, the table has the ID field I am referencing in my other table.
CONTACTS MIGRATION
----- ... -----
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id', false, true);
$table->foreign('user_id')->references('id')->on('users');
$table->string('image');
$table->string('name');
$table->string('lastname');
$table->string('email', 191)->unique();
$table->string('phone',191)->unique();
$table->string('address');
$table->string('description', 255);
});
----- ... -----
The field user_id references the id field in the table users, as stated. The second parameter is setting incrementing to false and the third is setting unsigned to true.
Even if I make the default style ($table->integer('user_id')->unsigned(); --- $table->foreign.....;), the migration isn't working.
I even made the foreign field in a separated schema from this main body, like so:
Schema::table('contacts', function($table) {
$table->foreign('user_id')->references('id')->on('users');
});
But even like this, the migration isn't working.
I really don't know what is happening.
This is my Contact Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
// Getting the user associated with the contact
// which means, I hope,
// The user that created the contact entry in the table 'contacts'
public function user()
{
return $this->belongsTo('App\User');
}
// protected $table = 'contacts';
// not using an id field
// could this be the error?
// dunno
// isn't laravel making an automatic id field?
// dunno too
public $fillable = array('name', 'lastname', 'email', 'phone', 'address');
// public $foreign = ('user_id');
//added because of error at migration
public $timestamps = false;
}
This is my User Model
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
// Putting it in simple terms
// Hopefully, this will return
// the many contacts that said user recorded in the 'contacts' table
public function contact()
{
return $this->hasMany('App\Contact');
}
// protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
UPDATE
I just rolled back my migrations and use the migrate command again, and it worked this time.
I can register an user, so the auth::check works and I can see the view with the form to insert a contact in the CONTACTS table.
But when I click the button to save, I get the following error:
2/2
QueryException in Connection.php line 729:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`phonebook`.`contacts`, CONSTRAINT `contacts_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`))
1/2
PDOException in Connection.php line 457:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`phonebook`.`contacts`, CONSTRAINT `contacts_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`))
I still don't know what is going on.
These are some of the ways you can add a contact and attach the user. Since you solved the foreign key issue, i won't address that.
$user = \Auth::user();
$user->contact()->create([
'name' => $request->input('name'),
'lastname' => $request->input('lastname'),
'email' => $request->input('email'),
'phone' => $request->input('phone'),
'address' => $request->input('address')
]);
Or
\App\Contact::create([
'name' => $request->input('name'),
'lastname' => $request->input('lastname'),
'email' => $request->input('email'),
'phone' => $request->input('phone'),
'address' => $request->input('address'),
'user_id' => \Auth::id()
]);
Or
$contact = new \App\Contact;
$contact->name = $request->input('name');
$contact->lastname = $request->input('lastname');
$contact->email = $request->input('email');
$contact->phone = $request->input('phone');
$contact->address = $request->input('address');
$contact->user_id = \Auth::id();
$contact->save();
Also add user_id to the $fillable property when you mass assign the value (second option shown above).
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:
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:
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.
Add classmap in composer.json :
"classmap" : [
"database",
"app\Models"
]
Change in config\auth.php :
'model' => 'App\Models\User' ,
In User model :
namespace App\Models;
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');
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
{
// ...
I get an error when i try to insert a role.I have found some solution of this issue in StackOverFlow but all those does not solve my problem.
I am trying to get id from roles table into roleID column of user_roles table.Here i am using Query Builder of Laravel 5.2.
public function store(Request $request)
{
//
$role = [];
$role['role'] = $request->input('role');
$data= Role::create($role);
$id= $data->id;
DB::table('user_roles')->insert([
'roleID' => $id
]);
//return $data;
return redirect(route('allRole'));
}
When i insert any role then it insert new data in roles table but i am not getting roleID in user_roles table.I get an error:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails
(`amarjobs`.`user_roles`, CONSTRAINT `fkuserRolesuserID` FOREIGN KEY
(`userID`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE
CASCADE) (SQL: insert into `user_roles` (`roleID`) values (14))
Where is the problem i have done? Thanks in advanced.
Searched result:
1. First Solution.
2. Second Solution.
As you can see your user_roles table required userID column & you aren't passing the field while inserting that's what generating the error.
DB::table('user_roles')->insert([
'roleID' => $id,
'userID' => $userId, //pass your userID here
]);
Also I like to mention couple of things you are naming your DB table column names in camel case which is bad you should be using underscores & as db sqls are generally case insensitive so using userID is equivalent to userid.
Also you are using DB::insert it will not insert any created_at or updated_at field or other eloquent features so I suggest you insert using eloquent model & using relations which is the beauty of laravel & eloquent active records
try like this
public function store(Request $request)
{
//
$role = [];
$role['role'] = $request->input('role');
$data= Role::create($role);
$userdata = User::all();
$user_id = $userdata->first()->id;
$id= $data->id;
DB::table('permissions')->insert([
'role_id' => $id
]);
DB::table('user_roles')->insert([
'roleID' => $id,
'userID' => $user_id
]);
//return $data;
return redirect(route('allRole'));
}
Here $userdata = User::all(); you are selecting all user do you want all your to have this role then you have to loop through on it & insert it. Or if you want first user to have this role then it's fine.
Also I suggest I think you should read more Laravels documentation to clear things.
It seems you are trying to insert only roleID to user_roles table.
But within in your given error it seems the user_roles TABLE has also userID field what is foreign key and connect with users (id) table.
As user_roles is a pivot table and it has both roleID and userID and both are foreign key. So while inserting with only roleID value it's trying to insert the userID with the NULL value what is not matched with user Table any of IDs that's why Integrity constraint Violated.
So inserting data in a right way would be, you have to provide VALID userID as well.
$id= $data->id;
DB::table('user_roles')->insert([
'roleID' => $id,
'userID' => $EXISTING_USER_ID
]);
I think, it will solve your problem.
in your above error, you are missing the userID field, which is must in relationship perspective. so you should pass the userID then your code will be working.
$role = [];
$role['role'] = $request->input('role');
$data= Role::create($role);
$id= $data->id;
DB::table('user_roles')->insert([
'roleID' => $id,
'userID'=>1, // pass userID with whom you wan to attach new roleID
]);
return redirect(route('allRole'));
here is advance version of using relationship method
Add these method in respective models
user model
public function userRoles(){
return $this->belongsToMany('App\Role','user_roles','userID','roleID');
}
role model
public function roleUsers(){
return $this->belongsToMany('App\User','user_roles','roleID', 'userID');
}
and do this for insertion of roles.
$user = App\User::find(1);
$user->roles()->attach($roleId);
$role = [];
$role['role'] = $request->input('role');
$data= Role::create($role);
$id= $data->id;
$user->userRoles()->attach(['
'roleID' => $id,
'userID'=>$user->id
']);
return redirect(route('allRole'));