Get attributes from relationship parent model - laravel

I'm loading some data for the user like this.
Method 1
$user->load(['subscription.payementTypes']);
Method 2
$user->load(['charity.payementTypes']);
Is there anyway I can figure out in the PaymentType model that it is called via subscription or charity?
I want to call an Accessor in PaymentType based on Subscription or Charity
// For Subscriptions
public function getPaymentDescriptionAttribute()
{
// if Subscription
// if Charity
}
The relationships are as follows.
//Class User
public function subscription()
{
return $this->hasOne(Subscription::class);
}
public function charity()
{
return $this->hasOne(Charity::class);
}
//Class Subscription
public function paymentTypes()
{
return $this->belongsToMany(PaymentType::class);
}

I feel like in class Subscription, you should name it paymentTypes. I'd say it's a hasMany though?
public function paymentTypes()
{
return $this->hasMany(PaymentType::class);
}
and in the PaymentType you can do
public function subscription
{
return $this->belongsTo(Subscription::class);
}

if it is not working you can do somthing like this
in User.php
//Class User
public function subscriptionWithPaymentType()
{
return $this->hasOne(Subscription::class)->with('paymentTypes');
}
then you can do this
$user->load(['subscriptionWithPaymentType']);

Related

Polymorphic relationship with other polymorphic realtion?

I have order and return tables which have a created_by and accepted_by field where the corresponding user id is stored.
But now I would like to have multiple types for created_by and accepted_by instead of only user type. Assume a company could also create or accept the order/return.
I was thinking of a polymorphic one to many relationship.
Let’s name this table participants.
Something like:
ID
created
participantable_id
participantable_type
1
1
1
user
2
0
11
company
This works either for order or return but not both.
Is it practically to add extra colums to participants like trx_id and trx_type (order/return)?
How would the realtionships looks like to perform queries like:
$order->createdBy // should give me either user or company model
$order->acceptedBy
$return->createdBy
$return->acceptedBy
Or is there even a cleaner solution I am overlooking?
Thanks!
It would be 1:N polymorphic relationships so no need for an extra table. The structure can be found in the documentation
Your Order and Return model need to have the columns created_by_id, created_by_type, accepted_by_id, accepted_by_type.
______ (1) Company
/
Order (N) ----<
\______ (1) User
_____ (1) Company
/
Return (N) ----<
\_____ (1) User
class Order extends Model
{
public function created_by()
{
return $this->morphTo(__FUNCTION__, 'created_by_type', 'created_by_id');
}
public function accepted_by()
{
return $this->morphTo(__FUNCTION__, 'accepted_by_type', 'accepted_by_id');
}
}
class Return extends Model
{
public function created_by()
{
return $this->morphTo(__FUNCTION__, 'created_by_type', 'created_by_id');
}
public function accepted_by()
{
return $this->morphTo(__FUNCTION__, 'accepted_by_type', 'accepted_by_id');
}
}
class User extends Authenticatable
{
public function created_orders()
{
return $this->morphMany(Order::class, 'created_by');
}
public function accepted_orders()
{
return $this->morphMany(Order::class, 'accepted_by');
}
public function created_returns()
{
return $this->morphMany(Return::class, 'created_by');
}
public function accepted_returns()
{
return $this->morphMany(Return::class, 'accepted_by');
}
}
class Company extends Model
{
public function created_orders()
{
return $this->morphMany(Order::class, 'created_by');
}
public function accepted_orders()
{
return $this->morphMany(Order::class, 'accepted_by');
}
public function created_returns()
{
return $this->morphMany(Return::class, 'created_by');
}
public function accepted_returns()
{
return $this->morphMany(Return::class, 'accepted_by');
}
}

Polymorphic BelongsTo relationship in Laravel

How could I set relationships to use just one table (model_types) in Laravel to store types for cars and bikes?
Car model
public function carTypes()
{
return $this->hasMany(CarType::class);
}
CarType model (inverse relationship):
public function car()
{
return $this->belongsTo(Car::class);
}
Bike model
public function bikeTypes()
{
return $this->hasMany(BikeType::class);
}
BikeType model (inverse relationship):
public function bike()
{
return $this->belongsTo(Bike::class);
}
There are 2 options I can think of to solve this problem, the first being a simple table using a type column and the other is using polymorphic relations which is a little overkill.
The first option is to have a type column on your model_types table which you could use to determine the type and adding constants in your ModelType class like this:
const TYPE_CAR = 1;
const TYPE_BIKE = 2;
Then you can easily access the data like so, so from the Car model it's
public function modelType()
{
return $this->belongsTo(ModelType::class)->where('type', ModelType::TYPE_CAR);
}
If you wanted to access it from the model_types table it would look like this:
public function cars()
{
return $this->hasMany(Car::class)
}
public function bikes()
{
return $this->hasMany(Bike::class)
}
You have it reversed.
A car can belong to one car type, but one car type can apply to many cars.
The same goes for bikes.
You don't need a polymorphic relationship.
Car model
public function carType()
{
return $this->belongsTo(ModelType::class);
}
Bike model
public function bikeType()
{
return $this->belongsTo(ModelType::class);
}
ModelType model
public function cars()
{
return $this->hasMany(Car::class);
}
public function bikes()
{
return $this->hasMany(Bike::class);
}
Not sure about inverse relationship, but in your Car model you should use
public function carTypes()
{
return $this->hasMany(ModelType::class, 'foreign_key', 'local_key');
}
Car Model:
public function carTypes() {
return $this->hasMany(ModelType::class);
}
Bike Model:
public function bikeTypes() {
return $this->hasMany(ModelType::class);
}
ModelType Model:
public function car() {
return $this->belongsTo(Car::class, 'modeltype_car_id');
}
public function bike() {
return $this->belongsTo(Bike::class, 'modeltype_bike_id');
}

Call to undefined relationship [person] on model [App\Note]

i have a notes, cards and person table wich notes table has card_id and person_id
now once i want load card data i alse want load person name's name but laravel give this error: Call to undefined relationship [person] on model [App\Note].
sorry my english is not good.
this my relationships:
notes:
public function card()
{
return $this->blongsTo(Card::class);
}
public function person()
{
return $this->blongsTo(Person::class);
}
cards:
public function notes()
{
return $this->hasMany(Note::class);
}
persons
public function notes()
{
return $this->hasMany(Note::class);
}
and this my action:
public function showCard(Card $card)
{
$card->load('notes.person');
return view('cards.card',compact('card'));
}
whats wrong?
You have a spelling mistake. Check the relationship, it says: ->blongsTo instead of belongsTo.
public function card()
{
return $this->belongsTo(Card::class);
}
public function person()
{
return $this->belongsTo(Person::class);
}

call the another function within a function

In laravel I want to call a function within function to make recursive.I caught the route error.how to call the function 'recursive in tableFetch'
class queryTest extends Controller
{
public function tableFetch() {
recursive();
}
function recursive(){
//condition
}
}
I want to do it for check the manager of the given person and then get the manager of the fetched value in query so need to do it recursive
A controller is not a good place for this. Instead, manage it in your Person Model(or whatever you have).
Everyone has a manager. So, your model has HasOne relation to itself.
Person Model:
public function manager()
{
return $this->hasOne(Person::class, 'manager_id');
}
Now if you need to check the manager of given person untill you meet a certain condition you can do it inside the model and get the result in the controller.
public function checkManager()
{
$manager = $this->manager
if (check manager)
return $manager;
//check for the last manager
return $this->manager ? $this->checkManager() : null;
}
Inside controller
function index()
{
$person = Person::find($id);
$manager = $person->checkManager();// this will do the recursive you need
}
Do something like this
class queryTest extends Controller
{
public function tableFetch() {
$this->recursive();
}
function recursive(){
//condition
}
}
you need to ask more precise details about your needs, because Laravel has some complications.
try doing this :
class queryTest extends Controller
{
public function tableFetch() {
$this->recursive();
}
public function recursive() {
//condition
}
}

Laravel 4 Relationship: messaging system

I followed the suggestions from user ehp in order to build a lightweight messaging-system:
https://stackoverflow.com/a/18717864/1084315
Users: id | username
Messages: id | from | content
user_messages: user_id | message_id
class User extends Eloquent {
public function messages()
{
return $this->belongsToMany('Message');
}
public function sent_messages()
{
return $this->hasMany('Messages', 'from');
}
}
class Message extends Eloquent {
public function from()
{
return $this->belongsTo('User', 'from');
}
public function to()
{
return $this->belongsToMany('User');
}
}
I create a message like this:
User::find(2)->messages()->create(array('text'=>'this is a message from admin to someone', 'from'=>'1');
Now I need to find / get every Message from a specific user to a specific user.
But in this example only the 'from' IDs are stored in the 'messages' table directly.
I can not even access the pivot of any Message by using
User::find(1)->sent_messages()->get();
What are best practices for collecting messages between one and another user?
Any help highly appreciated
First of all, I think there's a small typo:
public function sent_messages() {
return $this->hasMany('Messages', 'from');
}
This should probably be:
public function sent_messages() {
return $this->hasMany('Message', 'from');
}
Now, if you're looking to get all the messages sent from one user to another, what about this? Untested, but placing a constraint on the to relationship should do the trick.
$messages_from_A_to_B = Message::where('from', $UserA->id)->whereHas('to', function($q) use ($UserB) {
$q->where('user_id', $UserB->id);
})->get();
On a side note, I'm assuming that you specifically require that a user can send a message to more than one user? Else the following table structure seems like it would be easier:
users: id
messages: from | to
And then you just need:
class User extends Eloquent {
public function messages() {
return $this->hasMany('Message', 'to');
}
public function sent_messages() {
return $this->hasMany('Message', 'from');
}
}
class Message extends Eloquent {
public function from() {
return $this->belongsTo('User', 'from');
}
public function to() {
return $this->belongsTo('User', 'to');
}
}
$messages_from_A_to_B = Message::where('from', $UserA->id)->where('to', $UserB->id)->get();

Resources