I have a table like this:
CourseCategory can have duplicates in this table so that means a courseCategory can have multiple courseNames.
I am fetching all the courseCategory like this:
$courseCategories = Course::all()->pluck('courseCategory')->unique();
But Now I want to map all the courseNames beloging to a courseCategory in this collection.
so that I can have a $courseCategories which I want to be able to access it like this:
foreach($courseCategories as $courseCategory){
foreach($courseCatgory->courseNames as name){
//code
}
}
to get such a $courseCategories So far I have tried:
foreach ($courseCategories as $courseCategory) {
$courseCategories->$courseCategory = Course::where('courseCategory', '=', $courseCategory)->pluck('courseName');
}
dump($courseCategories);
which looks like this which is not quite right:
How Can I do this?
First get all data
$data = Course::all()
Get its category
$categories = $data->pluck('courseCategory')->unique();
Then do some mapping and filtering to get each of those categories child.
$result = $categories->map(function($category) use ($data) {
return $data->filter(function($row) use ($category) {
return $category == $row->courseCategory;
})->pluck('courseName');
});
Related
I'm trying to get only the category names, of all articles on the index() function on Laravel. So all articles and the related categories of each article. It's a many-to-many relationship.
What i did so far:
foreach($articles as $article) {
if (isset($article)) {
$article['categories'] = $article->category;
}
}
This gets me all articles with the related categories as a collection, it works, but not quite what I want. As I said, I want only the category names.
I tried $article->category->name; obviously did not work
also: $article->category->get('name');
furthermore what is interesting, If I rename $article['categories'] to $article['cat'] I get 2 collections the category with all related category objects and another exact same on just names cat.
I also tried:
...
$article['categories'] = $this->getcat($articles);
return response()->json($articles, 200);
}
public function getcat($query) {
if (isset($query) && is_countable($query)) {
foreach ($query as &$entity) {
if (!isset($entity)) { continue; }
if (isset($entity->categories)) {
$originObjects = $entity->categories;
$competition_all = [];
foreach($originObjects as $object) {
array_push($competition_all, $object->name);
}
return $competition_all;
}
}
}
The function returns what I need, but it does not return it as json, on the frontend.
From what i see.. your response is return response()->json($names, 200); , but your categories names array is saved into the $article['categories'] array. So.. if you return the response()->json($article, 200);, your categories names should be returned as json. The reason that $article->category->name; does not works is because this is array with objects because the type of your relation, but here you call only property.
The better way is to add to the query, the with function and pass the relation as first parameter, and then in second to add anonym function with the query and select only the names.
Eg.
$articles = Article::with('category', function($q) { ... })->get();
I have a database column called support_tags. This is a jsonb column containing a simple array that looks like:
[
"caring",
"budgets",
"careers_employment",
"addictions"
]
I am attempting to query this column using the following:
$services = \App\Models\Service::where("status", "accepted")->whereRaw("JSON_CONTAINS(support_tags, '" . json_encode($categories) . "')")->get();
This doesn't retrieve the results I am hoping for/expecting. If I send the following array:
[
"caring",
"smoking"
]
The results I get back are services that contain all array elements. I need this to work more like a whereIn, in that not all array values need to be present in the database column, but one or more. If anyone knows of a way to do this I'd be very grateful. Thanks.
you can use these eloquent methods: ->whereJsonContains() and ->orWhereJsonContains()
your query will be like this:
$services = \App\Models\Service::where("status", "accepted")
->where(function($query) {
$query->whereJsonContains('support_tags', 'smoking')
->orWhereJsonContains('support_tags', 'caring');
});
Just before I accept the other answer to this question, I thought it may be useful to share my implementation of this which is based on the accepted answer This does the trick:
$categories = request()->infoAdviceCategories;
$services = [];
if (count($categories)) {
$services = \App\Models\Service::where("status", "accepted")->whereJsonContains("support_tags", $categories[0]);
foreach ($categories as $category) {
if ($category !== $categories[0]) {
$services->orWhereJsonContains("support_tags", $category);
}
}
$services = $services->get();
}
return $services;
I have two query results.I need to merge the query result based on a condition.
$portfolio = DB::table('architects_portfolio')->get();
$img=DB::table('architects_portfolio_images')
->distinct()->get(['architects_images_id']);
and my condition to merge is
architects_portfolio.id = architects_portfolio_images.architects_images_id
I have my first table 'architects_portfolio' which contain portfolio and second table 'architects_portfolio_images' which contain images of portfolio.I need to get only one image for now.But I get all images of portfolio now by using below code.But I need only one
$architect = User::find($user_id)->architect;
$portfolio = ArchitectsPortfolio::join('architects_portfolio_images as images', 'architects_portfolio.id', '=', 'images.architects_images_id')
->where('architects_portfolio.architects_id', $architect->id)
->select('architects_portfolio.id', 'architects_portfolio.architects_id', 'architects_portfolio.name', 'architects_portfolio.description', 'images.filename','images.architects_images_id')
->distinct()->get(['images.architects_images_id']);
My tables
architects_potfolio
architects_portfolio_images
You should try this:
$rsltArchitectDetails = DB::table('architects_portfolio')
->select('architects_portfolio_images.architects_images_id')
->join('architects_portfolio_images', 'architects_portfolio.id' , '=', 'architects_portfolio_images.architects_images_id')
->distinct()
->get();
$querys = DB::table('architects_portfolio');
$querys->select('architects_portfolio_images.architects_images_id');
$querys->join('architects_portfolio','architects_portfolio.id','=','architects_portfolio_images.architects_images_id')->distinct()->get();
The best way is to use relationships, then you could just load portfolios with related images:
$portfolios = ArhitectPortfolio::with('images')->get();
To make it work, you just need to define the images relationship in the ArhitectPortfolio model:
public function images()
{
return $this->hasMany(ArchitectPortfolioImage::class, 'architects_images_id');
}
Instead of merging we can make use of following code
$data = Architect::where("user_id", $user_id)->first();
$architect = User::find($user_id)->architect;
$portfolio = ArchitectsPortfolio::where('architects_portfolio.architects_id', $architect->id)->paginate(6);
foreach ($portfolio as $r) {
$image = ArchitectsPortfolioImages::where('architects_images_id', $r->id)->first();
if ($image) {
$r->filename = $image->filename;
}
}
I have a query which looks like this:
$items = Item::live()
->with('location')
->where('last_location_id', Input::get('last_location_id'))
->get();
The background of this is...
2 tables: Items & Cars.
The live scope is:
public function scopeLive($query)
{
return $query->whereHas('basic_car', function($q)
{
$q->whereNotNull('id')->where('sale_status', 'Live');
});
}
This basically checks the cars table for a matching id to that of the items 'car_id' field and will run some where clauses on the cars table.
I now however want to check another field on the cars table, but using the Input::get('last_location_id') from the original query.
$items = Item::live()
->with('location')
->where('last_location_id', Input::get('last_location_id'))
->orWhere('ROW ON THE CARS TABLE' = Input::get('last_location_id'))
->get();
This does't work, then I tried:
$items = Item::live()
->with('location')
->where('last_location_id', Input::get('last_location_id'))
->orWhere(function($query)
{
$query->where('cars.Location', Input::get('last_location_id'));
})
->get();
Which results in an unknown column 'cars.Location' error.
My next test was to create another scope:
public function scopeLiveTest($query)
{
return $query->whereHas('basic_car', function($q)
{
$q->whereNotNull('id')->where('sale_status', 'Live')->where('Location', 1); // hardcoded ID
});
}
And replacing the live() scope with that works but I dont get the affect of the orWhere in the query itself and I also cannot specify a ID from the Input.
How can I do this?
You can pass a parameter to scope like this:
$items = Item::liveAtLocation(Input::get('last_location_id'))
->orWhere(function( $query ) { // to get the OR working
$query->live()
->with('location')
->where('last_location_id', Input::get('last_location_id'));
})
->get();
And for the scope:
public function scopeLiveAtLocation($query, $location_id)
{
return $query->whereHas('basic_car', function($q) use ($location_id)
{
$q->whereNotNull('id')->where('sale_status', 'Live')->where('Location', $location_id);
});
}
I presently have 3 tables: Shows, Genres and Show_Genre (associates the two). I have a search form that submits a series of checkboxes with values into an array based on what genres they selected. Presently I want to associate the Shows table and the Genres table into a variable and run a query against it once for every genre checkbox selected. Then, once the selection is filtered, I can display the resulting Show objects that matched the users parameters.
My present setup is the following
public function searchShows(SearchRequest $request)
{
//$ShowsWithGenres give a collection inside a collection which I can't seem to even access its values without doing a bunch of ugly code using count() in a for loop
$ShowsWithGenres = Show::with('genres')->get();
$genres = $request->name;
if(isset($genres))
{
foreach($genres as $genre)
{
//iterate against the selection repeatedly reducing the number of results
}
}
}
Thanks.
You should use whereHas() and whereIn.
Perhaps something like this should do it:
$shows = Show::whereHas('genres', function($q) use($genre_ids)
{
$q->whereIn('id', $genre_ids);
})->get();
EDIT
Try this, however I'm unsure about the performance.
$query= Show::query();
foreach($genre_ids as $id){
$query->whereHas('genres', function($q) use($id)
{
$q->where('id', $id);
})
}
$shows = $query->get();
Using Eloquents whereHas() function you can query results based on the relation's data. http://laravel.com/docs/5.0/eloquent#querying-relations
public function searchShows(SearchRequest $request)
{
// Start a query (but don't execute it at this point as we may want to add more)
$query = Show::with('genres');
$genreNames = (array) $request->name;
// Check there are some genre names, if theres not any it'll cause an SQL syntax error
if (count($genreNames) > 0)
{
$query->whereHas('genres', function($subQuery) use ($genreNames)
{
$subQuery->whereIn('genre_name', $genreNames);
}
}
// Finally execute the query. $shows now contains only shows with the genres that the user has searched for, if they didn't search with any genres, then it contains all the results.
$shows = $query->get();
}