Laravel 5.2 Nested Eloquent relationships - php

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

Related

Laravel hasManyThrough polymorphic table not working

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

Laravel Polymorphic Relations returns NULL

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;

laravel 4 hasOne/ hasMany / belongsTo doesn't work

I have some models belong to Activity Model.
in my Activity.php I had
<?php
class Activity extends \Eloquent {
protected $fillable = [];
public function activity_car_nums()
{
return $this->hasMany('ActivityCarNum');
}
public function newables()
{
return $this->hasMany('Newable');
}
public function serial_codes()
{
return $this->hasMany('SerialCode');
}
public function applys()
{
return $this->hasMany('Apply');
}
}
and in SerialCode.php, I had
<?php
class SerialCode extends \Eloquent {
protected $fillable = ['code'];
public function activity()
{
return $this->belongsTo('Activity');
}
}
and in my controller, when I wrote
$serial_codes = [];
while(count($serial_codes) < $serial_code_total)
{
$code = substr(md5(uniqid(rand(), true)),0,5);
$serial_code = new SerialCode(['code' => $code]);
if(!in_array($serial_code, $serial_codes))
{
$serial_codes[] = $serial_code;
}
}
$activity->serial_codes()->saveMany($serial_codes);
it works.
But when it turns to
//this can get activity object
$activity = Activity::find($id);
//this can get the serial codes of the object above.
$serial_codes = SerialCode::whereActivityId($id)->get();
//this don't work, it returns null
$serial_codes = $activity->serial_codes;
for I really don't know why...
Can anybody help me please, and sorry for my poor English. Thank You.
(If you need any code else please tell me.)
my model code:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use DB;
class Product extends Model
{
public $table="s_products";
protected $primaryKey = 'product_id';
public function reviews()
{
return $this->hasMany('App\ProductReview');
}
public function attributes()
{
return $this->hasMany('App\AttributeMapping');
}
public function images()
{
return $this->hasMany('App\Image');
}
}
I found the reason that why my model query cannot work, because the "_" in function name.
just change
public function serial_codes()
to
public function serialcodes()
then everything will go fine.
Thank to everybody.

Laravel model object chaining

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.

Laravel 4 / Eloquent ORM: Is it possible to obtain the object behind a relation?

Assuming I have these two classes:
class User extends Eloquent
{
public function phone()
{
return $this->hasMany('phone');
}
}
class Phone extends Eloquent
{
public function user()
{
return $this->belongsTo('user');
}
}
(Relationships aren't necessarily presented in this way.)
I'm trying to achieve this by using accessors:
class Phone extends Eloquent
{
public function user()
{
return $this->belongsTo('user');
}
public function getNumberAttribute($value)
{
//Grant access to the User object who has this Phone.
$userWhoOwnsThisPhoneNumber = /*SOMETHING*/;
/*For example, $userWhoOwnsThisPhoneNumber->phone should return THIS phone object. */
//...
}
}
Then perhaps do something like this:
$user = User::find($id)->phone->number;
I skimmed through the documentations multiple times, I couldn't find anything useful. Is it possible to do such as thing with Laravel 4?
Because you might have more than one phone for each user, your relations should be:
class User extends Eloquent
{
public function phones() /// <--- this is just to be clearer
{
return $this->hasMany('phone');
}
}
class Phone extends Eloquent
{
public function user()
{
return $this->belongsTo('user');
}
}
And you don't need any acessors, unless you need to change anything in the number, so you can just:
$user = User::find($id);
$phones = $user->phones;
foreach ($phones as $phone)
{
echo $phone->user->name;
}
or just
foreach (User::find($id)->phones as $phone)
{
echo $phone->user->name;
}
And you can also
$phone = Phone::where('number','555-5050')->first();
echo $phone->user->name;

Categories