I am looking for a solution for storing comments in the database, but it is not difficult at all:
In one table wants to write comments from several modules on the website.
I am currently creating a table using code 'comments table':
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('module_id')->unsigned();
$table->integer('parent_id')->unsigned();
$table->text('body');
$table->timestamps();
});
}
Comments modules table:
public function up()
{
//
Schema::create('comment_module',function (Blueprint $table){
$table->increments('id');
$table->string('title',190);
$table->string('name',190)->unique();
$table->text('body');
$table->timestamps();
});
}
for now everything is okay, but i have problem with select all comments for each blog post,gallery, etc..
blog, gallery - name of modules.
code for Map.php model
public function comments(){
return $this->hasMany(Comment::class,'module_id');
}
CommentModule.php model
public function comments(){
return $this->hasMany(Comment::class,'module_id');
}
Comment.php
public function module(){
return $this->belongsTo(CommentModule::class);
}
and now how to pass a 'mmodule_id' ?
normal use with any relationships for one table will be like that:
$map->comments->body . . etc.
but for that construction don`t work, yes of course i can use raw query and use join, right ?
Is any option to use a Eloquent?
IMHO for what I understood you want to attach comments to more than one Eloquent Model. There is a clean example in the laravel docs with Polymorphic Relations
As summary you have to add two fields on the comments table: commentable_id(integer) and commentable_type (string).
After that you declare the relation on the Comment model:
public function commentable()
{
return $this->morphTo();
}
And you can use the comments() relation in each model you want to attach comments, i.e.:
class Post extends Model
{
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
class Map extends Model
{
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
Now you can retrieve comments as usual:
$post->comments;
To attach a new comment to a parent:
$post->comments()->create([array of comment attributes]);
Related
I have a model named Point having the following fields:
name
description
lat
lng
The fields "name" and "description" can be in several languages, so I created two tables for points and their details.
Schema::create('points', function (Blueprint $table) {
$table->id();
$table->float('lat');
$table->float('lng');
$table->timestamps();
Schema::create('point_details', function (Blueprint $table) {
$table->id();
$table->integer('point_id');
$table->string('name');
$table->string('description');
$table->string('lang');
There is an index unique on point_id/language.
In the model files I have One To Many relationships
class Point extends Model
{
public function details()
{
return $this->hasMany(PointDetail::class);
}
}
class PointDetail extends Model
{
public function point()
{
return $this->belongsTo(Point::class);
}
}
Now I want to get the Point with details based on User language. I do so in the PointController:
class PointController extends Controller
{
public function show($id)
{
$point = Point::with(['details' => function($query) {
$query->where(
'lang', Auth::user()->lang ?
Auth::user()->lang :
'it');
}])->find($id);
return view('points.show',compact(['point']));
}
}
Can I avoid the "with" clause in the Controller? Maybe making the right query in the Point model file. I'm looking for a way to return the point with one detail associated with it, based on language of the Auth::user().
Thanks for any suggestion.
you can add query to relationship method in point class to details method
like that :
class Point extends Model
{
public function details()
{
return $this->hasMany(PointDetail::class)->where('lang', Auth::user()->lang);
}
}
I want to return the projects of the authenticated user, but am not getting any. I know the records exist in the database.
This is my model Project:
public function users(){
return $this->hasMany(User::class);
}
this is my model User:
public function projects(){
return $this->hasMany(Projet::class,'user_id');
}
and this is the controller function :
public function projetuser(){
$user = User::find(auth()->user()->id);
return $user->projects;
}
and this my user_projet migration:
public function up()
{
Schema::create('user_projet', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('projet_id');
$table->foreign('projet_id')->references('id')->on('projets')->onDelete('cascade');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('membre')->nullbale();
$table->timestamps();
});
}
You are defining a many-to-many relationship incorrectly. Use belongsToMany() instead of hasMany(). Because your pivot table name is not standard (it should be alphabetic order projet_user) you need to include it in the relationship definition as well.
<?php
use Illuminate\Database\Eloquent\Model;
class Projet extends Model
{
public function users()
{
return $this->belongsToMany(User::class, 'user_projet');
}
}
class User extends Model
{
public function projets(){
return $this->belongsToMany(Projet::class, 'user_projet');
}
}
Now in your controller you can do this:
public function projetuser(){
return auth()->user->projets;
}
Your question seems to vary between "projet" and "project." I assumed "projet" was the correct spelling, but try to keep this consistent.
Please note also the typo in your migration: nullbale.
I am building a blog with laravel where a post has many tags. I want to filter all post by a tag. means if I click on "PHP" tag I want to get all associated post.
Here is my code
I have two table first for tags and a second table for the link with posts
tag_table
public function up()
{
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string('tags');
$table->timestamps();
});
}
relation tag table
public function up()
{
Schema::create('article_tag', function (Blueprint $table) {
$table->increments('id');
$table->integer('article_id')->unsigned();
$table->foreign('article_id')->references('id')->on('articles');
$table->integer('tag_id')->unsigned();
$table->foreign('tag_id')->references('id')->on('tags');
});
}
Article Model
class Article extends Model
{
public function tags()
{
return $this->belongsToMany('App\Tag');
}
}
tag model
class Tag extends Model
{
public function articles()
{
return $this->belongsToMany('App\Article');
}
}
Tag Controller
public function show($id,$name)
{
//here I received tag id and name.
$list->with('articles')->get();
return view('articles.tagshow')->withList($list);
}
Eloquent offers the whereHas method that lets you filter on attributes of related models. In order to filter articles by the name of their associated tags, you should do the following:
$articles = Article::whereHas('tags', function($query) use ($tagName) {
$query->whereName($tagName);
})->get();
However, in your case it should be even simpler, because you already have the tag ID in your controller, so you can simply get a tag model by ID and then return related articles:
public function show($id,$name) {
return Tag::findOrFail($id)->articles;
}
Check the docs on querying relations for more details: https://laravel.com/docs/5.6/eloquent-relationships#querying-relations
Let's assume I have a Book. This Book has Chapters and those Chapters in this Book have Subchapters.
So I have three models:
Book > Chapter > Subchapter
When I delete the Book ($book->delete();), I also want to delete the related Chapters of this Book and also the related Subchapters of all the Chapters from the Book.
Here (Automatically deleting related rows in Laravel (Eloquent ORM)) I found out about Eloquent Events. Whenever a Book is deleted, before that, the Chapter gets deleted because we hook in:
class Book extends Eloquent
{
public function chapters()
{
return $this->has_many('Chapter');
}
protected static function boot() {
parent::boot();
static::deleting(function($book) {
$book->chapters()->delete();
});
}
}
So I thought, I only have to implement the same code in my Chapter-Model, only exchanging "Book" with "Chapter" and "Chapter" with "Subchapter":
class Chapter extends Eloquent
{
public function subChapters()
{
return $this->has_many('SubChapter');
}
protected static function boot() {
parent::boot();
static::deleting(function($chapter) {
$chapter->subChapters()->delete();
});
}
}
This works fine when I delete a Chapter. All the Subchapters will also be deleted.
When I delete the Book it works fine with the Chapters. All the Chapters will also be deleted.
However it only deletes Chapters when I delete the Book. It does not delete the related Subchapters of the deleted Chapters.
Can anybody help me?
That's because when you delete multiple objects at the same time it doesn't trigger the boot deleting function for each model so you should loop through the objects and delete them one by one:
class Book extends Eloquent
{
public function chapters()
{
return $this->has_many(Chapter::class);
}
protected static function boot() {
parent::boot();
static::deleting(function($book) {
foreach($book->chapters as $chapter){
$chapter->delete();
}
});
}
}
/********************************/
class Chapter extends Eloquent
{
public function subChapters()
{
return $this->has_many(SubChapter::class);
}
protected static function boot() {
parent::boot();
static::deleting(function($chapter) {
foreach($chapter->subChapters as $subChapter){
$subChapter->delete();
}
});
}
}
However my recommendation is to set cascading foreign key relation between the tables so the DBMS is going to delete the related rows automatically, the sample code below shows you how to do it in migration files:
Schema::create('chapters', function (Blueprint $table) {
$table->increments('id');
$table->integer('book_id')->unsigned();
$table->string('title');
$table->timestamps();
$table->foreign('book_id')
->references('id')
->on('books')
->onDelete('cascade')
->onUpdate('cascade');
});
Do the same for subChapters.
Hope It helps...
This is because $book->chapters() will just return an instance of Builder. When you call delete() on the builder it will simply just run the query needed to delete those models and not new them up and then delete them which will mean that the deleting event on the Chapter will never be fired.
To get around this you can do something like:
protected static function boot() {
parent::boot();
static::deleting(function($book) {
$book->chapters->each(function ($chapter) {
$chapter->delete();
});
});
}
Hope this helps!
The correct way to do that is to use onDelete('cascade'). In the chapters table migration:
$table->foreign('book_id')
->references('id')
->on('books')
->onDelete('cascade');
In the subchapters migration:
$table->foreign('chapter_id')
->references('id')
->on('chapters')
->onDelete('cascade');
In this case, you don't need to write any code and all chapters and subchapters will be deleted automatically.
I seen to of got tangled in Laravel's ORM with the following:
Scenerio: All Users have a Watchlist, the Watchlist contains other Users.
I can't seem the get the relationships to work correctly as they are cyclical, so far I have the following:
class UserWatchlist extends Model
{
protected $table = 'UserWatchlist';
public function Owner() {
return $this->belongsTo('App\User');
}
public function WatchedUsers() {
return $this->hasMany('App\User');
}
}
Schema::create('UserWatchlist', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('Users')->onDelete('cascade');
$table->integer('watched_id')->unsigned();
$table->foreign('watched_id')->references('id')->on('Users')->onDelete('cascade');
$table->timestamps();
});
class User extends Model
{
public function Watchlist() {
return $this->hasOne('App\UserWatchlist');
}
public function WatchedBy() {
return $this->belongsToMany('App\UserWatchlist');
}
}
It is not pulling through the correct in formation i'm expecting. Am I missing something fundamental?
Since UserWatchlist is a pivot table, i suppose you are facing a many to many relationship with both the elements of the relation being the same model (User)
If that is the case, you should not build a model for the pivot table UserWatchlist but all you have to do is to set the relation between the users through the pivot table:
class User extends Model
{
//get all the Users this user is watching
public function Watchlist()
{
return $this->belongsToMany('User', 'UserWatchlist', 'user_id', 'watched_id' );
}
//get all the Users this user is watched by
public function WatchedBy()
{
return $this->belongsToMany('User', 'UserWatchlist', 'watched_id', 'user_id' );
}
}
Check here for more info on many-to-many relationship