Laravel cannot get relationship data of a selected profile - laravel

I just created a profile for users, and wish to show the education details related to the logged-in user or another selected user.
for this, I created an education model for users and gave a proper relationship to it both the sides. im not able to get any data from the education table of loged in user or another user. i used foreach tag in blade file. please revview my code. thanks.
Education Model
class Education extends Model
{
use HasFactory;
protected $primaryKey = 'education_id';
public function myusers()
{
return $this->belongsTo('App\Models\User','user_id','education_id');
}
}
User Model
public function myeducation()
{
return $this->hasMany('App\Models\Education','education_id','user_id');
}
Profile Controller
public function index()
{
$user = Auth::user();
return view('candidate.profile',['user'=>$user,]);
}
Blade file
#foreach ($user->myeducation as $education)
<div>
{{ $education->school }}
</div>
#endforeach
Table Structure of Education and Users
**Education Table**
{
Schema::create('education', function (Blueprint $table) {
$table->bigIncrements('education_id');
$table->bigInteger('user_id');
$table->string('school');
$table->string('degree');
$table->string('fieldOfStudy');
$table->date('startDate');
$table->date('endDate');
$table->string('grade');
$table->string('activities');
$table->string('description');
$table->timestamps();
});
}
user table.
$table->increments('user_id');
$table->bigInteger('role_id');
$table->bigInteger('membership_id')->nullable();
$table->string('firstname');
$table->string('lastname');
there is no error message, but just blank
Table entries
DB::table('education')
'user_id' => '2',
'school' => 'University of Bedfordshire',
'degree' => 'MBA',
]);
DB::table('users')->insert([
'user_id' => '1',
'role_id' => '1',
'firstname' => 'Mohammed',
'lastname' => 'Sabeel',
.......
]);
DB::table('users')
' user_id' => '2'
'role_id' => '2',
'firstname' => 'zahida',
'lastname' => 'sabeel',
.......
]);

the problem is in your relationship second and third argument. you are passing keys in wrong way.
in Education model use code like
public function myUser()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
you need not to pass the third argument if you use the primary key for relationship. though you can pass the third argument to define which column to use to join the tables
public function myUser()
{
return $this->belongsTo('App\Models\User', 'user_id', 'user_id');
// second argument user_id is from your education model while the third argument that is user_id is the primary key of your user model
// i have used singular name for the relationship name with camel case
}
now in User model
public function myEducations()
{
return $this->hasMany('App\Models\Education', 'user_id');
// user_id is the user_id of education model
// and this is a has many relation i used plural form
}
read more about relationship in laravel doc

Before we begin, make sure that you have Education associated with that logged in User.
Try eager loading you relationship. Sometime this worked for me.
In your profile controller,
public function index()
{
$user = Auth::user()->load('myeducation');
return view('candidate.profile',['user'=>$user,]);
}
Even if it didn't work, Please share your table structure and table entries. So that we can examine clearly.

Related

Fetch Specific Columns in table with specific column in relationship table in Laravel Eloquent

Here I have two model. User and Company.
Inside User model:
public function company()
{
return $this->hasOne(Company::class);
}
Inside Company model:
public function user()
{
return $this->belongsTo(User::class);
}
And when I fetch users using query below:
User::query()
->with(array('company' => function($company) {
return $company->select('id', 'company_name');
}))->get()->map->only([
'id', 'email', 'has_employees', 'created', 'status', 'last_login_ago_day', 'company_name'
]);
This code returns only specific column of User model. I want to return also the specific column of Company model. How should I do that?
Need to add foreign key id inside company closure function and in this case the user_id
User::query()->role('admin')->with(['company' => function($company) {
$company->select('user_id', 'company_name');
}])->get()
->map->only([
'id', 'email', 'has_employees', 'created', 'status', 'last_login_ago_day', 'company'
]);

Laravel how to save belongstomany in store controller?

I can save my ticket inside a ticket table. But i also have a ticket_user table with inside a ticket_id and a user_id. So when the user press save it need to automaticlay pick also the ticket_id and the user_id inside the ticket_user table. I have a many to many table between Users and Ticket.
this is the error i get Call to a member function attach() on null
User Models
public function ticket(){
return $this->belongsToMany(Ticket::class, 'ticket_user');
}
Ticket models
public function users() {
$this->belongsToMany(User::class, 'ticket_user');
}
Controller
public function store(Request $request)
{
$this->validate($request, array(
'title' => 'required',
'ticket' => 'required'
));
$ticket = new Ticket;
$ticket->title = $request->title;
$ticket->ticket = $request->ticket;
$ticket->save();
$ticket->users()->attach($request->input('user_id'));
return redirect()->route('users.tickets.index');
}
You are not returning anything in users function in Ticket class.
public function users() {
return $this->belongsToMany(User::class, 'ticket_user');
}

How to make Laravel Resources work with polymorphic relation

I have a polymorphic relation in a Laravel application. I want a user of the website to be able to give a rating to both a User model as well as Product model.
I have following models and relations
class Rating extends Model
{
public function ratable()
{
return $this->morphTo();
}
}
class User extends Authenticatable
{
public function ratings()
{
return $this->morphMany('App\Rating', 'ratable');
}
}
class Product extends Model
{
public function ratings()
{
return $this->morphMany('App\Rating', 'ratable');
}
}
and the following database migration:
class CreateRatingsTable extends Migration
{
public function up()
{
Schema::create('ratings', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('ratable_id');
$table->string('ratable_type');
$table->double('rating');
$table->text('comment');
$table->timestamps();
});
}
}
I have defined two routes:
1) Route::post('products/{product}/rating', 'ProductController#setRating')->name('products.rating');
2) Route::post('users/{user}/rating', 'UserController#setRating')->name('users.rating');
I have the following code in the controller (will only show the Product example)
public function setRating(Request $request, Product $product)
{
$rating = new Rating();
$rating->rating = $request->rating;
$rating->comment = $request->comment;
$product->ratings()->save($rating);
}
The above works perfectly and the correct records get inserted in the database depending on whether the Product route or the User route is called.
Now, all the rest of my code is using Laravel Resources, and for consistency reasons, I have also defined a resource for Rating:
class RatingResource extends JsonResource
{
public function toArray($request)
{
return [
'ratable_id' => $this->ratable_id,
'ratable_type' => $this->ratable_type,
'rating' => $this->rating,
'comment' => $this->comment
];
}
}
I'm also changing the ProductController code to use this resource
public function setRating(Request $request, Product $product)
{
return new RatingResource(Rating::create([
'ratable_id' => $product->id,
'ratable_type' => $product,
'rating' => $request->rating,
'comment' => $request->comment,
]));
}
In postman, I'm calling the REST API:
http://{{url}}/api/products/1/rating with body:
rating: 4
comment: "Test"
Yet, I always get following error message
"SQLSTATE[HY000]: General error: 1364 Field 'ratable_id'
doesn't have a default value (SQL: insert into ratings (rating,
comment, updated_at, created_at) values (4, test, 2019-09-07
13:44:22, 2019-09-07 13:44:22))"
I'm not passing the ratable_id and ratable_typeas I'm filling these in already in the controller code.
I somehow need to pass the resource that it's a Productor a UserI'm giving a rating for.
How can I make this work?
The problem probably is that ratable_id is missing from $fillable.
Try $product->ratings()->create([...data...]) so you don't have to set ratable_id and ratable_type yourself:
public function setRating(Request $request, Product $product)
{
return new RatingResource(
$product->ratings()->create([
'rating' => $request->rating,
'comment' => $request->comment,
])
);
}

Laravel 5.6 eager load nested childrelations

I'm having an issue with getting child relations from a Card object to a User object. The relations are as following:
'User' -> hasOne 'Company'
'Company' -> hasMany 'Card'
So the other way around is:
'Card' -> belongsTo 'Company'
'Company' -> belongsTo 'User'
My Card model has got this:
public function company()
{
return $this->belongsTo('App\Company');
}
My Company model has got this:
public function user()
{
return $this->belongsTo('App\User');
}
public function cards()
{
return $this->hasMany('App\Card');
}
My User model has got this:
public function company()
{
return $this->hasOne('App\Company');
}
What I want to do is: in the User model I want to eager load all cards from that user. So my code looks like this:
$cards = Card::with('company.user')->get();
But it's constantly returning me all the card records in the database, not the ones that are from the logged in user itself. There definitely
is a userID, cause when I dump $this->id in the User model, I'm getting the ID '1'. In the database I've configured all foreign keys so that won't be the problem I assume.
Table 'cards' has a foreign key to 'company_id', and table 'companies' has a foreign key to 'user_id', they are all set by the migration script, which looks like this:
Schema::create('cards', function (Blueprint $table) {
$table->increments('id');
$table->integer('amount');
$table->string('status');
$table->unsignedInteger('company_id');
$table->timestamp('expires_at')->nullable();
$table->boolean('is_debit_allowed')->default(1);
$table->string('cancelled_by')->nullable();
$table->timestamp('cancelled_at')->nullable();
$table->timestamps();
$table->foreign('company_id')->references('id')->on('companies');
});
What am I doing wrong guys?
In the User model, you can add it to the $with array:
// this will eager load the company and cards for every user query, so beware!
protected $with = ['company.cards'];
Or create a new function cards:
public function cards()
{
return $this->company->cards;
}
$cards = $user->cards();
// use the auth helper to get logged in user's cards
$cards = auth()->user()->cards();
This should work for accessing via Card:
$cards = Card::whereHas('company.user', function ($query) {
$query->whereKey(auth()->id());
})->get();

Laravel getting users from multiple messages

I've got offers table with id's
Messages table with columns offer_id and from
and Users table with id's
I want to get users starting with offer $this in OfferResource
My goal is to get users that have replied to the offer with at least one message.
I started to configure Offer model with function messages to get messages
public function messages(){
return $this -> hasMany('App\Message');
}
so I'm able to get all messages (starting from offer resource):
'users' => $this->messages
How should I now configure messages model to get all users instead of messages?
I tried to write in Message model :
public function fromContact()
{
return $this->hasOne(User::class, 'id', 'from');
}
and then:
'users' => $this->messages->fromContact
but i've got error: "message": "Property [fromContact] does not exist on this collection instance.",
How should I correct my code to make this work?
I am assuming the from field on the Messages table is populated using user ID. Then you could establish belongsToMany relationship between the Offer and User models. Since this is actually a many-to-many relation with a pivot table messages.
In the Offer model define
public function users()
{
return $this->belongsToMany('App\User', 'messages', 'offer_id', 'from');
}
Then from the OfferResource you could load the offers data like this—
$offers = App\Offer::with('users')->get();
Then loop over the $offers like this:
foreach ($offers as $offer) {
dd($offer->users); // one offer will have multiple users as a Collection
}
Similarly for an $offer of ID 1 you could do this
$offer = App\Offer::with('users')->find(1)
Then to get the users that commented on this offer just use $offer->users
See the official documentation for defining many-to-many relationship.
In the Message model you have to spesify the column that refer to the user :
public function fromContact()
{
return $this->hasOne(User::class, 'from');
}
And then after geting the messages loop over them to get the user like this :
foreach ($this->messages as $message) {
$user = $message->fromContact;
// do somthing with the user :)
}
Your messages table has from field that is referencing User model and offer_id field which referencing Offer model that means you have ManyToMany relations between Offer and User.
Offer Model
public function users(){
return $this->belongsToMany(User::class, 'messages', 'offer_id', 'from')->using('App\Message');
}
Message Pivot
class Message extends Pivot {
protected $table = 'messages';
}
User model
public function offers(){
return $this->belongsToMany(Offer::class, 'messages', 'from', 'offer_id')->using('App\Message');
}
OfferResource
public function toArray($request)
{
$users = $this->users;
return [
'id' => $this->id,
... //add your offer fields here
'users' => $users->toArray(), // here $users is a laravel Collection
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
Access from Controller or Route
Route::get('/offer', function () {
return new OfferResource(Offer::with('users')->find(1)); //eager load users
});

Resources