Delete all records from related tables using laravel eloquent - laravel-5

I have 3 tables.
Posts
Likes
Post_images.
// Model Relations.
Posts hasMany likes.
Likes belongs to Posts.
post hasMany PostImages
post_imags belongs to Posts.
Now when i delete a post record i want to delete its related records from likes table as well as from post_images table,Besides this images should also be removed from storage.
How can i accomplish this ? any guidance would be highly appreciated.

If I understand correctly your query should be like this. But you cannot remove images with eloquent relations. So you need to do something like
$courses = \App\Course::all();
foreach($courses $ $course){
Storage::delete($course->image_column_name);
}
\App\Courses::with('sessions')->with('lessons')->delete();
I can give you better answer if you can share your models function, database schema and Storage information like where you store course images...

DB::table('users')->delete();
All users are deleted from 'user' Table

if you set table names with Models::table('abilities') in
Schema::create(Models::table('abilities'), function (Blueprint $table) {
$table->bigIncrements('id');
// other fields
}
you can use
DB::table(Models::table('abilities'))->delete();
as documented here you can
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
Models::table('abilities');
}

Related

Laravel Eloquent Many to Many Relationship pivot table

I have three tables categories, film_categories and films and three models respectively Category, FilmCategory and Film.
I have seen many tutorials where they don't create a pivot table model like i have created FilmCategory Model . They just create a pivot table film_categories without a model.
My question is what is the best practise - ?
Should i create a FilmCategory model and set a hasMany relationship
class Film extends Model
{
use HasFactory;
protected $primaryKey = 'film_id';
/**
* Film film Relationship
*
* #return Illuminate\Database\Eloquent\Relations\HasMany
*/
public function categories()
{
return $this->hasMany(FilmCategory::class, 'film_id', 'film_id');
}
}
OR
Should i just create a pivot table film_categories without a model FilmCategory and set belongsToMany relationship
class Film extends Model
{
use HasFactory;
protected $primaryKey = 'film_id';
/**
* Film film Relationship
*
* #return Illuminate\Database\Eloquent\Relations\HasMany
*/
public function categoriesWithPivot()
{
return $this->belongsToMany(Category::class, 'film_categories', 'film_id', 'category_id');
}
}
Technically speaking, both option are fine. You can implement the two of them, and depends on what you want to implement/achieve in the logic part of the code, use one between the two that suits best. Here are things to consider:
First, depends on what is film_categories table used for. If the table is simply exists to relate films and categories tables using many-to-many relationship, then there's no need to create the FilmCategory model, and you can just use belongsToMany(). Otherwise, if the film_categories will relates to another table, then you should create FilmCategory model and define the relation using hasMany(). You're also likely need to add a primary-key field to film_categories if this is the case.
The second consideration to take is what kind of data structure you want to have. Using the codes that you provide, you can get Films using these 2 queries and it'll gives you the correct values but with different structures:
Film::with('categoriesWithPivot')->get();
// Each record will have `Film`, `Category`, and its pivot of `film_categories` table
// OR
// Assuming that `FilmCategory` model has `belongsTo` relation to `Category` ...
Film::with('categories', 'categories.category')->get();
// Will gives you the same content-values as the above, but with in a different structure
And that's it. The first point is mostly more important to consider than the second. But the choice is completely yours. I hope this helps.
Since the film_categories table does not represent an entity in your system, I think you should define a belongsToMany relationship and should not create a separate model for the pivot table. If You still wanna have a model for your pivot table so create a model that extends Illuminate\Database\Eloquent\Relations\Pivot class. Check documentation here: model for pivot table

Laravel Many To Many (Polymorphic) issue

I've been trying to create a Many To Many (Polymorphic) system that saves the state of every update done by a specific user on specific Models (for instance: Company, Address, Language models) with a note field and the updated_by. The goal is to keep track of who updated the model and when, and the note field is a text field that states where in the system the model was updated.
Below is what I created, but I'm open to getting a different solution that, in the end, allows me to accomplish the goal described above.
I've created the model Update (php artisan make:model Update -m) with the migration:
/**
* Run the migrations.
*
* #access public
* #return void
* #since
*/
public function up()
{
Schema::create('updates', function (Blueprint $table) {
$table->id()->comment('The record ID');
$table->bigInteger('updatable_id')->unsigned()->comment('THe model record id');
$table->string('updatable_type')->comment('THe model name');
$table->string('note')->nullable()->comment('The record note');
$table->integer('updated_by')->unsigned()->nullable()->comment('The user ID which updated the record');
$table->timestamps();
$table->softDeletes();
});
}
On the model Update all the $fillable, $dates properties are standard, and the method of the Update model:
class Update extends Model
{
/**
* Method to morph the records
*
* #access public
*/
public function updatable()
{
return $this->morphTo();
}
}
After trying several ways on the different models, my difficulty is getting the relation because when I save to the updates table, it saves correctly. For instance, in the Company model: Company::where('id', 1)->with('updates')->get(); as in the model Company I have the method:
public function updates()
{
return $this->morphToMany(Update::class, 'updatable', 'updates')->withPivot(['note', 'updated_by'])->withTimestamps();
}
Most certainly, I'm doing something wrong because when I call Company::where('id', 1)->with('updates')->get(); it throws an SQL error "Not unique table/alias".
Thanks in advance for any help.
The problem I see here is using morphToMany instead of morphMany.
return $this->morphToMany(Update::class, 'updateable', 'updates'); will use the intermediate table (and alias) updates (3rd argument) instead of using the default table name updateables. Here it will clash with the table (model) updates, so it will produce the error you are receiving.
return $this->morphMany(Update::class, 'updateable'); will use the table updates and should work with your setup.
Do notice that morphMany does not work with collecting pivot fields (e.g. withPivot([..]), it's not an intermediate table. Only morphToMany does.

Custom hasMany relationship query with select()

Each company on my app can store its own events.
A company and its events are related though the following hasMany relationship:
/**
* The events that belong to the company.
*/
public function events()
{
return $this->hasMany('App\Event');
}
To list a company's events, I use:
Auth::user()->company->events
Since each event stores, a lot of data that I don't need when I query the hasMany, I would like to customize the relationship to only select the id and name columns instead of the whole row.
My hasMany relationship query would be something like
DB::table('events')->where('company_id', Auth::id())->select('id', 'name')->get();
How do I take the collection returned from this result and use it as the query for my hasMany relationship, which will then correctly return a collection of event instances?
Add the filter inside your events method like :
public function events()
{
return $this->hasMany('App\Event')->select('id', 'company_id', 'name');
}
Then call it like:
Auth::user()->company->events
Important update: 'company_id' is necessary for company->events link, otherwise 'events' relationship always returns empty array
How about
Auth::user()->company()->with('events:id,name')->get();
https://laravel.com/docs/5.8/eloquent-relationships#eager-loading
Go to Eager Loading Specific Columns

Laravel find record in another table associated with $data

I am looking over some laravel code and I have a few questions regarding the code. In the view, I see a piece of code "$data->profile->age". Does this code automatically find the profile record in the profile table associated with the $data? How does it find the associated profile?
Controller:
return view('new-design.pages.influencer.info')
->withData($data)
View:
$data->profile->age
Yes. It finds the associated profile using the relations you definied in your Profile model
Once the relationship is defined, we may retrieve the related record using Eloquent's dynamic properties. Dynamic properties allow you to access relationship methods as if they were properties defined on the model:
Here's a simple example from the documentation to help you understand:
Let's say you have a posts table and a comments table:
We need to define a relationship between this two tables.
A one-to-many relationship is used to define relationships where a single model owns any amount of other models. For example, a blog post may have an infinite number of comments.
Note: you must have a foreign key in your comments table referencing the posts table, like post_id, in this case, if you use a different name you should inform that in your relation:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
In your Post model you could do:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('App\Comment');
}
}
And in your Comment model you should define the inverse relationship
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo('App\Post');
}
}
Now, if you want to access all comments from a post you just need to get the relation:
$post = Post::find($id); // find a post
$post->comments; // This will return all comments that belong to the given post
So, you basically access them as if they were a property from the model, as said in the documentation
In your view you could do something like this:
#foreach($post->comments as $comment)
{
{{$comment->text}}
}
#endforeach
This example will print every comment text from the Post we get in the controller.
I reckon in your model for $data there is a function called profile. From that it is getting the equivalent profile.
Example: Imagine you have a model called phone and you want to find the user who owns it. You can write the following function in your model.
public function user()
{
return $this->belongsTo('App\User');
}
And in the view you may write something like
$phone->user->name
Now, behind the scene laravel will go to the phone and get the value from user_id for that phone. (If the foreign key is located in different column you can specify that too). Then laravel will find the users table with that user_id and retrieve the row. Then show the name on view.
Now if there is a complex query you can also write a function for that in the model.

Laravel defining a many-to-many relationship with the same table

So I have a posts table with a corresponding Post model. I want to have related posts for every post. Since a post can have many other related posts, it is a many-to-many relationship between the posts table and the posts table (same table).
So I created a related_posts pivot table with its corresponding model RelatedPost. I want to define this relationship in the two models. Like so:
Post model:
public function related()
{
return $this->belongsToMany(RelatedPost::class, 'related_posts', 'related_id', 'post_id');
}
RelatedPost model:
public function posts()
{
return $this->belongsToMany(Post::class, 'related_posts', 'post_id', 'related_id');
}
Now in my post controller after selecting a particular post, I want to get all its related posts. So I do this:
$post->related()->get();
But when I do this I get the following error message:
"SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'related_posts' (SQL: select related_posts.*, related_posts.related_id as pivot_related_id, related_posts.post_id as pivot_post_id from related_posts inner join related_posts on related_posts.id = related_posts.post_id where related_posts.related_id = 1) "
This is my migration for the pivot table:
Schema::create('related_posts', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('post_id');
$table->unsignedInteger('related_id');
$table->timestamps();
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
$table->foreign('related_id')->references('id')->('posts')->onDelete('cascade');
});
I have searched all over everywhere and though the solutions I've found really make sense I haven't been able to get any of them to work.
Any help will be very much appreciated!
Thanks to #d3jn's comment on my question I was able to solve my problem. So I am posting the solution here just in case someone else might need it.
I am relating the Post model to itself not to the pivot model RelatedPost. So I don't need a RelatedPost model. I only need a pivot table (related_post), and the relation's ids namely related_id and post_id.
So with my migration unchanged, I only need to do away with the RelatedPost model and change my related() method in the Post model to look like this:
public function related()
{
return $this->belongsToMany(Post::class, 'related_posts', 'post_id', 'related_id');
}
And now everything works.

Resources