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
Related
I have two models with relationship methods,
Product
public function facts()
{
return $this->hasMany('App\Fact');
}
Facts
public function products()
{
return $this->belongsTo('App\Product');
}
I'm trying to get access to relationship column name and loop through it
$product = Product::where('slug', 'some-slug')->with('facts')->get();
this works but how to select a column called 'name' and loop through it? I have tried
foreach($products as $product){
$sum = $facts->name;
}
dd{$sum}
Exception: Property [name] does not exist on this collection instance
You are trying to pull the name field from a collection of facts, which won't have a property for that whole collection called name. You can use two loops. Example at the simplest level:
foreach ($product as $products) {
foreach($products->facts as $fact){
$sum = $facts->name;
echo $sum;
}
}
Since it's a hasMany relationship, you can pluck name from the collection
foreach ($product as $products) {
$sum = implode('', $products->facts->pluck('name')->toArray());
dd($sum);
}
Not sure where you have this variable from but you are not using the iterator in your foreach loop:
foreach($products->facts as $fact){
$sum = $facts->name;
}
What is $facts? It sounds like it is a Collection. Also what is $products, you created $product. You want to be using $fact the current iterated Fact for this Product:
$product = Product::where(....)->('facts')->first();
foreach ($product->facts as $fact) {
...
$something = $fact->name;
...
}
I want to count each location in my Job table by using location_id in my job table with id in location table. below code, I can count result correctly but I don't know how to pass this variable to the view. Please help?
//my code
public function index(){
$location = Location::all();
$count_location = [];
foreach ($location as $locations){
$count_location = Job::where('location_id', $locations->id)->count();
}
}
Use withCount() and view() to pass location with counted jobs to the view:
public function index(){
return view('view.name', [
'locations' => Location::withCount('jobs')->get()
]);
}
In the view:
#foreach ($locations as $location)
{{ $location->name }} has {{ $location->jobs_count }} jobs
#endforeach
You can return the collection of locations to the view and then loop through each object in the collection like so:
return view('index', [
'locations'=> $locations,
]);
Then in your index.blade.php you can use something like a #foreach or #forelse loop
#foreach ($locations as $location)
{{ $location->id }}
#endfoeach
EDIT
From the looks of it you would be better off defining a relationship between locations and jobs (i.e. a "many to many" or "one to many" relationship). this would allow you to get the counts for jobs at given locations very easily like so:
$location->jobs->count()
Eloquent relationships are explained in the documentation here
https://laravel.com/docs/5.5/eloquent-relationships
It would be more efficient if construct your query to fetch the count of related models instead of looping through all the results.
Have a look at Counting Related Models in the documentations.
For example, to get the count of all jobs related to a location, you could do:
$locations = App\Location::withCount('jobs')->get();
foreach ($locations as $location) {
echo $location->jobs_count;
}
You need to adjust the code according to your models structure.
Do this
public function index(){
$locations = Location::all();
return view('index', compact('locations'));
}
In your Location model make a relationship by adding this
public function jobs(){
return $this->hasMany(Job::class);
}
In your index view do this
#foreach ($locations as $location)
{{$location->jobs->count}}
#endforeach
Please note that Job should be there in your your model
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
I'm having problem with this scope in my product Model
My scope look like this:
public function scopeLessNinetyDays( $query ){
$date = new \Carbon\Carbon;
$date->subWeek(12);
return $query->where('created_at', '<', $date->toDateTimeString())->get() ;
}
I tried to loop it in category and the result is at the bottom. I need to return true or false. If the product created_at is in 12 weeks already. This is weird because it returns collection. Instead of single product.
#foreach( $category->product->take(4) as $product )
{{ dd($product->lessNinetyDays()) }}
#endforeach
If I used this code it returns single product. See Image at the bottom.
#foreach( $category->product->take(4) as $product )
{{ dd($product) }}
#endforeach
I don't know how to achieved that goal because of the results.
You are wrongly using a Local Scope. Scopes are used when selecting rows from the database, only that match the defined scope.
What you are looking for, is something like a "fake attribute" (accessor), which is probably the most Eloquent way of achieving what you are wishing for.
First, define this accessor:
public function getIsLessNinetyDaysAttribute() {
$date = (new \Carbon\Carbon)->subWeek(12);
return $this->created_at->lt($date);
}
Now, you can access this property by using:
#foreach( $category->product->take(4) as $product )
{{ dd($product->is_less_ninety_days) }}
#endforeach
This should return either true or false.
Example for using a local Scope
After defining this scope:
public function scopeLessNinetyDays( $query ){
$date = new \Carbon\Carbon;
$date->subWeek(12);
return $query->where('created_at', '<', $date->toDateTimeString())->get();
}
Now, you can chain this scope to your select query:
#foreach( $category->product->lessNinetyDays()->get() as $product )
{{ dd($product) }}
#endforeach
In this foreach loop, the only rows returned are the rows that are matching the lessNinetyDays scope.
There a multiple ways to achieve your goal, but in such cases, I always prefer an accessor.
Scope's are for query selecting. See Local Scopes
If you just add the following to the model then it should return true or false.
public function lessNinetyDays()
{
$date = new \Carbon\Carbon;
$date->subWeek(12);
return $this->created_at > $date;
}
You're using the scope incorrectly.
It's not supposed to return anything - it's only supposed to modify the query, it shouldn't return anything, especially the results of the query. Therefore you should replace
return $query->where('created_at', '<', $date->toDateTimeString())->get() ;
with
$query->where('created_at', '<', $date->toDateTimeString());
Then, if you want to fetch products that were created within last 90 days, you'll need to do the following:
$products->lessNinetyDays()->get();
See more info here: https://laravel.com/docs/5.3/eloquent#local-scopes
Trying to get products AND variants for a particular supplier.
I can get the products easy enough, but can't figure out how to best get to the variants with matching product_id and send it to the view.
Variants.product_id matches with Product.ID
This works (getting products for the supplier)
public function suppliers($id) {
$supplier = Supplier::orderby('company_name', 'ASC')->find($id);
$products = Supplier::find($id)->products;
$data = [];
$data['supplier'] = $supplier;
$data['products'] = $products;
return view('admin.purchasing.supplier-details', $data);
}
I've tried this to get the variants also without luck.
Controller:
public function suppliers($id) {
$supplier = Supplier::orderby('company_name', 'ASC')->find($id);
$products = Supplier::find($id)->products;
$variants = array();
foreach ($products as $product) {
$product_id = $product->id;
$variants[] = Variant::find($product_id);
}
$data = [];
$data['supplier'] = $supplier;
$data['products'] = $products;
$data['variants'] = $variants;
return view('admin.purchasing.supplier-details', $data);
}
View:
#foreach($products as $product)
<tr>
<td>{{ $product['title'] }}</td>
#foreach($variants as $variant)
#if($variant->product_id == $product['id'])
<td>${{ $variant->price }}</td>
#else
<td>not set</td>
#endif
#endforeach
</tr>
#endforeach
Any tips much appreciated.
First of all , you should have relation set on your models to make this work
like this For exemple :
Supplier.php
public function products()
{
return $this->hasMany('App\Product');
}
Product.php
public function variants()
{
return $this->hasMany('App\Variant');
}
public function Supplier()
{
return $this->belongsToMany('App\Supplier'); //in case you have only one supplier for each product change this to belongsto
}
Variant.php
public function products()
{
return $this->belongsToMany('App\Product'); //not sure if this should be manytomany or one to many , it deppends on what you did
}
anyway now you can do this
Controller
public function suppliers($id) {
$Data = Supplier::where('id',$id)->orderby('company_name', 'ASC')->with('products.variants')->first(); //you will get the supplier with all products associated to him with variants foreach product
return view('admin.purchasing.supplier-details')->with('Data',$Data); // now you just loop the $supplierwithproducts->products to get results (dd the variable to check output)
}
View
{{ $Data->name }} // supplier name since Supplier model was the starting point
#foreach($Data->products as $product) //loop all products related to that supplier
{{ $product->name }} //shows product name (depends on you database columns
#foreach($product->variants as $variant) // loops all variants in the current product
{{ $variant->name }} // shows variants
#endforeach
#endforeach
If you copy and paste this code it might not work ,but this will give you an idea how you should handle relations in laravel (levrage eloquent relations)
Check this for more informations
Laravel Docs
Laracasts Defining Relationships With Eloquent
Laracasts Updating Records and Eager Loading