laravel eloquent - match data stored within array - php

I have a multiselect form to store multiple client_id in contact table:
{!! Form::select('client_id[]', $clients, null, ['multiple'=>true]) !!}
When I show an individual client, I wish to show the related contacts.
My client Model has as a 1:many relationship defined as:
public function contact()
{
return $this->hasMany('App\Models\contact');
}
usually, for non array items, I would use:
$contacts = $client->contact()->get();
to fetch related contacts, but as the client_id is stored as an array in my contact table, how to I fetch this data?

I really think you just want this:
$contacts = $client->contact()->lists('id', 'name')->toArray();
Note that you didn't specify your version of Laravel, but in 5.1+ lists returns a Illuminate\Support\Collection instance, but in previous versions it returns an Array.
Sidenote
Your hasMany relationship should be defined as plural and not singular:
public function contacts()
This is by no means a requisite, but it better defines your relationship type.

Related

Laravel 5.4 - how to find specific record in relation

I have some eloquent models named Client and Company. And my Client may belong to multiple Company:
public function companies()
{
return $this->belongsToMany(Company::class);
}
I'd like to check if provided Client belongs to given Company. This is what I ended up with:
$client->companies
->filter(
function ($value, $key) use ($company) {
return $company->getKey() === $value->getKey();
}
)
->count() > 0;
Is there any shorter way?
Using models and the relationship collection:
$client->companies->contains($company);
Using relationship query to check existence:
$client->companies()->where('company_id', $company->id)->exists();
// even shorter, and don't need to know about the key yourself
$client->companies()->whereKey($company)->exists();
Going form the other direction:
$company->clients->contains($client); // if setup
$company->clients()->where(....)->exists();
You can always use your relationship method to query the relation:
$client->companies()->where('company_id', $company->id)->exists();
This uses the query builder to actually query the relation at the database level, unlike when you treat companies as a property which gets a collection of all of the related rows from the database.
Try
$myArray = $client->companies->comp_id;
where comp_id can be any column name. This should return an array. Then check if the array is empty by doing:
if (empty($myArray))

Laravel/Eloquent Relationship Inconsistent

I'm trying to get information associated with an application in my database.
Each application has 1 applicant.
Each application has 1 puppy.
I'm returning a view with an eloquent query like this:
$active_applications = Application::with('applicant', 'puppy')->where('kennel_id', '=', $user_kennel->id)->get();
And I have some relationships defined in my application model like so:
public function puppy(){
return $this->belongsTo('App\Puppy');
}
public function applicant(){
return $this->belongsTo('App\User');
}
When the view loads, I'm able to get the information associated with 'puppy'. It retrieves properly. The applicant, however stays null.
I have, in my applications table, a column named "user_id", which I was hoping it would use value in that column to search the users table 'id', and retrieve information on the user. It stays null, however. The following is a dd() of the variable in question:
Am I missing something obvious? Why would it retrieve one and not the other?
EDIT: the puppy table
Your relation is wrong -
public function applicant(){
return $this->belongsTo('App\User');
}
When you don't pass the foreign key as a parameter, laravel looks for the method name + '_id'. Therefore in your case laravel is looking for the column applicant_id in your application table.
So, to get results there are two ways -
1) You need to either change your method name -
public function user(){
return $this->belongsTo('App\User');
}
**2) Pass foreign key as the second parameter - **
public function applicant(){
return $this->belongsTo('App\User', 'user_id');
}
Laravel 5.6 doc - belongsTo
If its a One to Many(Inverse) Relation -
Eloquent determines the default foreign key name by examining the name
of the relationship method and suffixing the method name with a _
followed by the name of the primary key column.
If its a One to One Relation -
Eloquent determines the default foreign key name by examining the name
of the relationship method and suffixing the method name with _id.
Review Laravel doc for more details
Try the following line instead:
$active_applications = Application::with(['applicant', 'puppy'])->where('kennel_id', '=', $user_kennel->id)->get();
As far as I know, multiple "with" should be passed as array.
Adjust the relationship as well
public function applicant(){
return $this->belongsTo('App\User', 'user_id');
}

Eloquent: Has Many Through Relationships

I am trying to figure out a relationship but I can't seem to solve the issue.
So what my script does first is checking if there is a valid session where status = 0.
Then I want to check if there is a valid trial where status = 0 ->first() associated with that session. And if so, I want to grab all the relevant data related by trial_id.
I understand what logic is required. However, I am wondering if there is a method to do this with as little commands as possible using Eloquent relationships.
Specifically, once i have the $session object. How can I filter the trials, in order to get the appropriate stimuli_tracker data?
The important components to the relationships for the table is as follows:
Sessions
id (has one to many relationship to trials(sessions_id)
user_id (foreign key)
status
Trials
id (one to many relationship with stimuli_tracker)
sessions_id (foreign key)
status
Stimuli_Tracker
trials_id (foreign key)
stimulus
stimulus_type
Sessions Model
class Sessions extends Model
{
protected $table = 'sessions';
public function stimuliTracker()
{
return $this->hasManyThrough('App\StimuliTracker', 'App\Trials', 'sessions_id','trials_id');
}
}
Trials Model:
class Trials extends Model
{
public function stimuli()
{
return $this->hasMany(App\StimuliTracker);
}
}
EDIT
I have tried in artisan tinker to
$object = \App\Session::where(arg);
then I tried to
$object->stimulus
but didn't work. I tried a few other fields but I only received null. Maybe I'm not getting how to grab the content properly
$object->stimulus is an undefined attribute based on what you've shown in your code.
To access the stimulus information for your session, you have to use the name of the relationship, which in this case is:
$object->stimuliTracker
The thing is that this will return an Eloquent Collection because it is a hasManyThrough relationship (which is a hasMany of a hasMany).
I'm assuming that the 'stimulus' attribute belongs to the StimuliTracker class. If this is the case, then you will need to loop through your StimuliTracker Collection to extract it:
foreach ( $object->stimuliTracker as $record )
{
$stimulus = $record->stimulus;
// do something with $stimulus
}
EDIT (Added):
If you are just looking for an array of the values in the 'stimulus' attribute, you can get that with the lists() method:
$stimulus_values = $object->stimuliTracker->lists('stimulus');

Laravel eager loading, loaded table fields

how can I choose which fields I want to get from the with ORM eloquent. For example
$tourTeams = Tournament::with('teams')->where('id', $tourId)->first();
From the teams relation I want only to get the name (without the id and timestamps).
I didn't it in the documentation. For the Tournament eloquent I can do it via the get function while passing it an array of fields names, like this: get(array('name', 'id')). But how do I do this on the Team eloquent?
Note: here is how Team related to Tournament, this code taken from the Tournament eloquent file:
public function teams()
{
return $this->belongsToMany('Team', 'Tournament_Team');
}
You can get specific columns from the relation like this:
$tourTeams = Tournament::with(['teams'=>function($q){
$q->select('id','name');
}])->where('id', $tourId)->first();

Laravel belongsToMany to return specific columns only

So I have a many to many relationship between Users and Photos via the pivot table user_photo. I use belongsToMany('Photo') in my User model. However the trouble here is that I have a dozen columns in my Photo table most I don't need (especially during a json response). So an example would be:
//Grab user #987's photos:
User::with('photos')->find(987);
//json output:
{
id: 987,
name: "John Appleseed",
photos: {
id: 5435433,
date: ...,
name: 'feelsgoodman.jpg',
....// other columns that I don't need
}
}
Is it possible to modify this method such that Photos model will only return the accepted columns (say specified by an array ['name', 'date'])?
User.php
public function photos()
{
return $this->belongsToMany('Photo');
}
Note: I only want to select specific columns when doing a User->belongsToMany->Photo only. When doing something like Photo::all(), yes I would want all the columns as normal.
EDIT: I've tried Get specific columns using "with()" function in Laravel Eloquent but the columns are still being selected. Also https://github.com/laravel/laravel/issues/2306
You can use belongsToMany with select operation using laravel relationship.
public function photos()
{
return $this->belongsToMany('Photo')->select(array('name', 'date'));
}
Im assuming you have a column named user_id. Then you should be able to do the following:
public function photos()
{
return $this->belongsToMany('Photo')->select(['id', 'user_id', 'date', 'name']);
}
You have to select, the foreign key, else it will have no way of joining it.
Specifying the exact columns you want for the Photos relationship will likely end up biting you in the butt in the future, should your application's needs ever change. A better solution would be to only specify the data you want to return in that particular instance, i.e. the specific JSON response you're delivering.
Option 1: extend/overwrite the toArray() Eloquent function (which is called by toJson()) and change the information returned by it. This will affect every call to these methods, though, so it may end up giving you the same problems as doing select() in the original query.
Option 2: Create a specific method for your JSON response and call it instead of the general toJson(). That method could then do any data building / array modifications necessary to achieve the specific output you need.
Option 3: If you're working with an API or ajax calls in general that need a specific format, consider using a library such as League/Fractal, which is built for just such an occasion. (Phil is also working on a book on building APIs, and it doesn't suck.)

Categories