Laravel Through Relationship - laravel-5

Given below are the tables I have:
keywords
--------
id
keyword
Keyword table has many footprints
footprints
----------
id
keyword_id
footprint
Each serp is associated with a footprint
serps
-----
id
footprint_id
phrase
I need to get the keyword each serp is associated with. By reading about Laravel's Has One through relationship, I get the feeling that it can be done with has one trough relationship.
I want to get the keyword using:
$serp->keyword;
On Serp Model, I wrote the following code which is not working. I will highly appreciate your help to the write right relationship code.
class Serp extends Model {
//
public function keyword(){
return $this->hasOneThrough(
'\App\Keyword',
'App\Footprint') ;
}
}

In your case, you can use has one through to find Serp based on keyword
class Keyword extends Model {
public function serp(){
return $this->hasOneThrough(
'\App\Serp',
'App\Footprint') ;
}
}
But if you want to use $serp->keyword(), you should use inverse relationship of hasOneThrough.
Check this trait out, it might help you

Related

How i can prevent duplicate name on the table using eloquent query in laravel

I am currently working on a desktop management application with laravel 5.6. According to the management rule a patient can have one or more consultations according to given dates. When I display the list of consultations, I have the same name that repeats, the name that repeats corresponds to the patient who had several consultations, my question of how to avoid this. What I want is the name, and all the dates for these consultations.
class Consultation extends Model
{
public function patient()
{
return $this->belongsTo('App\Models\Patient');
}
}
class Patient extends Model
{
public function consultations()
{
return $this->hasMany('App\Models\Consultation');
}
}
Here is the query :
$consultations = Consultation::all();
The simplest (but not the prettiest) way to do this is to simply find all patients with consultations. Put those patients in an array, and then in your blade you would loop through these patients and show the consultations individually.
Controller Code:
$active_patients = [];
foreach(Patient::all() as $patient) {
if($patient->consultations->count()>0)
array_push($active_patients,$patient);
}
Pass $active_patients to your view, then loop over it as shown below. Obviously, I don't know all of the attribute names for your Patient or Consultation models and you will need to fix html markup as required, but you can get the picture:
#foreach($active_patients as $patient)
<p>{{$patient->name}}:</p>
#foreach($patient->consultations as $consultation)
<p>{{$consultation->date}}</p>
#endforeach
#endforeach
Disclaimer: This is not the most robust way to do this. It's simply the most straightforward approach. The best way to do this is to use scoped queries combined with appended attributes. For instance, you would make a scope on the Patients model for all patients that have a consultation by using the 'whereHas' eloquent query method to find patients that have consultations scheduled. Then you could just reference them directly as ActivePatient rather than having to build an array each time you reference them. You could also append an attribute to the Consultations model that does the same thing and grabs each consultation for the specific users and makes a nested model collection, but that's much more involved. I'd be happy to share that method with you if you want, but the above code would at least provide you with a working method to achieve what you requested.

Selecting specific column in ORM relationship Laravel 5.5

I have an order table with a primary key id and another table trips. I trip can have many orders. I have defined the relationship in this way
public function orders_currency() {
return $this->hasMany('App\Order', 'trip_id', 'id')->select('id', 'converted_currency_code');
}
Although I know that, I have to select id of the order table in order to get the result, that's why I am mentioning to select the id of the order table.
Despite this, I am getting the orders_currency index empty. Which angle am I missing in this case?
Any clue will be appreciated.
Did you set up the model correctly?
You'd do something like this in your model script I suppose
class Trips extends Model
{
public function orders() {
return $this->hasMany('Order');
}
I got the solution by doing this way
public function orders_currency() {
return $this->hasOne('App\Order', 'trip_id', 'id')
->select('trip_id','converted_currency_code');
}
I had to select referencing key in this case.

Laravel 5.5 retrieving null by nested relation

I have 3 databases:
Routes:
id
name
Rates:
Id
Route_id
Car_id
Cars:
id
name
My model for routes
public function rates()
{
return $this->hasMany('App\Rate', 'route_id');
}
My model for rates
public function car() {
return $this->belongsTo('App\Car','car_id');
}
Now I need to access the car relation, but when I do
return $this->route->with('from','to','rates.car')->paginate(74);
I get null for the car relation
{"id":1,"from_id":1,"to_id":2,"distance":400,"created_at":null,"updated_at":null,"from":{"id":1,"name":"\u0410\u043a\u043a\u043e","created_at":null,"updated_at":null,"lat":32.93310000000000314912540488876402378082275390625,"long":35.0827000000000026602720026858150959014892578125},"to":{"id":2,"name":"\u0410\u0440\u0430\u0434","created_at":null,"updated_at":null,"lat":31.261399999999998300381776061840355396270751953125,"long":35.21490000000000009094947017729282379150390625},"rates":[{"id":1,"route_id":1,"car_id":1,"rate":1123,"night_rate":1391,"car":null},{"id":5551,"route_id":1,"car_id":2,"rate":1123,"night_rate":1391,"car":null},{"id":11101,"route_id":1,"car_id":3,"rate":1123,"night_rate":1391,"car":null},{"id":16651,"route_id":1,"car_id":4,"rate":1123,"night_rate":1391,"car":null},{"id":22201,"route_id":1,"car_id":5,"rate":1123,"night_rate":1391,"car":null},{"id":27751,"route_id":1,"car_id":6,"rate":1123,"night_rate":1391,"car":null},{"id":33301,"route_id":1,"car_id":7,"rate":1123,"night_rate":1391,"car":null},{"id":38851,"route_id":1,"car_id":8,"rate":1123,"night_rate":1391,"car":null}]},
From my understanding you are trying to access a Car model through a Route model.
A couple of things I noticed that should help you find a solution.
First off I think the inverse relation you are supposed to use the belongToMany() function instead.
public function car() {
return $this->belongsToMany('App\Car','Rates'); // Perhaps call the table something like routes_cars to more clearly define it's a pivot table
}
Next I see you are trying to use model functions within the context of $this(). I assume you are doing this in your model? That logic should be in a controller, that might cause some undesired results but I'm not entirely sure. Also it looks like your parameters are incorrect when using with(). You use the function name that you defined in belongsToMany()
App/Route::with('car')->paginate(74);
With the correct relationships setup you rarely need to worry about the pivot table. If you are going to add extra information in the pivot table there are laravel functions to help you do that in the documentation.

what to do with an inverted polymorphic relation?

I have been trying to get my head around these polymorphic relationships all day. I might be over complicating/thinking it but. Can Laravel handle inverse polymorphic relationships? I have a registration flow that can have two types of field Models- normal field and customField.
When I loop through all the fields available it could pull the attributes from either NormalField or CustomField.
<?php
foreach($registrationFlow->fields->get() as $field)
{
echo $field->name; // could be custom field or could be normal field
}
?>
My difficulty is that, the example given in the docs works if you want to assign a photo to either staff or orders, but i want to assign either a customField or a normalField to a registrationFlow
*Edit
If you follow the example for the polymorphic many to many relationship, The tag class contains posts and videos- while i would want just a simple fields() method that relates to customField or normalField dependent on the type
First of all, you should take a look at the updated docs for Laravel 5.1: https://laravel.com/docs/5.1/eloquent-relationships#polymorphic-relations.
I think the difficulty with the example they provide is that the relationship between Photo and Staff/Product are "has-a" relationships, whereas you are trying to model an "is-a" relationship. However, you can model "is-a" essentially the same way. Take a look at this article: http://richardbagshaw.co.uk/laravel-user-types-and-polymorphic-relationships/.
Basically, the strategy is to define a generic model (and a generic table), perhaps in your case Field, that relates to your RegistrationFlow. You then have two subtype models, NormalField and CustomField, that have one-to-one relationships with Field. (there's your "is-a"). Thus, RegistrationFlow is indirectly related to your field subtypes.
Polymorphism comes in when you want to access the specific subtypes:
class Field extends Model {
public function fieldable()
{
return $this->morphTo();
}
}
Your base field table should have fieldable_id and fieldable_type columns defined (see the Eloquent docs).
You can then add methods to NormalField and CustomField that let you access the base model (your "inverse relationship"):
class NormalField {
public function field()
{
return $this->morphOne('Field', 'fieldable');
}
}
class CustomField {
public function field()
{
return $this->morphOne('Field', 'fieldable');
}
}
Usage:
$field = Field::find(1);
// Gets the specific subtype
$fieldable = $field->fieldable;

Can I require a one-to-one relationship in Laravel Eloquent?

I've got a Product class and a Detail class. I wanted to separate the big, long description from the basic data (sku, price) just for speed. However there will always be a big long description. So each item in the store will always have two records.
Is there a way to force or require both records? Is there a way to require that the 1-to-1 relationship exists - so that this would always work...
$P = new App\Product(['sku'=>'123','price'=>69]);
$P->Detail->html = '<p>Lorem ipsum.</p>';
$P->push();
My hasOne/belongsTo stuff is all fine. But if the details record does not exist yet ~ I get errors. I'm wondering if Detail can auto-magically exist.
There's not a lot you can do to 'force' the paired record to exist, however you could use a getter to make the retrieval of the description a little safer. Something like:
class Product extends Model {
public function detail()
{
return $this->hasOne('App\Detail');
}
public function getDetailHtml()
{
if ($this->detail()->count()) {
return $this->detail->html;
}
}
}

Resources