Delete all posts related to a user in laravel - php

this is my posts table
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->integer('category_id')->unsigned()->index();
$table->integer('photo_id')->default(0)->unsigned()->index();
$table->string('title');
$table->text('body');
$table->timestamps();
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
});
}
this is my users table
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->integer('role_id')->index()->unsigned()->nullable();
$table->integer('photo_id')->index()->default(0);
$table->boolean('is_active')->default(0);
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
these are the relations
public function posts() {
return $this->hasMany('App\Post');
}
public function user() {
return $this->belongsTo('App\User');
}
Delete code of the user
public function destroy($id)
{
$user = User::findOrFail($id);
if($user->photo_id !== 0) {
unlink(public_path() . $user->photo->path);
}
$user->delete();
Session::flash('deleted_user', 'The user has been deleted.');
return redirect('/admin/users');
}
Delete code of the post
public function destroy($id)
{
$post = Post::findOrFail($id);
if($post->photo_id !== 0) {
unlink(public_path() . $post->photo->path);
}
$post->delete();
return redirect('/admin/posts');
}
I am trying to delete all the posts related to a user when I delete a user.
For that, I am using foreign reference constraint in posts table as shown above
But it is not working when I delete the user. The posts are still there.
I dont know what I am doing wrong

This problem occurs most probably because the default table engine in your MySQL instance is set to MyISAM which doesn't support foreign keys. Trying to work with foreign keys on a MyISAM table would definitely not be a bug in Laravel. Although it would be nice if the Schema Builder could automatically set the engine to InnoDB if foreign keys are used.
so, use this line in your schema
$table->engine = 'InnoDB';
or alter the table with
ALTER TABLE table_name ENGINE=InnoDB;
May be help you.

Create you custom method like function destroyAllByUser()
and put the code like
DB::table('posts')->where('user_id', '=', 1)->delete();
I hope it may help

Delete user;
public function destroy($id)
{
$user = User::findOrFail($id);
if($user->photo_id !== 0) {
unlink(public_path() . $user->photo->path);
}
$user->posts->delete();
$user->delete();
Session::flash('deleted_user', 'The user has been deleted.');
return redirect('/admin/users');
}

A alternative way to solve that is to configure database.php file under laravel-project\config folder to work on InnoDB engine.
'mysql' => [
...
'engine' => 'InnoDB'
]
Now you don't need to worry when you using foreign keys...
REMEMBER - If you didn't configured this before you create your tables you should remigrate again.

Related

ERROR : how to get information to foreign key laravel 8

I cannot retrieve the username from the foreign key, please help me.
The user table contains a name field I think with the foreign key I could retrieve that. But it does not work.
My migration table
public function up()
{
Schema::create('bookings', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->integer('doctor_id');
$table->unsignedBigInteger('campagne_id');
$table->string('time');
$table->integer('status')->default(0);
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('campagne_id')->references('id')->on('campagne')->onDelete('cascade');
});
}
My booking Model
public function utilisateur()
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function Campagne()
{
return $this->belongsTo(Campagne::class, 'campagne_id', 'id');
}
}
my controller
public function liste()
{
$bookings = DB::table('bookings')->paginate(6);
return view('listeAppointement', compact('bookings', 'doctors'));
}
My erreur enter image description here
i dont know happen. Thanks for advance.
Your setup is good to go, Did you verified that all reference 'user_id' from table bookings exist on users table? It happens sometimes when relation not find required field with foreign key.

Can I create custom pivot table name using another M:M entity?

I'm still thinking is there a ways how can I create a custom pivot table name? Because I created a documents and users table has a many to many relationship with document_user which is my pivot table and this table was created for received document that user created. And I'm planning to create a another pivot table for document and user this table was for sent documents so I can have history. See my code below.
create_document_user_table
public function up()
{
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'));
$table->timestamp('dateModified')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
});
}
documents_table
public function up()
{
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();
});
}
users_table
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('first_name');
$table->string('last_name');
$table->string('middle_name');
$table->string('email');
$table->string('username');
$table->string('address');
$table->string('password');
$table->string('remember_token');
$table->integer('role_permission_id')->unsigned();
$table->foreign('role_permission_id')->references('id')->on('roles_permissions_dt')->onDelete('cascade');
$table->timestamps();
});
}
This works well inserting records to my pivot table. What I'm planning to achieve is every-time I inserted a records for documents this will inserted too in my custom pivot table not only in my document_user pivot table. Any help would appreciated! Thanks for your info or tips.
UPDATE
#Mina thanks for the tips that you given but actually this is my insert or save for my pivot table. How can I inserted this in my revisions table?
DocumentController
public function postDocuments(Request $request)
{
$this->validate($request,
[
'title' => 'required|regex:/(^[A-Za-z0-9 ]+$)+/|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();
$user = Auth::user();
foreach($request->recipient_id as $recipientId)
{
$document->recipients()->sync([ $recipientId => ['sender_id' => $user->id]],false );
}
return redirect()->back();
}
You can call your pivot tables as you like.
As mentioned previously, to determine the table name of the
relationship's joining table, Eloquent will join the two related model
names in alphabetical order. However, you are free to override this
convention. You may do so by passing a second argument to the
belongsToMany method:
return $this->belongsToMany('App\Role', 'user_roles');
(Eloquent: Relationships #Many To Many)
In your case you would need to define the relations like this:
class User extends Model
{
// other stuff
createdDocuments()
{
return $this->belongsToMany('App\Document', 'document_user_created');
}
sentDocuments() // or receivedDocuments()
{
return $this->belongsToMany('App\Document', 'document_user_sent');
}
// other stuff
}
class Document extends Model
{
// other stuff
createdByUsers()
{
return $this->belongsToMany('App\User', 'document_user_created');
}
sentToUsers() // or sentFromUsers() or whatever it does mean
{
return $this->belongsToMany('App\User', 'document_user_sent');
}
// other stuff
}
You do not need another pivot table. You need a table like that:
public function up()
{
Schema::create('revisions', function (Blueprint $table) {
$table->increments('id');
$table->integer('document_id')->unsigned();
//Rest of table structure
$table->foreign('document_id')->references('id')->on('document_user')->onDelete('cascade');
$table->timestamps();
});
}
When you need to create a new Revision:
$document = new Document;
//add $document attributes
$user->documents()->save($document);
$document->recipients->each(function($recipient){
$id = $recipient->pivot->id;
Revision::create(['document_id'=>$id]);
})

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:
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';
}
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.
*/
}

Laravel. Update two tables at one POST method

I have this code right there, this code is working fine and data is successfully stored to table "reports". But I also want to update Users table and their field Credits also. How can I do this in this function ? I also have the relationship between these two tables "reports" and "users".
public function giveCredits($id)
{
$report = Report::where('id', $id)->first();
$report->credits += Input::get('credits');
$report->save();
return redirect()->back();
}
Users Table
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('email')->unique();
$table->string('password');
$table->integer('credits');
$table->enum('role', ['user', 'admin'])->default('user');
$table->rememberToken();
$table->timestamps();
});
Reports table
Schema::create('reports', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('credits');
You just need to add the logic to update the user (assuming you have a relationship method called user):
public function giveCredits($id)
{
$report = Report::where('id', $id)->first();
$report->credits += Input::get('credits');
// if the report has a user, update it
if ($report->user) {
$report->user->credits += Input::get('credits');
$report->user->save();
}
$report->save();
return redirect()->back();
}

Automaticlly attach to pivot table in Laravel 5

I currently have a Users to Groups Relationship (ManyToMany) with a pivot table group_user. I want the user to be able to create a group but once creating the group, how do I make it, that the creator becomes member of this group?
Currently I have
My Pivot Table (group_user):
Schema::create('group_user', function(Blueprint $table)
{
$table->integer('group_id')->unsigned()->index();
$table->foreign('group_id')->references('id')->on('groups')->onDelete('cascade');
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
My Groups table (groups):
Schema::create('groups', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->timestamps();
});
My Users table (users):
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('name');
$table->string('lastname');
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
My models ofcourse have the following: User.php
public function groups()
{
return $this->belongsToMany('App\Group');
}
Group.php
public function users()
{
return $this->belongsToMany('App\User');
}
What create function should I write in my controller so that when a User creates a Group, that he automaticly becomes member of this group (automaticlly make the pivot relationship)?
This should work, make sure you implement validation, ect.
public function store(Request $request)
{
$group = Group::create([ // <-- if names are unique. if not, then create is fine
'name' => $request->get('name')
]);
auth()->user()->groups()->attach([$group->id]);
return view('your.view');
}
Also make sure to add:
use App\Group;
See attach() and detach().
$user = User::find(1);
$user->groups()->attach(10); // pivot relationship of this user to group of id 1.
OR
$group = Group::find(10);
$user->groups()->save($group);
For many groups of this user:
$user->groups()->sync(array(1, 2, 3));

Categories