I'm building a basic forum, there are many topics and each topic has comments, a comment or "commentable" can be a a comment or a reply (commented a comment), this is because I want to have nested comments, that's where parent_id is useful. I'm wondering if my polymorphic relationship is the best way to achieve this so I'm open to any suggestions. The first issue I came up with is I don't know hw to do ajax pagination of topic->comments ..., I thought with something like Comment::whereHas('topic') ... but my comments dont' have a topic relationship defined in the model.
I'm using laravel advanced ajax pagination, how can I paginate comments?
Topic model:
class Topic extends Model
{
protected $table = 'topics';
public function author()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
public function comments()
{
return $this->morphMany('App\Models\Comment', 'commentable')->whereNull('parent_id');
}
public function up()
{
Schema::create('topics', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id')->index();
$table->foreign('user_id')->references('id')->on('users');
$table->string('title');
$table->text('body');
$table->string('url')->unique();
$table->string('slug')->unique();
$table->boolean('isVisible')->default(false);
$table->timestamps();
});
}
}
Comment model:
class Comment extends Model
{
protected $table = 'comments';
public function author()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
public function replies()
{
return $this->hasMany('App\Models\Comment', 'parent_id');
}
}
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id')->unsigned();
$table->integer('parent_id')->unsigned();
$table->integer('commentable_id')->unsigned();
$table->string('commentable_type');
$table->text('body');
$table->timestamps();
});
}
This is where I took inspiration:
Related
I have a customer model that has many contacts. I defined a relationship to get the most recent contact of the customer using the "Has One Of Many" relationship in Laravel 8:
Models
class Customer extends Model
{
use HasFactory;
public function contacts()
{
return $this->hasMany(Contact::class);
}
public function latestContact()
{
return $this->hasOne(Contact::class)->ofMany('contacted_at', 'max')->withDefault();
}
}
class Contact extends Model
{
use HasFactory;
protected $casts = [
'contacted_at' => 'datetime',
];
public function customer()
{
return $this->belongsTo(Customer::class);
}
}
Migration (contact model)
class CreateContactsTable extends Migration
{
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->softDeletes();
$table->foreignID('customer_id');
$table->string('type');
$table->dateTime('contacted_at');
});
}
}
In my view, I want to show all customers and order them by their latest contact. However, I can't figure out how to do that.
I tried to achieve it via the join method but then I obviously get various entries per customer.
$query = Customer::select('customers.*', 'contacts.contacted_at as contacted_at')
->join('contacts', 'customers.id', '=', 'contacts.customer_id')
->orderby('contacts.contacted_at')
->with('latestContact')
Knowing Laravel there must be a nice way or helper to achieve this. Any ideas?
I think the cleanest way to do this is by using a subquery join:
$latestContacts = Contact::select('customer_id',DB::raw('max(contacted_at) as latest_contact'))->groupBy('customer_id');
$query = Customer::select('customers.*', 'latest_contacts.latest_contact')
->joinSub($latestContacts, 'latest_contacts', function ($join){
$join->on([['customer.id', 'latest_contacts.customer_id']]);
})
->orderBy('latest_contacts.latest_contact')
->get();
More info: https://laravel.com/docs/8.x/queries#subquery-joins
I suspect there is an issue with your migration, the foreign key constraint is defined like this:
Check the documentation:
https://laravel.com/docs/8.x/migrations#foreign-key-constraints
Method 1: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->foreignId('consumer_id')->constrained();
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}
Method 2: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('customer_id');
$table->foreign('customer_id')->references('id')->on('customers');
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}
Hello everyone I'm currently working on a laravel project where I have a parent table that has the id's of three tables referenced to it. These table migrations also have their models respectively. Here are the table migrations files respectively:
create_products_table.php
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('product_id', 10);
$table->string('product_name');
$table->string('image');
$table->string('images');
$table->string('product_description');
$table->bigInteger('size_id')->unsigned();
$table->string('color');
$table->string('product_quantity');
$table->string('old_price');
$table->string('discount');
$table->string('product_price');
$table->bigInteger('user_id')->unsigned()->nullable();
$table->bigInteger('category_id')->unsigned();
$table->bigInteger('gender_id')->unsigned();
$table->timestamps();
$table->foreign('size_id')->references('id')->on('sizes')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->foreign('gender_id')->references('id')->on('genders')->onDelete('cascade');
});
create_genders_table.php
Schema::create('genders', function (Blueprint $table) {
$table->id();
$table->string('gender_class');
$table->timestamps();
});
create_categories_table.php
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('cat_name');
$table->timestamps();
});
create_sizes_table.php
Schema::create('sizes', function (Blueprint $table) {
$table->id();
$table->string('sizes');
$table->timestamps();
});
Also this is how I defined the relationships on their models respectively
Product.php
public function category()
{
return $this->belongsTo(Category::class);
}
public function gender()
{
return $this->belongsTo(Gender::class);
}
public function size()
{
return $this->belongsTo(Size::class);
}
Category.php
public function products()
{
return $this->hasMany(Product::class);
}
Gender.php
public function products()
{
return $this->hasMany(Product::class);
}
Size.php
public function products()
{
return $this->hasMany(Product::class);
}
I'm actually a laravel beginner and I studied eloquent model relationships at laravel.com so what I did was just based on my understanding of one to many relationships. When I check all my request with dd($request), category_id, gender_id, size_id all show null and I believe it's because I didn't define the relationship properly. Now this is where I seriously need your assistance.
So please my experienced developers I seriously need your help I'll really be grateful if I get your replies today. Thanks in advance.
=>Everything is right, just make changes in the products migration add this code.
$table->foreign('size_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('gender_id')->references('id')->on('products')->onDelete('cascade');
=>and migrate table
I have 4 tables, 1->user, 2->category, 3->comment, 4->post
I want to get the category for the related post that user already commented
SELECT kategoris.* FROM kategoris
INNER JOIN yazis on yazis.kategori_id = kategoris.id
INNER JOIN yorums on yorums.yazi_id = yazis.id
INNER JOIN users on users.id = yorums.user_id
where users.id = 1
Relations
Depending on how your models are setup, this is how the query should be with Eloquent
$category = Post::whereHas('comments', function($query) {
$query->where('user_id', auth()->user()->id);
})->first()->category;
Update:
This is how your models and table migrations should look
User has many posts and comments
public function posts()
{
return $this->hasMany(Post::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
Category has many posts
public function posts()
{
return $this->hasMany(Post::class);
}
Post belongs to a category and a user, has many comments
public function category()
{
return $this->belongsTo(Category::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
Posts Table Migration
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
Comment belongs to a post and a user
public function post()
{
return $this->belongsTo(Post::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
Comments Table Migration
Schema::create('comments', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedBigInteger('post_id');
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
$table->timestamps();
});
Let's populate some data like this...
Database Seeder
$user = factory(User::class)->create([]);
$category = Category::create([]);
$post = $user->posts()->create(['category_id' => $category->id]);
$post->comments()->create(['user_id' => $user->id]);
And get the category of the post that the authenticated user commented on with the query above...
Hope this helps :)
So, I'm trying to create a relationship where users can follow other users or follow categories.
My intuition says that what I've done so far is not the right way of doing things. I'm especially confounded by how to create the follower - followee relationship.
TABLES:
Users
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('email');
$table->string('password');
$table->string('first_name');
});
}
Categories
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('category');
});
}
Follows
public function up()
{
Schema::create('follows', function (Blueprint $table) {
$table->increments('id');
$table->integer('follower_id');
$table->integer('followee_id')->nullable();
$table->integer('category_id')->nullable();
});
}
MODELS:
User
class User extends Model implements Authenticatable
{
public function follows()
{
return $this->hasMany('App\Follow');
}
}
Category
class Category extends Model
{
public function follows()
{
return $this->hasMany('App\Follow');
}
}
Follow
class Follow extends Model
{
public function post()
{
return $this->belongsTo('App\User');
}
public function source()
{
return $this->belongsTo('App\Category');
}
}
According to your scenario, it is recommended that you use Polymorphic Many To Many relationship.
Schema:
users
id - integer
...
categories
id - integer
...
followables
user_id - integer
followable_id - integer
followable_type - string
Models:
User:
public function followers()
{
return $this->morphToMany(User::class, 'followables');
}
public function following()
{
return $this->morphedByMany(User::class, 'followables');
}
Category:
public function followers()
{
return $this->morphToMany(User::class, 'followables');
}
Then you can create the relationship like:
When following an User:
$user->followers()->create(['user_id' => 12])
When following a Category:
$category->followers()->create(['user_id' => 25])
Hope it helps.
I find the pivot tables pretty complicated and I don't see what to do next or what I am doing wrong, I've found some tutorials but didn't help me in my needs.
I have a projects and users with a many-to-many relation.
One project hasMany users and One user hasMany projects.
What I have now leaves projects without a relationship to a user.
This is what I have so far:
Projects table
class CreateProjectsTable extends Migration {
public function up()
{
Schema::create('projects', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->date('completion_date');
$table->integer('completed')->default(0);
$table->integer('active')->default(0);
$table->timestamps();
});
}
Users table
class CreateUsersTable extends Migration {
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->integer('company_id');
$table->integer('project_id');
$table->integer('usertype_id')->default(0);
$table->string('username');
$table->string('password');
});
}
Project User table (pivot)
class CreateProjectUsersTable extends Migration {
public function up()
{
Schema::create('project_users', function(Blueprint $table)
{
$table->increments('id');
$table->integer('project_id')->references('id')->on('project');;
$table->integer('user_id')->references('id')->on('user');;
});
}
User model
public function projects() {
return $this->belongsToMany('App\Project', 'project_users', 'user_id', 'project_id');
}
Project model
public function users() {
return $this->belongsToMany('App\User', 'project_users', 'project_id', 'user_id');
}
Project controller
public function index(Project $project)
{
$projects = $project->with('users')->get();
dd($projects);
$currenttime = Carbon::now();
//return view('project.index', array('projects' => $projects, 'currenttime' => $currenttime));
return view('user.index', compact('projects'));
}
The relationship in your User model is not correct. You have to swap the keys.
public function projects() {
return $this->belongsToMany('App\Project', 'project_users', 'user_id', 'project_id');
}
Edit regarding latest comment:
Don't think about the pivot table, as long as you have your relations setup correctly, which I believe they are, Laravel handles all of that for you.
Now $projects->users does not make any sense because projects does not have users. projects is just a collection of Project. Each Project within that collection will have a users relation. You would have to iterate through the collection to view each Project's users.
foreach($projects as $project) {
foreach($project->users as $user) {
echo $user;
}
}