can't find questions by category name in Laravel - php

i am trying to retrieve questions based on the category witch they belong with this function inside my questions controller:
public function getByCategoryName($categoryName) {
$category = Category::where('name', $categoryName)->first();
return response($category->questions);
}
the problem is that, even if $category its being correctly set, $questions is null and the browsers returns an empty response to my request
the tables are created like this:
Questions table:
Schema::create('questions', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('title')->nullable(false);
$table->string('content')->nullable(false);
$table->integer('points')->default(0);
$table->foreignId('user_id')
->constrained('users')
->onDelete('cascade');
$table->string('category_name');
$table->foreign('category_name')
->references('name')->on('categories')
->onDelete('cascade')
->onUpdate(null);
});
categorie table:
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('name')->nullable(false);
$table->unique('name');
});
I have the relatives relationship functions HasMany and BelongsTo seated inside the the models.
Question model:
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
Category model:
public function question() : HasMany {
return $this->hasMany(Question::class);
}
What am I doing wrong?

As others have pointed out. It's better to use the primary ID key for efficient mapping. However, for education purposes it is possible and I will explain. Eloquent determines the foreign key name by examining the name of the relationship method and suffixing the method name with _id.
So, in this case, Eloquent assumes that the Question model has a category_id column.
However, since the foreign key on the Question model is not category_id, we must pass a custom key name as the second argument to the belongsTo method:
public function category()
{
return $this->belongsTo(Category::class, 'foreign_key'); // If we do not pass this eloquent thinks the foreign key is 'category_id'
}
// We need to pass our custom foreign key
public function category()
{
return $this->belongsTo(Category::class, 'category_name');
}
Eloquent assumes the parent model Category will be associated using its primary id. Since this is not our case we need to associate the parent model key to the 'name' column.
So we need to pass a third argument to the belongsTo method specifying the parent tables custom key:
public function category()
{
return $this->belongsTo(Category::class, 'category_name', 'name');
}
Your complete solution should look something like this.
// Question model
public function category()
{
return $this->belongsTo(Category::class, 'category_name', 'name');
}
// Category model
public function questions()
{
return $this->hasMany(Question::class, 'category_name', 'name');
}

Change this :
public function question() : HasMany {
return $this->hasMany(Question::class);
}
To this :
public function questions() : HasMany {
return $this->hasMany(Question::class, 'category_name');
}

Related

eloquent only get first Active query

hey guys i have a confusing question
I have 3 tables
basket_lists (carts)
basket_items (carts_item)
products
with this migrate
'basket_lists':
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->boolean('active');
$table->timestamps();
basket_items:
$table->bigIncrements('id');
$table->unsignedBigInteger('product_Id');
$table->unsignedBigInteger('basket_list_id');
$table->timestamps();
products:
$table->bigIncrements('id');
$table->string('title');
$table->text('description');
$table->bigInteger('amount');
$table->timestamps();
I have some products in my table , when i search (query) {
BasketList::where('active', '=', 1)->with('basketItems.products')->get();
it only gives me the first basketlist products (where id = 1)
if i insert new basketlist and set the first basketlist to (active = 0) and second one to (active = 1) it will not show any products.
Here is my model classes :
class BasketList extends Model
{
public function basketItems()
{
return $this->hasMany(BasketItem::class ,'basket_list_id' );
}
}
class BasketItem extends Model
{
public function products()
{
return $this->hasMany(Product::class,'id' );
}
public function basketList()
{
return $this->belongsTo(BasketList::class);
}
}
public function basketItem()
{
return $this->belongsTo(BasketItem::class ,'product_id');
}
You must change your relationship to belongsTo()
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class BasketItem extends Model
{
//
protected $table = 'basket_items';
public function product()
{
return $this->belongsTo(Product::class, 'product_id','id' ); // Watch out for the case sensitive. how did you wright product_id in your migration. (product_id or product_Id)
}
You break Laravel default naming conventions for foreign keys 'product_Id'
It must be 'product_id'
Eloquent determines the foreign key of the relationship based on the
model name. In this case, the BasketItem model is automatically
assumed to have a 'product_id' foreign key. If you wish to override this
convention, you may pass a second argument to the hasMany method:
Fix
App\BasketItem.php
public function product()
{
return $this->belongsTo(Product::class, 'product_Id','id' );
}
Check Documentation
Usage
BasketList::where('active', '=', 1)->with('basketItems', 'basketItems.product')->get();

Add friend model to belongs to many relationship

Table friend:
$table->integer('user_id');
Table friend_user:
$table->integer('user_id');
$table->integer('friend_id');
$table->primary(['user_id', 'friend_id']);
User model:
public function friends()
{
return $this->belongsToMany(User::class, 'friend_user', 'user_id', 'friend_id');
}
UserController:
public function getAddFriend(User $user)
{
Auth::user()->friends()->attach($user->id);
return redirect()->back();
}
Why is it that if I write $user->id in attach(), the data is not inserted into table friend_user, but if I write the id(1, 2 or something else) in attach(), the data is inserted into the table friend_user?
How to add the data in the table friend_user after clicking?
I believe the underlying problem is model binding, i presume your route has a parameter called user. Then i would explicit define your model binding in AppServiceProvider.php or RouteServiceProvider.php boot() method.
use Illuminate\Support\Facades\Route;
Route::model('user', User::class);

How to know when my relation returns an object and when an array?

I got few relations in my model Reply:
/** Reply.php */
public function thread()
{
return $this->belongsTo(Thread::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
My reply table got user_id and thread_id
And then I try to get user name I do it like this:
$reply->user->name
And it works.
But when I try to get thread title:
$reply->thread->title
I got error:
Trying to get property title of non-object
And if need to get title only method I know is:
$reply->thread['title']
What is the difference between methods I use? Why in one case I get user as an object but in another I get thread as an array?
Update:
My Reply model relations:
public function user()
{
return $this->belongsTo(User::class);
}
public function favorites()
{
return $this->morphMany(Favorite::class, 'favorited');
}
public function thread()
{
return $this->belongsTo(Thread::class);
}
My Thread model relations:
public function replies()
{
return $this->hasMany(Reply::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function category()
{
return $this->belongsTo(Category::class);
}
And my User model relations:
public function threads()
{
return $this->hasMany(Thread::class)->latest();
}
public function replies()
{
return $this->hasMany(Reply::class)->latest();
}
When you make
one to one
relation then relation will return object
When you make
one to many
relation will return array of objects
The Model class implements the Arrayable interface, this means that you can access the attributes also as if it were an array, this is why this work:
$reply->thread['title'];
When you use a BelongsTo relationship, this expect to return an object (an instance of your model) or null in case this relation isn't set, this is why you can use "magic methods" to access attributes like this:
$reply->thread // an object
$reply->thread->title // getting attributes using magic methods
But, what happen when the relationship isn't set? well, the relationship will return null so when you do this:
$reply->thread->title
It will throw an arror:
Trying to get property title of non-object
Because you are trying to access the title attribute of null.
Update:
This is where -I think- the error is. With the newest version of Laravel (as of today: Laravel 5.8), the primmary keys types has changed from integers to bigIntegers(), and this is for all the tables:
Schema::create('replies', function (Blueprint $table)
{
$table->bigIncrements('id'); // <---- equivalent to bigInteger
$table->integer('user_id')->unsigned;
$table->integer('thread_id')->unsigned;
$table->text('body');
$table->timestamps();
});
So, your foreign keys should be also big integers, try this:
Schema::create('replies', function (Blueprint $table)
{
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id'); // <-----------
$table->unsignedBigInteger('thread_id'); // <-----------
$table->text('body');
$table->timestamps();
});
Check this article related this issue.
I think that the only reason for this error would be a null return from the relation. In that case
$reply->thread['title']
won't work, can you check it please ?
If the $reply->thread['title'] works, I would like to see the output of dd($reply->thread); please.
If it does not work and the cause of the error is indeed a null return, you just have to check that
$reply->thread is not null before using it.
Let me know if it helped you :)

Store Comments in DB

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]);

Laravel 5.1 Multiple Many to Many Relationship on the Same Model

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

Categories