I am new to laravel. I am trying to build a relationship between two tables.
my database tables
comments table
$table->increments('id');
$table->text('comment');
$table->string('shop_name','80');
$table->bigInteger('product_id');
$table->timestamps();
comments_images table
$table->increments('id');
$table->bigInteger('comment_id');
$table->string('images','255');
$table->string('shop_name','80');
$table->timestamps();
=========================
Comment model
public function images()
{
return $this->hasMany(Comments_images::class,'comment_id');
}
Comments_images model
public function comments()
{
return $this->belongsTo(Comment::class);
}
I tried to return related data like this
return Comments_images::find(439)->comments()->get();
return Comment::find(880)->images()->get();
return (new Comment())->images()->get();
None of them work!
What should I do?
Are you utilizing the namespace correctly? For example, 'App\Comments_images'.. Also, models are best left singular- for example, 'Comment' or 'Comment_Image'. I bring that up because you aren't being consistent, which may be causing the error. The last thing is to use a string of the class, not returning an actual class. See the below examples, and notice capitalization and that I don't put an 's' on some things..
// in Comment model
public function images()
{
return $this->hasMany('App\Comments_Image','comment_id');
}
// in Comments_Image model
public function comment()
{
return $this->belongsTo('App\Comment', 'id', 'comment_id');
}
Edit: Feel free to use Comment::class instead of the string 'App\Comment' - It resolves to the same thing and works better with editor navigation, autocomplete, and other helpful things.
Related
I'm fairly now to using Pivot tables, and Many to Many relations overall, so hopefully I can learn what the issue.
I have a many to many relation between beers and beer lists, and I have a custom pivot table:
Schema::create('beer_list_pivot', function (Blueprint $table) {
$table->id();
$table->foreignId('beer_id')->constrained();
$table->foreignId('list_id')->constrained();
});
And the relations are looking like this:
BeerList Model:
public function beer()
{
return $this->belongsToMany(Beer::class, 'beer_list_pivot', 'beer_id', 'list_id');
}
Beer Model:
public function list()
{
return $this->belongsToMany(BeerList::class, 'beer_list_pivot', 'list_id', 'beer_id');
}
The attach method is used like this:
public function addItem(Request $request, $id)
{
$beerId = $request->beer;
$list = BeerList::findOrFail($id);
$list->beer()->attach($beerId);
return redirect("/list/" . $list->id);
}
This is returning the error:
SQLSTATE[HY000]: General error: 1 no such table: main.lists (SQL: insert into "beer_list_pivot" ("beer_id", "list_id") values (1, 1))
Any idea what is causing this?
it says lists table not found
try this
Schema::create('beer_list_pivot', function (Blueprint $table) {
$table->id();
$table->foreignId('beer_id')->constrained();
$table->foreignId('list_id')->constrained('beer_lists'); // <= here put your table name
});
and refresh migration
As you mentioned you are new to using pivot tables, so let me share some super small tips so you have less errors next time:
Try to stick to the Laravel standard table naming convention as much as possible, so you reduce code declaration and possible misses in declaring stuff.
You should be safe to remove all definitions for each relation (remove any parameter after table definition).
Try to add $table->timestamps(); to your tables as much as possible, because you will be able to debug anything if you have a created_at and updated_at column.
You can take advantage of implicit model binding in your controllers.
So, only for tip 1, your final code could be like this (if you follow standards):
Migration
Schema::create('beer_beer_list', function (Blueprint $table) {
$table->id();
$table->foreignId('beer_id')->constrained();
$table->foreignId('list_id')->constrained();
$table->timestamps();
});
BeerList Model
public function beer()
{
return $this->belongsToMany(Beer::class);
}
Beer Model
public function list()
{
return $this->belongsToMany(BeerList::class);
}
So, for tip 4:
public function addItem(Request $request, BeerList $list)
{
$beerId = $request->beer;
$list->beer()->attach($beerId);
return redirect("/list/" . $list->id);
}
And your route should be something like:
Route::post('/beer/{list}', [BeerListController::class, 'addItem']);
The most important thing for this to work is that {list} or whatever {slug} you write, must match BeerList $list or BeerList $slug (variable name) and also you have to type hint it. The documentation explains it very well.
i am still new to laravel and i want to implement visitors/view counter to my page, i looked everywhere and found a way but when i tried it it doesn't seem to work properly the views are always 0 .
this is the table where the views are stored :
Schema::create('views', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->morphs('viewable');
$table->timestamps();
});
and this is the views Model :
class views extends Model
{
protected $table = 'views';
protected $guarded = ['id'];
}
and these are the functions i added to the model i want to count its visitors :
public function views()
{
return $this->morphMany(
\App\Models\views::class,
'viewable'
);
}
public function getViewsCount()
{
return $this->views()->count();
}
public function getViewsCountSince($sinceDateTime)
{
return $this->views()->where('created_at', '>', $sinceDateTime)->count();
}
public function getViewsCountUpto($uptoDateTime)
{
return $this->views()->where('created_at', '<', $uptoDateTime)->count();
}
i called the function in my blade like this :
<i class="fa fa-eye"></i> {{$details->getViewsCount()}} Views
and i'm getting 0 views, i don't know if this is working or i am doing something wrong .. any ideas please !
The problem that I can see is the relationship.
The View model contains the viewable_id and viewable_type so the relationship should be a MorphTo.
And then for example if the Post model could have views then this would have the MorphMany relationship.
You are creating a one to many polymorphic relationship documented here https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-polymorphic-relations.
Additionally, look into the withCount method, https://laravel.com/docs/8.x/eloquent-relationships#counting-related-models might be a better fit for what you want. So you can do something as follows:
Post::withCount('views');
Or if you need to filter the count based on when the view was done.
Post::withCount([
'views' => function ($query) {
$query->where('created_at', >=, $someDate)
}
]);
And then you can access it like $posts[0]->views_count.
Edit:
I would also add to make sure that if you are adding data manually the viewable_type value would need to look like this App\Models\View or in laravel versions 7 or below the default location of the file would be App\View, but this depends on the location of your models.
There are two Models User and Submission and a User can have any number of submissions in which he is referenced as Author. I have set up the relationship according to the documentation and
the result of hasMany() is working fine. Only the belongsTo() method does not return the expected objects.
Here is the migration of my models:
Schema::create('users', function (Blueprint $table) {
$table->id();
});
Schema::create('submissions', function (Blueprint $table) {
$table->id();
$table->foreignId( 'author' );
$table->foreign( 'author' )->references('id')->on('users');
});
And these are the relationships within my models:
class User extends Authenticatable {
public function submissions() {
return $this->hasMany( 'App\Submission', 'author' );
}
}
class Submission extends Model {
public function author() {
return $this->belongsTo( 'App\User', 'author' );
}
}
Now, in my controller I want to execute this code:
$author = Submission::find(1)->author;
dd($author);
But, instead of the user object, the stored integer value of the author ID is printed. The relationship does not seem to be resolved via the author() method.
On the other hand, when I fetch a user and their submissions, everything works as expected, i.e. the submissions are printed as objects:
$u = User::find(1)->submissions;
dd($u);
But the relation from Submission to User does get resolved properly, when I do not define a custom foreign key with belongsTo and rename the colum to author_id.
The configuration that works is this one:
//migration for Submissions table
Schema::create('submissions', function (Blueprint $table) {
$table->id();
$table->foreignId( 'author_id' );
$table->foreign( 'author_id' )->references('id')->on('users');
});
//within Submission model
public function author() {
return $this->belongsTo( 'App\User' );
}
I have the feeling that I'm missing something. Is there any additional link I have to make? I browsed through the documentation and the web for solutions, but to no success. If there is no other solution, I'll follow with renaming the column. But I'd rather understand the cause of my problem and work with my original design.
you should not name relation functions and fields using the same string.
When you have a column author and a public function author() laravel goes for column content first.
Add '_id' to the column, so you do not need to define referenced field in $this->belongsTo( 'App\User', 'author' );.
My Laravel version is 5.5.13.
I created a many to many relationship between User model and Pet model. Pets can belong to multiple users.
I am trying to do in my update method in controller, get a list of all associated user ids. So I tried:
public function update(Request $request, Pet $pet)
{
dd($pet->users()->lists('id'));
$pet->update($request->all());
return response()->json($pet, 200);
}
However I get:
Call to undefined method Illuminate\Database\Query\Builder::lists()
It seems there is no lists().
If I do dd($pet->users()) it gives no error and shows a lot of information.
*May you please help to get this lists() to work.
My relationship in Pet model is:
public function users()
{
return $this->belongsToMany('App\User');
}
And my relatinship in User model is:
public function pets()
{
return $this->belongsToMany('App\Pet');
}
Here is my migration for the pivot:
Schema::create('pet_user', function (Blueprint $table) {
$table->integer('pet_id')->unsigned()->index();
$table->foreign('pet_id')->references('id')->on('pets')->onDelete('cascade');
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
list() is no more available in Laravel. Alternatively you can use pluck() and pluck all items like this pluck()->all();
pluck('key')->all();
pluck()->all();
Reference doc
laravel has deprecated the lists() method use pluck instead.
https://laracasts.com/discuss/channels/laravel/lists-deprecated-replacement
Okay I want to have custom field that does not exist as a column in my db table.
I followed, last part :
http://laravel.com/docs/4.2/eloquent#accessors-and-mutators
My model code:
class Car extends Eloquent{
protected $fillable = array('driverID', 'fuelRemaining');
protected $appends = array('is_driver');
public function user(){
return $this->belongsTo('user');
}
public function getIsDriverAttribute(){
return ($this->attributes['driverID'] == Auth::user()->id);
}
}
Car table:
Schema::create('cars', function(Blueprint $table)
{
$table->increments('id');
$table->integer('driverID');
$table->integer('fuelRemaining');
$table->mediumtext('desc');
$table->timestamps();
});
As you can see i want an extra field which is "is_driver" to be returned, but when I run this, this field is used to determine whether current signed in user is the driver himself by comparing the IDs.
it will output this error:
Undefined index: driverID
Not sure what am I doing wrong here, please advice.
Ah I have found why. This is a reference for future readers
In my controller I only get these two
$car = Car::where('fuelRemaining', 0)->get(array('id', 'desc'));
When i added authorID to the get array
$car = Car::where('fuelRemaining', 0)->get(array('id', 'desc', 'authorID'));
I am able to get the authorID attribute in my custom accessor mentioned in the question.