I've read many posts about this issue but none of them works for me. I have a 'ISA' relationship in my database. A person can be either a Patient or a Nurse:
class Person extends Model
{
protected $table = 'persons';
public function commentable()
{
return $this->morphTo();
}
}
class Patient extends Model
{
public function persons()
{
return $this->morphMany('App\Person', 'commentable');
}
}
class Nurse extends Model
{
public function persons()
{
return $this->morphMany('App\Person', 'commentable');
}
}
This is my tables and the data inside them:
And this is my Route:
Route::get('person', function () {
$person = Person::find(1)->commentable();
return json_decode(json_encode($person), true);
});
I get an empty array!
You have to access the relationship as a property:
$person = Person::find(1)->commentable;
Related
I have three models Driver Worker and Group. The models are like this:
class Group extends Model
{
.....
public function driver()
{
return $this->belongsTo('App\Driver');
}
public function worker()
{
return $this->belongsTo('App\Worker');
}
}
Drivers
class Driver extends Model
{
public function groups()
{
return $this->hasMany('App\Group');
}
}
Worker
class Workerextends Model
{
public function groups()
{
return $this->hasMany('App\Group');
}
}
But how can I get a single element with the relationships that I have defined in my models. I have this in my controller but I only get the first element of the table. I need to get the element with the id and also the relations.
public function show(Group $group)
{
return $group->with(['worker','driver'])->first();
}
try this
public function show(Group $group,$id){
$group = $group->where('id',$id)->with(['worker','driver'])->first();
return $group
}
in your Route
Route::get('/group/show/{id}', 'GroupController#show')->name('group.show');
I've following relationship:
class Project extends Model
{
public function invitors()
{
return $this->hasMany(Invitation::class)
}
}
// User model
class User extends Model
{
public function invitations()
{
return $this->morphMany('App\Invitation', 'invitee');
}
}
// Business Model
class Business extends Model
{
public function invitations()
{
return $this->morphMany('App\Invitation', 'invitee');
}
}
// Invitation model
class Invitation extends Model
{
public function invitee()
{
return $this->morphTo();
}
public function project()
{
return $this->belongsTo(Project::class);
}
}
What I want is to get project invitors (users, and businesses). When I use from $project->invitors->invitee its not working.
In your example $project->invitors is a collection of Invitation instances, and it hasn't property invitee. You can use helper pluck to loop $project->invitors and get their invitees:
$invitees = $project->invitors->pluck('invitee');
As a response to the first comment:
to get specific attributes of fetched linked models ("invitee") you can specify accessors:
class Business extends Model
{
...
public function getInviteeNameAttribute() {
return $this->name;
}
}
class User extends Model
{
...
public function getInviteeNameAttribute() {
return $this->first_name . ' ' . $this->last_name;
}
}
...then get that attribute from invitee:
$invitees[0]->invitee_name
See https://laravel.com/docs/7.x/eloquent-mutators#defining-an-accessor
Consider the following table structure:
user table
id
name
lang_region_id
lang_region table
id
lang_id
region_id
lang table
id
name
region table
id
name
Fairly new to the Laravel framework, but trying to setup Eloquent models and relationships to an existing database. I want to establish the relationship between my user model and the lang and region models. The lang_region table defines what language and region combinations are available and then we can link each user to a valid combination.
I have read through the Laravel documentation several times looking for the proper relationship type, but is seems that the Many to Many and Has Many Through relationships are close, but since our user.id isn't used in the intermediate table I may be out of luck.
Sorry for the amateur question, but just getting used to Laravel and ORMs in general.
I would use the lang_region table as both a pivot table and a regular table with its own model.
class LangRegion extends model
{
protected $table = 'lang_region';
public function language()
{
return $this->belongsTo(Language::class, 'lang_id');
}
public function region()
{
return $this->belongsTo(Region::class);
}
public function users()
{
return $this->hasMany(User::class);
}
}
class User extends model
{
protected $table = 'user';
public function langRegion()
{
return $this->belongsTo(LangRegion::class);
}
}
class Language extends model
{
protected $table = 'lang';
public function regions()
{
$this->belongsToMany(Region::class, 'lang_region', 'lang_id', 'region_id');
}
public function users()
{
$this->hasManyThrough(User::class, LangRegion::class, 'lang_id', 'lang_region_id');
}
}
class Region extends model
{
protected $table = 'region';
public function languages()
{
$this->belongsToMany(Language::class, 'lang_region', 'region_id', 'lang_id');
}
public function users()
{
$this->hasManyThrough(User::class, LangRegion::class, 'region_id', 'lang_region_id');
}
}
If I understand what you want correctly:
class User extends Model {
private function lang_region() {
return $this->hasOne(LangRegion::class)
}
public function lang() {
return $this->lang_region()->lang();
}
public function region() {
return $this->lang_region()->region();
}
}
class LangRegion extends Model {
public function lang() {
return $this->belongsTo(Lang::class);
}
public function region() {
return $this->belongsTo(Region::class);
}
}
I have a User which is of type Player and has several Equipments
I want to request a piece of Equipment and see if the User is it's owner before returning it to the user. If they do not own it they will get an unauthorized response
Here are the relationships I have for the models:
App\User.php
class User extends Authenticatable
{
protected $table = 'user';
public function player()
{
return $this->hasOne(Player::class);
}
}
App\Player.php
class Player extends Model
{
protected $table = 'player';
public function equipment()
{
return $this->hasMany(Equipment::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
App\Equipment.php
class Equipment extends Model
{
protected $table = 'equipement';
public function player()
{
return $this->belongsTo(Player::class);
}
}
EquipmentController.php
With my attempt which is working... just very ugly.
class EquipmentController extends Controller
{
public function show($id)
{
$equipment = Equipment::find($id);
if ( ! $equipment ) {
return 'Equipment does not exist');
}
// my attempt
$test = Equipment::with('player.user')->findOrFail($id);
if ($test->toArray()['player']['user']['id'] != Auth::user()->id){
return 'Unauthorized';
}
//
return $equipment;
}
}
Is there a neater way to do this?
I want something readable in the controller like:
if(!$equipment->ownedBy(Auth::user())){
return 'Unauthorized';
}
Or something similarly as readable.
And once the relationship is found, I'm not sure where the logic should be placed. Should it be in the Equipment model?
Any help would be much appreciated!
In your Equipment model:
public function authorized()
{
return ($this->player->user->id == auth()->user()->id())
}
Then from your controller, try:
$equipment->authorized() //returns true or false
For some reason, I cannot chain model objects. I'm trying to eager load 'Location' for an 'Order' and would prefer the logic to be contained in the models themselves. But past one chain, it does not work.
class Order extends Eloquent {
protected $table = 'orders';
public function customer() {
return $this->belongsTo('Customer');
public function location() {
return $this->customer()->location(); // this does not work
}
}
class Customer extends Eloquent {
protected $table = 'customers';
public function user() {
return $this->belongsTo('User');
}
public function orders() {
return $this->hasMany('Order');
}
public function location() {
return $this->user()->location();
// return $this->user(); // WORKS!!
}
}
class User extends Eloquent {
protected $table = 'users';
public function locations() {
return $this->hasMany('Location');
}
public function location() {
return $this->locations()->first();
}
}
I eventually want to do this:
class ChefController extends BaseController {
public function get_orders() {
$chef = $this->get_user_chef(); // this already works
return $chef->orders()->with('location')->get(); // does not work
}
}
Try to reference relation (user table) by adding user_id as second argument, like this:
public function user() {
return $this->belongsTo('User',"user_id");
}
Maybe you called that id field different, but you know what I mean.