accessing a parent of a parent relationship laravel - laravel

I am building an application in laravel in which each channel has some sections and you can post threads in the sections. I would like to access the channel from the thread.
The hierarchy so far is this
-channel
--section
---threads
here are the three model classes
channel
use Illuminate\Database\Eloquent\Model;
class Channel extends Model
{
public function users(){
return $this->belongsToMany('App\User');
}
public function posts(){
return $this->hasMany('App\Post');
}
public function isSubscribed($id){
return $this->users()->find($id);
}
public function sections(){
return $this->hasMany('App\Section');
}
}
section
{
public function channel(){
return $this->belongsTo('App\Channel');
}
public function threads(){
return $this->hasMany('App\Thread');
}
}
thread
{
protected $fillable=['title','body','solved'];
public function solutions(){
return $this->hasMany('App\Solution');
}
public function comments(){
return $this->hasMany('App\ThreadComment');
}
public function section(){
return $this->belongsTo('App\Section');
}
public function arguments(){
return $this->belongsToMany('App\Argument');
}
public function user(){
return $this->belongsTo('App\User');
}
public function reports(){
return $this->morphTo('App\Report','reportable');
}
}
what I would like to do is to have a channel() method in thread class that makes me access the channel without having to do $thread->section->channel each time

If you really want to, use an accesor.
public function getChannelAttribute()
{
return $this->section->channel;
}

If you don't have a problem using a package for this, use https://github.com/staudenmeir/eloquent-has-many-deep. You can have any levels of relationships.
Read the usage section of the package for details.

Related

hasManyThough returns null - Eloquent

I'm looking to retrieve all transactions of an event which are created by a booking. I was thinking of using a hasManyThrough relationship. However it returns null. What am I doing wrong?
Event model:
public function booking(){
return $this->hasMany(Booking::class);
}
public function transaction(){
$this->hasManyThrough(Transaction::class, Booking::class);
}
Booking model:
public function event() {
return $this->belongsTo(Event::class);
}
public function user() {
return $this->belongsTo(User::class);
}
public function transaction(){
return $this->hasMany(Transaction::class);
}
Transaction model:
public function booking() {
return $this->belongsTo(Booking::class);
}
public function user() {
return $this->belongsTo(User::class);
}
My tables look like so

Laravel relationship "fallback"

class Price extends Model {
public function priceable() {
return $this->morphTo();
}
}
class Venue extends Model {
public function events() {
return $this->hasMany('App\Event');
}
public function price() {
return $this->morphOne('App\Price', 'priceable');
}
}
class Event extends Model {
public function venue() {
return $this->belongsTo('App\Venue');
}
public function price() {
return $this->morphOne('App\Price', 'priceable');
}
}
What is the best way to have a fallback, if the event doesn't have a price assigned, to get it to use the event's venue price?
Is there a logical way to make this as a relation or should I just do everything in the Controllers?
You can set a default model with optional custom values directly from the relation. This default model can be populated either from an array or an anonymous function:
public function price()
{
return $this->morphOne('App\Price', 'priceable')->withDefault([...]);
}
You can refer to Laravel's documentation about default models for some more explanation.
class Event extends Model {
...
public function getEventPriceAttribute() {
return $this->price > 0 ? $this->price : $this->venue()->price
}
...
}
By doing this, you can call Event object and get the price like this:
$eventObject->eventPrice;

laravel relationship between 5 tables

I have 5 tables User, Profile, Address,State,City .Need to create relationship between tables.Address has State id , City id and Profile id in the table.Profile has User Id in the table.City has State Id in the table. How to write relationship between table
class City extends Model
{
public function state() {
return $this->belongsTo('App\State');
}
public function addresses() {
return $this->hasMany('App\Address');
}
}
class State extends Model
{
public function cities() {
return $this->hasMany('App\City');
}
public function addresses() {
return $this->hasMany('App\Address');
}
}
class Profile extends Model
{
public function address() {
return $this->belongsTo('App\Address');
}
public function user() {
return $this->belongsTo('App\User');
}
}
class Address extends Model
{
public function profile() {
return $this->belongsTo('App\Profile');
}
public function city() {
return $this->belongsTo('App\City');
}
public function state() {
return $this->belongsTo('App\State');
}
}
// users table
public function profile(){
return $this->hasOne('App\Profile');
}
Generally your model design is true, i have edited a few parts. Try the codes below.
class City extends Model
{
public function state()
{
return $this->belongsTo('App\State');
}
public function addresses()
{
return $this->hasMany('App\Address');
}
}
class State extends Model
{
public function cities()
{
return $this->hasMany('App\City');
}
public function addresses()
{
return $this->hasMany('App\Address');
}
}
class Profile extends Model
{
public function addresses()
{
return $this->hasMany('App\Address');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
class Address extends Model
{
public function profile()
{
return $this->belongsTo('App\Profile');
}
public function city()
{
return $this->belongsTo('App\City');
}
public function state()
{
return $this->belongsTo('App\State');
}
}
class User extends Model
{
public function profile()
{
return $this->hasOne('App\Profile');
}
}
By the way, Laravel relationships add default keys according to your method names. If you have problem about it you can find info from official documents. For example:
$this->belongsTo('App\Model', 'foreign_key', 'other_key');
as #mustafa.akcoban says...
When you use belongsTo Eloquent will work as follow
$this->belongsTo('App\City', 'foreign_key', 'other_key');
// foreign_key = is the primary key in the related model, by default 'id' for Eloquent
// other_key = is the field in the current model that contains the id of the other model, by default othermodelname_id for Eloquent
// For eg. 'App\City', 'id', 'city_id'
When you use hasMany Eloquent works as follow
$this->hasMany('App\Model', 'currentmodel_id', 'primary_key');
// currentmodel_id = is the field that contains the current model primary key in the related model
// primary_key = is the current primary key model that will be in the other model, by default id for Eloquent
// For eg. 'App\City', 'state_id', 'id'
Remember you can or can't use second and third parameter, if something is wrong Laravel dump will tell you what column was not found in the table, and you will can fix.
Please try and practice this, and let me know how it works :)

Complex relationship formation in Laravel 5

I'm working on a complex shopping cart project. I have relationships like this
CategoryGroup model
// App\CategoryGroup
class CategoryGroup extend Model
{
public function categories()
{
return $this->hasMany(Category::class);
}
}
Category model
// App\Category
class Inventory extend Model
{
public function categoryGroup()
{
return $this->belongsTo(CategoryGroup::class);
}
public function products()
{
return $this->belongsToMany(Product::class);
}
public function listings()
{
return $this->belongsToMany(
Inventory::class,
'category_product',
null,
'product_id',
null,
'product_id'
);
}
}
Product model
// App\Product
class Product extend Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
public function listings()
{
return $this->hasMany(Inventory::class);
}
}
Inventory model
// App\Inventory
class Inventory extend Model
{
public function products()
{
return $this->belongsTo(Product::class);
}
}
Now I'm stuck on the situation where I need to create a relationship between The CategoryGroups and the Inventory model like this:
// App\CategoryGroup
class CategoryGroup extend Model
{
public function categories()
{
return $this->hasMany(Category::class);
}
public function listings()
{
// Can't figured out the way
// A belongsToMany like the App\Category would be great
}
}
Is there a good way to achieve this kind of relationship?
Laravel has no native support for a direct relationship.
I created a package for cases like this: https://github.com/staudenmeir/eloquent-has-many-deep
You can use it like this:
class CategoryGroup extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function inventories() {
return $this->hasManyDeep(
Inventory::class,
[Category::class, 'category_product', Product::class]
);
}
}

Laravel Relationship error trying to call a relationship within the model

On Laravel "4.1.x-dev",
How can I call a method on a relation within the model? From the below example
public function userLink() {
return $this->user->link;
}
My function userLink gives me the error : Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
Also is there another way for me to access the linked user from Drawing with some kind of eager loading trick?
I have several different type of users. Each type of user has it's own table with an ID in each table that corresponds to the *ID** of the users table. In my Users model I have a method called ''link'' that performs a ''morphTo'' and gets me the correct user object.
class Drawing extends Eloquent {
public function user() {
return $this->belongsTo('User', 'user_id');
}
// this throws the relation error above, also I beleive this does two queries, anyway to improve this?
public function userLink() {
return $this->user->link;
}
}
class User extends Eloquent {
public function link() {
return $this->morphTo('User', 'type', 'id');
}
}
class Retailer extends Eloquent {
public function user() {
return $this->belongsTo('User', 'id');
}
}
class Manufacturer extends Eloquent {
public function user() {
return $this->belongsTo('User', 'id');
}
}
Try this instead:
Drawing::first()->user->link;
or this:
// Drawing model
public function user()
{
return $this->belongsTo('User', 'user_id');
}
// Drawing model
// Requires above relation
public function userLink()
{
return $this->user->link;
}
Then:
$ulink = Drawing::first()->userLink();
Also check the Defining An Accessor.
Update: Just make changes to your method like this (Create an accessor):
public function getUserLinkAttribute()
{
return $this->user->link;
}

Resources