Laravel : One is to Many Relationship, get foreign key value - php

I'm currently working on productcategories and products relationship
which is one is to many.
I wonder why i'm having this error
Call to undefined method stdClass::products()
Here's my model for Products
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public $table = "products";
public $fillable = ['productcategory_id',
'name',
'description',
'price',
'pic',
'availability',
'featured',
];
public function productcategory()
{
return $this->belongsTo('App\ProductCategory');
}
}
and here's my model for Product Category
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ProductCategory extends Model
{
public $table = "productcategories";
public $fillable = ['name',
'description',];
public function products(){
return $this->hasMany('App\Product','productcategory_id','id');
}
}
and Here's my view file
#foreach($productcategories as $productcategory)
#foreach($productcategory->products() as $product)
{{ $product->name }}
#endforeach
#endforeach
Please help me i'm getting this error all the time.

Just shooting in the dark here, but I would first remove the parentheses in your view file from $productcategory->products(). If that doesn't solve the issue, dd($productcategories) in your Controller and verify that you're passing a Collection of ProductCategory as I wouldn't expect the resulting error to include reference to "stdClass".

Related

Sync function in laravel not working as expected

I have an edit form which should update an activity with selected categories, but the sync function isn't working as expected.
It adds the selected checkboxes to the database but doesn't delete the old values. Resulting in mutliple of the same values in the pivot table.
form code:
<p class="activiteit-categorie">
<label>categorie</label>
#foreach ($categories as $categorie)
<div class="categorie-input">
<input type="checkbox" name="categories[]" value="{{ $categorie->id }}"><label for="categorie">{{$categorie->name}}</label><br>
</div>
#endforeach
</p>
controller code:
if ($request->has('categories')) {
$activiteit->categorie()->sync($request->input('categories'));
} else {
$activiteit->categorie()->detach($request->input('categories'));
}
return redirect()->route('active-overview')->with('message', 'Activiteit is succesvol aangepast!');
models categorie:
namespace App;
use Illuminate\Database\Eloquent\Model;
class categorie extends Model
{
protected $fillable = [
'name'
];
public function activiteit() {
return $this->BelongsToMany('App\activiteit');
}
}
model activiteit:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class activiteit extends Model
{
protected $fillable = [
'name', 'image', 'intro', 'goal', 'traject', 'extra_info', 'duration', 'price'
];
public function categorie() {
return $this->belongsToMany('App\categorie');
}
}
You can try this
class categorie extends Model{
protected $fillable = [
'name'
];
public function activiteit() {
return $this->BelongsToMany('App\activiteit','pivot_table_name','categorie_id','activiteit_id');
}
}
Use like this another Model
if ($request->has('categories')) {
$activiteit->categorie()->sync($request->categories);
} else {
$activiteit->categorie()->detach($request->categories);
}
It works fine for me
So after trying some stuff out I came up with a simple solution to my problem.
I first detach all the categories from the selected activity and then add selected categories to the pivot table.
$activiteit->categorie()->detach();
if ($request->has('categories')) {
$activiteit->categorie()->sync($request->categories);
}

App\Todo::lead must return a relationship instance, but "null" was returned. Was the "return" keyword used?

I have Todo and Tbl_leads model and there corresponding tables todos and tbl_leads. When I am trying todo have the lead name it throw me an error.
#This is Tbl_leads model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tbl_leads extends Model
{
//Table Name
protected $table = 'tbl_leads';
//Primary key
public $primaryKey = 'ld_id';
//Timestamps
public $timestamps = true;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'ld_id', 'first_name', 'last_name', 'email',
];
public function tasks() {
$this->hasMany('App\Todo', 'lead_id','ld_id');
}
}
This is Todo Model
<?php
namespace App;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Todo extends Model
{
use SoftDeletes;
protected $fillable = [
'title',
'description',
'user_id',
'outcome_id',
'lead_id',
'tasktype_id',
'due_time',
'complete_time',
];
protected $casts = [
'due_time' => 'datetime',
'complete_time',
];
public function lead() {
$this->belongsTo('App\Tbl_leads', 'lead_id');
}
}
This is my index method
public function index()
{
$tasks = Todo::latest()->paginate(5);
return view('taskmanagement.cruds.index',compact('tasks'));
}
this is blade where I want get the the first name from Tbl_leads model
div class="card-body">
<ul class="todo-list" data-widget="todo-list">
#forelse($tasks as $task)
<div class="col-3">
#if(!empty($task->lead_id))
<div>
<small>Related to</small>
</div>
<div class="mt-0">
<a href="#">
<strong class="mx-4">{{$task->lead->first_name}}</strong>
</a>
</div>
#endif
</div>
</div>
</div>
</li>
#empty
<p class="text-center">No Tasks is available</p>
#endforelse
Plz can anyone tells me what I have done wrong. And I know the model name and there primary key slightly different is not set accordingly to laravel. Is my model relationship correct?
Let me clarify few points to you. Firstly you need to put a return in each relationship. For example:
public function lead() {
return $this->belongsTo('App\Tbl_leads', 'lead_id');
}
Next thing you are showing this portion {{$task->lead->first_name}} which is called lazy loading. It means if you are displaying 100 records of Todo then you are querying database 101 times. 1 for Todo and 100 times for lead->first_name. Which is not good. So what you can do in your index method pass your relation in with() so that it will be eager loaded. Means it will become just one or two query or simply a join. So it will be fast. Example of your index method...
public function index()
{
$tasks = Todo::with('lead')->latest()->paginate(5);
return view('taskmanagement.cruds.index',compact('tasks'));
}

Append new element to eloquent collection

I have two tables posts and photos. Each post has 5 photos. I want to list in view each post with one photo (profile pic), first picture.
$published_post = Post::where('created_by',auth()->user()->id)
->where('status','published')
->get();
$photo = Photo::where('post',$published_post->id)->get();
These two gives me two different collection. How can I add the first photo of a particular post to its array so in view I can display using a foreach loop.
This is how I want in view:
#foreach($published_post as $item)
{{ $item->title }}
{{ $item->profile_photo }}
#endforeach
I tried put and push, but doesn't seem to be working. Not sure how exactly does we append a new key value pair to an object.
My two models:
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->timestamps();
});
Schema::create('photos', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('image');
$table->integer('post');
$table->timestamps();
});
class Post extends Model
{
protected $table = 'posts';
}
class Photo extends Model
{
protected $table = 'photos';
protected $fillable = ['image', 'post'];
}
Post Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/*This is used to specify the table which this model is associated with*/
protected $table = 'posts';
protected $fillable = [
'title'
];
public $timestamps = true;
public function photos(){
return $this->hasMany(Photos::class,'post');
//post is the foreign key for posts table
}
}
Photo Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Photo extends Model
{
/*This is used to specify the table which this model is associated with*/
protected $table = 'photos';
protected $fillable = [
'image', 'post'
];
public $timestamps = true;
}
View:
#foreach($published_post as $item)
{{ $item->title }}
{{ $item->photos->first()->image }} // photos relation is invoked and fetched first image
#endforeach
You need to create 2 Models, one for Posts and one for Photos.
php artisan make:model Post
php artisan make:model Photo
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Posts extends Model
{
//
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Photo extends Model
{
//
}
Then create a hasMany relationship on the Post model to link to the Photo model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Photo;
class Post extends Model
{
public function photos()
{
return $this->hasMany(Photo::class);
}
}
Then in your view you can lazy load the photos whenever you like
#foreach($posts as $post)
{{ $post->title }}
{{ $post->photo[0]->name}}
#endforeach
The syntax to go in your view will be slightly different, but this gives you a good idea on how the functionality should work.
Ok, first you should change your Post model like this:
class Post extends Model
{
protected $table = 'posts';
public function photos()
{
return $this->hasMany(Photo::class, 'post');
}
}
And then, add the following to your Photo model:
class Photo extends Model
{
protected $table = 'photos';
public function post()
{
return $this->belongsTo(Post::class, 'post');
}
}
With this, you've created the relation between your models, and now you can get your data this way:
$published_post = Post::where('created_by',auth()->user()->id)
->where('status','published')
->with('photos')
->get();
And in your view, you can get the first photo this way:
#foreach($published_post as $item)
{{ $item->title }}
{{ $item->photos()->first()->name }}
#endforeach
For more info on relations, you might want to read the docs.
I hope this helps!

How to create a relationship in laravel

Am new to laravel, I have issues trying to connect this tables: plans,users and loans even after reading the docs,
I have a plans tables that have all my plans, then I have a users table and loans table, my loans table has a user_id and a plan_id, all I want is to pull the records for plans and the users in the loan model.
Loanplan.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loanplan extends Model
{
//
protected $fillable = [
'title',
'amount',
'interest',
'repayment_month',
'status',
];
public function loan()
{
return $this->belongsTo('App\loan');
}
}
my loan model:
Loan.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $table = 'loans';
//
protected $fillable = [
'id',
'user_id',
'loanplan_id',
'payment_made',
'status',
];
public function user()
{
return $this->belongsTo('App\User');
}
public function loanplan()
{
return $this->belongsTo('App\Loanplan');
}
}
I want get all the loan plans and users table records with plan_id and user_id as foreign respectively respectively in my LoanController.
I think the problem is with the customization of the loans table name in the Loanplan model.
According with your descriptions you need the followings setup:
A User can access to one or many Loans
users 1---m plans
A Loan belongs to a Loanplan // here I'm using Loanplan because that is your model name.
loans 1---m plans
So, this means:
User.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'users';
//
protected $fillable = [
'id',
//
];
public function loans()
{
return $this->hasMany(Loan::class);
}
//
}
Loan.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $table = 'loans';
//
protected $fillable = [
'id',
'user_id',
'loanplan_id',
//
];
public function user()
{
return $this->belongsTo(User::class);
}
public function plan()
{
// Notice that here I'm specifying the foreign key:
return $this->belongsTo(Loanplan::class);
}
//
}
Loanplan.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loanplan extends Model
{
protected $table = 'plans';
//
protected $fillable = [
'id',
//
];
public function loans()
{
return $this->hasMany(Loan::class);
}
//
}
So with this, you can access the information in your LoanController.php:
LoanController.php
public function myCoolMethod()
{
// get a user
$user = User::first();
// access his/her loans
$loans = user->loans;
//
// get a loan plan
$plan = Loanplan::first();
// access its loans
$loans = plan->loans;
//
}
I strongly suggest you to read the Laravel Documentation regarding relationships and also a course for database design. Have a good day mate.
Loanplan.php is missing the protected $table = "plans" variable
Same file,
public function loan()
{
return $this->belongsTo('App\loan');
}
the relationship should be hasOne or hasMany, not belongsTo.
Moreover, the name of the class should have Loan with capital L.
public function loan()
{
return $this->...('App\Loan');
}
First of all add protected $table = 'plans'; to your Loanplan model since the table name is 'plans'
Loanplan Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loanplan extends Model
{
protected $table = 'plans';
protected $fillable = [
'title',
'amount',
'interest',
'repayment_month',
'status',
];
public function loan()
{
return $this->hasOne('App\loan'); // or hasMany
}
}
?>
Loan Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $table = 'loans';
//
protected $fillable = [
'id',
'user_id',
'loanplan_id',
'payment_made',
'status',
];
public function user()
{
return $this->belongsTo('App\User');
}
public function loanplan()
{
return $this->belongsTo('App\Loanplan');
}
}
?>
add this to the User Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function Loan()
{
return $this->hasOne('App\Loan'); // or hasMany
}
}
?>
First, you have to check if the model already querying from table that you created before. Laravel will automatically access table base on your class name.
Note that we did not tell Eloquent which table to use for our Flight model. By convention, the "snake case", plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the Flight model stores records in the flights table.
You can read it from this documentation
Second, make sure you call the right class. From Loanplan.php in the loan() method it's not using uppercase for the first letter.
Third, try to state the foreign key and primary key. You can also check how to do it in the documentation.

How do I get the user-name in every thread (Laravel)?

I wan't to get the name of the user who created is own thread. Like Michael did a thread about food. So at the bottom of the food-thread should be the name of Michael.
I've wrote the code for this but it doesn't really works. Maybe someone of you can find the mistake.
I have two models. A thread Model and a users model.
thread model:
<?php
namespace App\Models\Thread;
use Illuminate\Database\Eloquent\Model;
use App\User;
class Thread extends Model {
public $table = 'thread';
public $fillable = [
'thread',
'content',
'user_id'
];
public function userthread() {
return $this->belongsTo('User','user_id', 'id');
user model:
<?php
namespace App;
use ...
protected $table = 'users';
protected $fillable = ['name', 'email', 'password'];
protected $hidden = ['password', 'remember_token'];
public function threaduser() {
return $this->hasMany('App\Models\Thread\Thread','user_id', 'id');
}
}
and now the controller method, where I'm trying to get the name:
public function show($id)
{
$thread = Thread::query()->findOrFail($id);
$threaduser = Thread::where('user_id', Auth::user()->id)->with('userthread')->get();
return view('test.show', [
'thread' => $thread,
'threaduser' => $threaduser
]);
}
in my html:
{{$threaduser->name}}
The error message I get is :
Undefined property: Illuminate\Database\Eloquent\Collection::$name (View: /var/www/laravel/logs/resources/views/test/show.blade.php)
I hope someone can help me there.
change it to
{{$threaduser->userthread->name}}
change userthread() function in your Thread Class to
public function userthread() {
return $this->belongsTo('App\User','user_id', 'id');
}
get() gives you a Collection not a Model you either have to do a foreach on it like
#foreach ($threadusers as $threaduser)
{{ $threaduser->userthread->name }}
#endforeach
Or use first instead of get if there is only one Thread per User.
Depending on what you want to do, of course.

Categories