laravel many to many retrieve data - laravel

I have many to many relationship and here's what I am doing:
In url I am passing businesses id which is in Business table:
#foreach ($business as $businesses)
<a target="_blank" href="{{ url('business/' . $businesses->id) }}"> {{($businesses->name) }}
</a> #endforeach
Then this function is ran:
public function displayBusiness($id) {
$business = Business::find($id)->addresses;
//return $business;
//$address = Address::find($id);
$session = session()->put('key', $id);
$gallery = Gallery::where('business_id', $id)->get();
$location = Location::where('business_id', $id)->get();
$review = Review::where('business_id', $id)->get();
return view('displayBusiness', compact('business', 'address', 'gallery', 'location', 'review'));
}
But the problem is the lines that are commented out, bring back results that match business id which is not always the case because sometimes business id = 1 and address id = 4 but this code will bring back address id = 1
So what I want to do is to look at my junction table that has business_id and address_id and use $id to find business_id as well as address_id that matches that id.
return business gives me []
So what I want is something like this:
Let's assume $id = 1
Go into business_address and find business_id that matches 1;
Also find address_id that matches business_id found,
Bring back matching id to business table and compact the results that match id
same for address table
my models:
Address.php
public function businesses() {
return $this->belongsToMany(Business::class, 'business_address', 'business_id', 'address_id');
}
Business.php
public function addresses() {
return $this->belongsToMany(Address::class, 'business_address', 'address_id', 'business_id');
}

I'm guessing each business has many addresses.
1. this would return the business with id of $id
$business = Business::find($id);
2. This would return All addresses matching that business
$address = $business->addresses;
Please note that the $address would return a collection not a single object
Let me know if this helps

Related

Laravel fetch intermediate table data with many to many relationship

I have 3 tables
user, specialities & results
results contain specialitie_id, user_id
I have create many-to-many relationship
Here's the relationship in user model
public function specialities()
{
return $this->belongsToMany(Speciality::class, 'results', 'user_id', 'specialitie_id')->withPivot('result', 'color');
}
I want to fetch data from the result table based on specialitie_id
If my url is
abc.com/result/5
I have attached table structure as well,
it should show me result related to specialitie_id 5
I tried this but it doesn't work
$result = User::with('specialities')->where('id', 5)->get();
Any help would be appreciated.
Your current query:
$result = User::with('specialities')->where('id', 5)->get();
Is saying, give me all results where the USER_ID = 5 WITH all the specialities related to it.
You are very close but did it backwards:
//Give me all results where the SPECIALITY_ID = 5
//WITH all the users related to it
$result = Speciality::with('users')->where('id', 5)->get();
Please note that the above is an array
Example of a Controller Function:
public function results($id){
$results = Speciality::with('users')->where('id', $id)->get();
return view('user_specialities', compact('results'));
}
Example view user_specialities:
#foreach($results as $result)
<p>Result: {{$result->result}}</p>
<p>Formulary: {{$result->formulary}}</p>
<p>Color: {{$result->color}}</p>
<p>User ID: {{$result->user->id}}</p>
<p>User Name: {{$result->user->name}}</p>
#endforeach
Speciality Model:
public function users()
{
return $this->belongsToMany(User::class, 'results', 'specialitie_id', 'user_id')->withPivot('result', 'color');
}
User Model:
public function specialities()
{
return $this->belongsToMany(Speciality::class, 'results', 'user_id', 'specialitie_id')->withPivot('result', 'color');
}

retrieving related field in controller index function gives error but ok in show function

I define the relation in Company table (where I added the plural):
protected $table = 'companies';
public function country() {
return $this->belongsTo(Country::class, "country_id")->withDefault(['country' => 'unknown']);
}
I also did the same in the Country model.
When I use the following code in the controller show function it works:
public function show (Company $company) {
$company->country = $company->country()->pluck('country');
But if I use the same code in the index function in a loop, I get an error "Call to undefined method stdClass::country()":
public function index (Company $company) {
if (request('tag')) {
$companies = Tag::where('name',request('tag'))->firstOrFail()->companies;
$companies->page_title = "Businesses matching tag '".request('tag')."'";
} else {
$companies = DB::table('companies')
->where([['is_active', '=', '1']])
->orderBy('company')
->get();
}
foreach($companies as $key => $thisCompany) {
...
$thisCompany->country = $company->country()->pluck('country');
}
I guess it is due to the fact that $company is created in the loop and not passed through the function like in show(Company $company)... but I could not find how to solve this issue... so help will be appreciated.
I have added the model in the argument of the function and change the name of the $company variable in the loop by $thisCompany to avoid confusion with the $company model.
No error but the field $country->country does not contain the name of the country but "Illuminate\Support\Collection {#443 …1}"
Why is it so complicated? Please help...
Paul, sorry, I think I didn't explain myself well in the comments.
What I meant by "What about if you change DB::table('companies') by Company?", is to stop using DB Query Builder to use the Eloquent Company model.
Specifically in this segment of code:
$companies = DB::table('companies')
->where([['is_active', '=', '1']])
->orderBy('company')
->get();
So, it could be:
$companies = Company::where([['is_active', '=', '1']])
->orderBy('company')
->get();
The explanation is that in the first way (with DB Query Builder), the query will return a collection of generic objects (the PHP stdClass object) that do not know anything about the Company and its relationships.
On the other hand, if you use the Eloquent model Company, it will return a collection of Company objects, which do know about relationships, and specifically the relationship that you have defined as country.
Then, when you loop over the collection, you will be able to access the country relation of each Company object:
foreach($companies as $key => $company) {
//...
$company->country = $company->country()->pluck('country');
}
Finally, your code could looks like:
public function index () {
if (request('tag')) {
$companies = Tag::where('name',request('tag'))->firstOrFail()->companies;
$companies->page_title = "Businesses matching tag '".request('tag')."'";
} else {
$companies = Company::where([['is_active', '=', '1']])
->orderBy('company')
->get();
}
foreach($companies as $key => $company) {
//...
$company->country = $company->country()->pluck('country');
}
//...
}

Replicate Laravel collection - Laravel 5.3

Im replicating a trips table. On the trips form, there is a dropdown to select species. A user can select many species to. Im having trouble replicating this species table beacuse its in its own table, and its a collection. So using "replicate" wont work.
This is how Im replicating the trips table right now:
public function replicateTrip (Request $request, $slug, $id) {
$listing = $request->user()->listings()->where('slug', $slug)->first();
$trip = $listing->trips()->where('id', $id)->first();
$replicateTrip = Trip::find($trip->id);
// This is how im getting the species from the species table
$replicateSpecies = DB::table('species_trip')->where('trip_id', $id)->get();
$newTask = $replicateTrip->replicate();
$newTask->save();
return redirect()->back();
}
If I DD the $replicateSpecies variable when cloning my current trip, I get:
I need to replicate the species array from my orginal trip into the species table, and I cant just use "replicate", because its a collection.
So my question is how would I replicate this collection? Or if there is another method of doing this?
You can try it as:
public function replicateTrip (Request $request, $slug, $id) {
$listing = $request->user()->listings()->where('slug', $slug)->first();
$trip = $listing->trips()->where('id', $id)->first();
$replicateTrip = Trip::find($trip->id);
// This is how im getting the species from the species table
$replicateSpecies = DB::table('species_trip')->where('trip_id', $id)->get();
$newTask = $replicateTrip->replicate();
$newTask->save();
$replicateSpecies->each(function ($item, $key) use($newTask) {
$copy = $item->replicate();
$copy->trip_id = $newTask->id;
$copy->save();
})
return redirect()->back();
}

How get rows from closest table using one to one?

I have two tables:
Hotels | Countries
country id name
I need to get all notes from Hotels , and get Hotels.country will be name of country: Countries.name
There is function in Hotel model:
public function country()
{
return $this->hasOne('App\Country', 'country', 'id');
}
In controller I try to get all hotels with related countries:
$hotels = Hotel::all();
After I try to get country name for each row from $hotels:
foreach($hotels as $item){
echo $item->country["name"]; // It does not work
}
It should be
public function country()
{
return $this->belongsTo('App\Country', 'country', 'id');
}
After that,
#foreach ($hotels as $hotel) {{ $hotel->country->name }}
should work.
You will need to use eager loading.
$hotels = Hotel::with('country')->get();
Check out the documentation here.
In order to access the country name, it's a normal object:
$hotel->country->first()->name
If you want to have a direct function, in your Hotel Model
Hotel.php
public function countryName()
{
return $this->country->first()->name
}

check if value exists in array

I have 2 queries and I want to check if values of one queries exists in array of other query. I have "maintenance" which has "process_id" and "processes" (array of process id's). I want to check for each process_id if exists in processes. in my controller:
$processes = DB::select('select id from processes');
$maintenance = DB::select('select process_id from maintenances where car_id ="' . $id . '" group by process_id');
$result = array();
foreach ($processes as $key => $value) {
$result[] = $value->id;
}
In my Helper.php
public static function array_value($value, $array) {
$results = 0;
$str = "$value";
if (in_array($str, $array)) {
$results += 5;
} else {
$results += 1;
}
return $results;
}
In my view
#foreach ($maintenance as $m)
<tr> #if (Helpers\Helper::array_value($m->process_id, $processes)== 5)
<td> {{ $m->process }} </td>
#elseif (Helpers\Helper::array_value($m->process_id, $processes)== 1)
<td>Missing</td>
#endif
</tr>
#endforeach
And it displays only values in the first if. It doesn't displays Missing when process_id isn't found in array processes
If you're using laravel have you considered setting up a relationship to make this task simpler?
I assume process and maintenance will have a one to many relationship?
You could set up a many to many relationship:
in your process model:
public function maintenance() {
return $this->belongsTo('Maintenance')
}
(where Maintenance is the name of your model class. The function name can be anything)
In your maintenance model:
public function process() {
return $this->hasMany('Process')
}
Then your revised model retrieval is:
$maintenance = Maintenance::find($id);
UPDATED:
$maintenance = Maintenance::where('car_id', '=', $id)->first();
$maintenance->load('process');
(you could chain these)
Then in your view:
#if($maintenance->process()->first())
{{$maintenance->process()->name}} //or whatever positive output
#else
"NO process found" //or your negative output
#endif
The relationship does the hard work for you - you also then have the properties of the related mode available such as name etc which may be more user friendly.
the first() method retrieves the first related model. if this is null (ie not found) then the negative response works. YOu could also use count() which may be better then use:
#if($maintence->process()->count() > 0)
but all depends what you want to do.
YOu can also explore the get() method which will return a collection, useful if you expand your relationship to a many to many eg each maintenance may have many processes/
Hope this helps

Resources