I am found this type of result where User_id and full_name print everytime. full_name print one time and related multiple data shows in a single array - laravel

$nearProviderdata = DB::table('users','category')
->leftJoin('service_provider_rating', 'users.id', '=', 'service_provider_rating.rating_receiver_user_id')
->leftJoin('service_provider_category', 'users.id', '=', 'service_provider_category.user_id')
->leftJoin('category', 'category.id', '=', 'service_provider_category.category_id')
->select('users.id as user_id','users.full_name','category.id as category_id','category.title')
->distinct()->get()->groupBy('user_id');
I am receiving the below response from the above code.
[0] => stdClass Object
(
[user_id] => 11
[full_name] => Jimmi Patel
[category_id] => 1
[title] => Painter
)
[1] => stdClass Object
(
[user_id] => 11
[full_name] => Jimmi Patel
[category_id] => 2
[title] => Home Cleaner
)
[2] => stdClass Object
(
[user_id] => 11
[full_name] => Jimmi Patel
[category_id] => 3
[title] => Electrician
)
I want the result something like as below
[0] => stdClass Object
(
[user_id] => 11
[full_name] => Jimmi Patel
['category'] => [ category_id => 1,title => Painter, category_id => 2, title => Home Cleaner, category_id => 3, title => Electrician]
)
It's laravel version 5.7. I have tried group by also to get the result but it is showing only 1 row and 1 category data. So i am using the subquery to get the data. Please let me know if i am doing something wrong in it.

I think you don't need to join that much with raw query
better use models for this purpose
Simplified example:
$nearProviderdata = User::with(
'categories',
'serviceProviderRating',
'serviceProviderCategory'
)->get();
You can also add select in subquery and map response

Related

How to use eloquent ->with method on collection

You may find the question stupid. I may not be doing the research well so I thought to ask it here. I would like to know how to use ->with on collection or what is its equivalent. Here is the code:
$theLastCommentOfThisPost = $post->comments->with('user')->sortByDesc('id')->first();
I would like to get something like this:
Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[id] => 19
[commentable_type] => App\Post
[commentable_id] => 123
[comment] => totoototo
[is_approved] => 1
[user_id] => 1
[created_at] => 2019-04-01
[updated_at] => 2020-02-04
[user] => App\User Object
(
[id] => 1
[name] => App\Post
[email] => totos#toto.fr
)
)
)
thanks
If you want to "load" relationships for a Collection of Models you would use the load method.
$post->comments->load('user')->.....
Though to not have to load all the comments to only get one you can do this with a query:
$post->comments()->with('user')->latest()->first();
Not really sure overall the data you need besides this one object.
Laravel 5.8 Docs - Eloquent Collections - Available Methods - load

how to sort data in Laravel Eloquent query, based on a specific field

I have this Eloquent query:
$events = Product::forCard()->latest()->take(setting('storefront_recent_products_section_total_products', 10))->get();
I want to sort this record in ascending order by start_event. I tried to do this, but I have some issues because data come from multiple tables.
Array
(
[0] => Array
(
[price] => Modules\Support\Money Object
(
[amount:Modules\Support\Money:private] =>
[currency:Modules\Support\Money:private] => USD
)
[special_price] =>
[selling_price] => Modules\Support\Money Object
(
[amount:Modules\Support\Money:private] =>
[currency:Modules\Support\Money:private] => USD
)
[special_price_start] =>
[special_price_end] =>
[options_count] => 0
[id] => 40
[slug] => -YvHm5m1m
[in_stock] => 1
[new_from] =>
[new_to] =>
[name] => Race4
[description] =>
[organizer] =>
[short_description] =>
[address] =>
[city] => vehari
[state] => pakistan
[zip_code] =>
[lat] =>
[lng] =>
[start_event] => 2020-01-13 00:00:00
[end_event] =>
[translations] => Array
(
[0] => Array
(
[id] => 33
[product_id] => 40
[locale] => en
[name] => Race4
[city] => vehari
[state] => pakistan
[start_event] => 2020-01-13 00:00:00
)
)
[files] => Array
(
)
)
You should be able to order is ascending something similiar to this:
$events = Product::forCard()->latest()
->take(setting('storefront_recent_products_section_total_products', 10))
->orderBy('start_event', 'asc');
Basically you can tell using the method orderBy() which column shall be used to order and the type of ordering, in this case ascending.
Laravel makes it easy and absolutely no brainer to sort data.
$events = Product::forCard()->latest()->take(setting('storefront_recent_products_section_total_products', 10))
->orderBy('start_event')->get();
Where start_event is the column you want t use in sorting.
There is a better approach, as the above code will automatically sort the returned data in an ascending order, but you can explicitly tell it what to do.
Just modify the last part of the code with:
orderBy('start_event', 'ASC')->get(); /** If you want Ascending OR; **/
orderBy('start_event', 'DESC')->get(); /** If you want Descending. **/

Laravel: nested "with()" function

I want to retrieve data from three tables: courses, competencies and competency_standards. The following query almost works, but it does not bring back the associated competency_standards table data.
$coursesAndComps = Course::with(
array('competencies' => function($query)
{
Competency::with('competency_standards');
})
)->get()->toArray();
Where the competencies table is linked to the courses table (competencies.course_id = course.id) and the competency_standards table links to the competencies table (competency_standards.competencey_id = competency.id).
The array returned looks like this:
Array
(
[0] => Array
(
[id] => 1
[name] => the first course
[competencies] => Array
(
[0] => Array
(
[id] => 9
[course_id] => 1
[name] => first course comp 1
)
[1] => Array
(
[id] => 10
[course_id] => 1
[name] => first course comp 2
)
)
)
)
but within the competencies array, I was hoping to find another array called competency_standards like this:
...
[0] => Array
(
[id] => 9
[course_id] => 1
[name] => first course comp 1
[competency_standards] => Array
(
[0] => Array
(
[id] => 22
[competency_id] => 9
[name] => standard foo
)
[1] => Array
(
[id] => 23
[competency_id] => 9
[name] => standard bar
)
)
)
...
Is this possible? Am I going about this the wrong way?
It should be possible to use:
$coursesAndComps = Course::with('competencies', 'competencies.standards')
->get()->toArray();
but of course you need to have defined standards relationship in Competency model to link Competency with Standard

Laravel eager loading returns all results when querying realtionship

I want to get products with a seri name contains a certain word. However it returns all products. Matching serie name condition appears to be array under each related product; for the rest of products it is just a blank "serie" key.
$products=Product::with(array(
'serie'=>function($query)
{
$query->where('name','like','%unky%');
}))
->get()->toArray();
and array returned is like
[0] => Array
(
[id] => 1
[updated_at] => 2014-02-14 22:26:04
[created_at] => 0000-00-00 00:00:00
[brand_id] => 1
[cat_id] => 1
[serie_id] => 1
[devices_ids] => 1
[color_code] => #BEB991
[barcode] => 8699131462430
[title] => Funky Charlie iPhone 5/5S Kılıfı
[desc] => Sert 6 gr
[price] => 29.90
[serie] => Array
(
[id] => 1
[updated_at] => 2014-02-14 22:18:31
[created_at] => 0000-00-00 00:00:00
[name] => Funky
)
)
[1] => Array
(........
[5] => Array
(
[id] => 6
[updated_at] => 2014-02-14 22:46:10
[created_at] => 0000-00-00 00:00:00
[brand_id] => 1
[cat_id] => 1
[serie_id] => 2
[devices_ids] => 1
[color_code] => red
[barcode] => 8699131462546
[title] => Bonjour Kırmızı iPhone 5/5S Kılıfı
[desc] => Sert 6 gr
[price] => 24.90
[serie] =>
As you can see serie key is empty.
What i want is only to bring products with matching serie name and does not bring products like with id"5".
What i am doing wrong?
Thanks
I think that instead of using Model::with(), you want to instead filter the Model, based on the related model, so you should use Model::whereHas()
$products = Product::whereHas('serie', function($query)
{
$query->where('name','like','%unky%');
})->get()->toArray();
Eager loading constraints do not put a constraint on the results of the model - it constraints the related model. In your case, you get all Products. But if you try to access the Series of a Product, you will only get those Series that are true to your condition.
If you need to access the Series too and do not only need the Products, I would make the query like this:
$products=Product::with(array(
'serie'=>function($query)
{
$query->where('name','like','%unky%');
}))
->whereHas('serie', function($query) {
$query->where('name','like','%unky%');
})
->get()->toArray();
In this case, you get only the Products that are linked to a Serie whose name is like %unky% and you get only the related Series that hold to the same condition.
To sum this up: whereHas restricts the list of Products based on the condition, whereas the Eager Loading constraint restricts only the list of Series for each Product.

Transforming multidimensional array data returned from database

I am having problems with working with multidimensional array data.
I have 2 tables (maincategories and categories) which I joined.
Table Maincategories:
id, maincategory
Table Categories:
id, maincategory_id, category
$this->db->select('m.id, m.name_en AS maincategory')
->select('c.name_en AS category')
->from('categories AS c')
->join('maincategories AS m', 'c.maincategory_id=m.id', 'left');
$query = $this->db->get();
This results in all 4 categories being listed as below.
[3] => stdClass Object
(
[id] => 7
[maincategory] => Career
[category] => Business Sales
)
[4] => stdClass Object
(
[id] => 1
[maincategory] => Accommodation
[category] => Camping
)
[5] => stdClass Object
(
[id] => 6
[maincategory] => Accommodation
[category] => Hostels
)
[6] => stdClass Object
(
[id] => 7
[maincategory] => Career
[category] => Career Events
)
4 unique categories are in the list while 2 of them belong to maincategory: Accommodaton and the other 2 categories belong to maincategory: Career. What I wanted to achieve is that each maincategory is only listed ONCE and the categories shall fall under that main_category. Something like this:
[6] => stdClass Object
(
[id] => 7
[maincategory] => Career
[category] => array(Career Events, Business Sales, .....)
)
[7] => stdClass Object
(
[id] => 7
[maincategory] => Accommodation
[category] => array(Hostels, Camping, .....)
)
The array dump will maybe/probably look different in its end result but I hope you understand what I am trying to achieve. I read quite a bit about transforming multidimensional arrays. I just can't get my head around it yet. Thanks a lot for any direction!
Try like this:
function fetch_all(){
$data = array();
$first = $this->db->select('id, maincategory')->get('maincategory')->result_array();
if( is_array( $first ) && count( $first ) > 0 ){
foreach( $first as $key => $each ){
$data[$key]['category_id'] = $each['id']; #main category id
$data[$key]['maincategory'] = $each['id']; #main category name
$second = $this->db->select('category')->where_in('maincategory_id', $each['id'])->get('categories')->result_array();
$data[$key]['category'] = $second; #all sub-category(s) array
}
}
}
instead of using so many db calls, try using the underscore.php library http://brianhaveri.github.io/Underscore.php/
I've outlined a few examples of how to use it for this case here: http://codebyjeff.com/blog/2012/08/no-more-machine-gunning-use-underscore-php
Edit

Resources