Laravel pass list parameters (columns) in select query - php

I use three table spareparts, categories and parameter and YajraDatatables.
My controller action is:
public function anyData()
{
$spareparts_param_list = Sparepart::all();
$list='';
foreach ($spareparts_param_list as $value) {
foreach ($value->category->parameter as $par_list) {
$list .= $par_list->Name.',';
}
}
$spareparts = Sparepart::
join('cars', 'spareparts.car_id', '=', 'cars.id')
->select(['spareparts.id', 'cars.Brend', 'spareparts.Model', $list]);
$datatables = app('datatables')->of($spareparts);
return $datatables->make();
}
My array list $list print parameters such as color,type,tires,.
How to pass $list array in select query?

You can use whereIn:
public function anyData()
{
$spareparts_param_list = Sparepart::all();
$list = [];
foreach ($spareparts_param_list as $value) {
foreach ($value->category->parameter as $par_list) {
$list[] = $par_list->Name;
}
}
$spareparts = Sparepart::
join('cars', 'spareparts.car_id', '=', 'cars.id')
->whereIn('Name', $list)
->select(['spareparts.id', 'cars.Brend', 'spareparts.Model']);
$datatables = app('datatables')->of($spareparts);
return $datatables->make();
}
You can run this raw Mysql command:
select sp.id as sp_id, sp.model as sp_model, c.brend as car_brend, json_arrayagg(p.name) as p_name
from spareparts as sp
join cars as c on sp.car_id=c.id
join categories as cat on sp.category_id=cat.id
join parameters as p on cat.id=p.category_id
group by sp.model;
Above command will give you a result like the following:
1 | Audi A6 door | Audi A6 | ["color", "window"]
The last column will be a json column of all parameters related to each category.

You can use whereIn(), something like this:
$users = DB::table('users')
->whereIn('id', [1, 2, 3])
->get();
Docs - https://laravel.com/docs/5.7/queries#where-clauses

Related

how to join 4 tables in php laravel?

I Want to extract data from 4 tables .
like sname,cgpa,Group_Cgpa,Room_No and Hostel Name.
Relation of table is as follows.
AllotmentApps has : id,sname,cgpa and grpID (from Group id Table) columns.
Groups has : id,Group_CGPA
Room has : id, HostelID (From Hostel) and ResidentID (From Group id).
Hostels has: id, Name, Total_Rooms.
I'm facing problem in joining the tables. Join with AllotmentApps and Groups works fine, but problem occurs when I joined the Room and Hostel Table.
Join of AllotmentApps and Groups
public function FinalList()
{
$allot_apps = AllotmentApps::join('Groups','Groups.id','AllotmentApps.grpID')->orderBy('Groups.Group_CGPA', 'Desc')->get()->groupBy(
function($item) {
return $item->grpID;
}
) ->take(3);
Join of 4 Tables
public function FinalList()
{
$allot_apps = AllotmentApps::select('sname','cgpa','Group_CGPA','Hostel_Name')->join('Groups','Groups.id','AllotmentApps.grpID')->join('Hostels','Hostels.id','Hostels.HostelID')->join('Rooms','Rooms.id','Hostel.HostelID')->orderBy('Groups.id', 'Asc')->get()->groupBy(
function($item) {
return $item->grpID;
}
) ->take(3);
Try This
$allot_apps=AllotmentApps::select('AllotmentApps .sname','AllotmentApps .cgpa','Groups.Group_CGPA','tablename.Hostel_Name')
->join('Groups','Groups.id','=','AllotmentApps.grpID')
->join('Rooms','Rooms.ResidentID','=','Groups.id')
->join('Hostels','Hostels.id','=','Rooms.HostelID')
->orderBy('Groups.id', 'Asc')
->groupBy()
->get();
public function FinalList()
{ $capasity = Rooms::selectRaw('count(id) as c')->count();
$allot_apps = Rooms::select('Hostel_Name','Rooms.id','Groups.Group_CGPA','AllotmentApps.sname','AllotmentApps.cgpa')->join('Hostels','Hostels.id','Rooms.HostelID')->join('Groups','Groups.id','Rooms.ResidentID')->join('AllotmentApps','Groups.id','AllotmentApps.grpID')->orderBy('Groups.Group_CGPA', 'Desc')->get()->groupBy(
function($item) {
return $item->grpID;
}
) ->take($capasity);
// return $allot_apps;
return view('x', compact('allot_apps'));
}

Laravel table joins

I'm trying to do some table joins and having some trouble.i need to display
the customer’s complete name and title, item description, quantity ordered, for each item ordered after April 2000. i made a SQL script that works but i need to use Laravel ORM.
SELECT `first_name`,`last_name`,o.order_id,`quantity`,`description`,`date_placed`
FROM `customer` c
JOIN `order` o
ON c.`customer_id` = o. `customer_id`
JOIN `orderline` ol
ON o.`order_id` = ol. `order_id`
JOIN `item` i
ON ol.`item_id` = i. `item_id`
WHERE `date_placed` > '2000-4-00';
I created 2 models for the tables "Customer", "Order"
here is my Customer model
public function orders(){
return $this->hasMany('App\Order','customer_id');
}
here is my order model
public function orderline(){
return $this->hasMany('App\Orderline','order_id');
}
right now i am able to get some of my data but i dont feel like this is a good way to go about
$customer = Customer::all();
foreach($customer as $input){
$item = Customer::find($input->customer_id)->orders;
$name = $input->title . ' ' . $input->first_name . ' ' . $input->last_name;
$datePlaced = null;
$orderID = null;
foreach($item as $value){
$orderID = $value->order_id;
$datePlaced = $value->date_placed;
$order = Order::find($value->order_id)->orderline;
}
if anyone could point me in the right direction that would be great.
It looks like you want to get all Customers with their Orders and OrderLines?
Customer::with(['order' => function ($query) {
$query->where('date_placed', '>=', '2000-04-01')->with('orderline');
}])->get();
If you want to limit the columns on the relationships, you can...
Customer::with(['order' => function ($query) {
$query->select(/* columns */)->where('date_placed', '>=', '2000-04-01')
->with(['orderline' => function ($query) {
$query->select(/* columns here */);
}]);
}])->get();
Just make sure if you specify the columns in the relationships, that you're selecting all of the foreign keys or related columns for each relationship.

Getting null array PHP

i have a database named "products" which has a column "categories". This table contain four category of products namely electronic,Decoration,clothes and vehicle. My target to show these category with their count ie:if there are four products belongs to category electronic, then output should be like this :electronic=4 and so on
My code
public function category()
{
$arrayCategorys = ['electronic','Decoration','clothes','vehicle'];
$data = [];
foreach($arrayCategorys as $arrayCategory)
{
$sql = "SELECT count(id) FROM products WHERE categories='$arrayCategory'";
$records = \DB::select($sql);
$data = array_merge_recursive($data, [
"{$arrayCategory}" =>isset($records[0]->count),
]);
$data=array_filter($data);
dd($data);
}
}
I want show output like this
'electronic'=>'4',
'Decoration'=>'2',
'clothes'=>'2',
'vehicle'=>'1' according to data in database
but iam getting nothing ,[]
You can GROUP BY your categories like this way when you COUNT
SELECT categories,COUNT(*)
FROM products
GROUP BY categories;
For Idea: http://www.w3resource.com/mysql/aggregate-functions-and-grouping/aggregate-functions-and-grouping-count-with-group-by.php
EDIT: Though i am not familiar with laravel5 syntax but this may work for you
$result = DB::table('products')
->select('products.categories',
DB::raw('count(products.id) as category_count')
)
->orderBy('products.id', 'asc')
->groupBy('products.categories')
->get();
You used isset($records[0]->count) but the column name for the count will be count(id). Name the count as count like this "SELECT count(id) AS count FROM products WHERE categories='$arrayCategory'". And you wont be able to get the count just by checking if it is set. Remove the isset and just use $records[0]->count. The code should look like:
public function category()
{
$arrayCategorys = ['electronic','Decoration','clothes','vehicle'];
$data = [];
foreach($arrayCategorys as $arrayCategory)
{
$sql = "SELECT count(id) AS count FROM products WHERE categories='$arrayCategory'";
$records = \DB::select($sql);
$data = array_merge_recursive($data, [
"{$arrayCategory}" =>$records[0]->count,
]);
$data=array_filter($data);
dd($data);
}
}

Select posts based on selected categories

I have following scenario:
user selects couple categories
user should see posts which belongs to these categories
post belong to one or more categories
I setup the database like this:
users -> category_user <- categories
posts -> categoriy_post <- categories
I managed to accomplish this, but I had to find all ids from these tables to find relevant posts. I need to make it simpler because this approach is blocking some other actions I need to do. This is my code:
$categoryIds = Auth::user()->categories;
$ids = array();
$t = array_filter((array)$categoryIds);
if(!empty($t)){
foreach ($categoryIds as $key => $value) {
$ids[] = $value->id;
}
}else{
return View::make("main")
->with("posts", null)
->with("message", trans("front.noposts"))->with("option", "Latest");
}
$t = array_filter((array)$ids);
if(!empty($t)){
$p = DB::table("category_post")->whereIn("category_id", $ids)->get();
}else{
return View::make("main")
->with("posts", null)
->with("message", trans("front.noposts"))->with("option", "Latest");
}
$postsIds = array();
foreach ($p as $key => $value) {
$postsIds[] = $value->post_id;
}
$t = array_filter((array)$postsIds);
if(!empty($t)){
$postIds = array_unique($postsIds);
$posts = Post::whereIn("id", $postsIds)
->where("published", "=", "1")
->where("approved", "=", "1")
->where("user_id", "!=", Auth::user()->id)
->orderBy("created_at", "desc")
->take(Config::get("settings.num_posts_per_page"))
->get();
return View::make("main")
->with("posts", $posts)->with("option", "Latest");
}else{
return View::make("main")
->with("posts", null)
->with("message", trans("front.noposts"))->with("option", "Latest");
}
How to do this properly without this bunch code?
Yes, there is Eloquent way:
$userCategories = Auth::user()->categories()
->select('categories.id as id') // required to use lists on belongsToMany
->lists('id');
if (empty($userCategories)) // no categories, do what you need
$posts = Post::whereHas('categories', function ($q) use ($userCategories) {
$q->whereIn('categories.id', $userCategories);
})->
... // your constraints here
->get();
if (empty($posts)) {} // no posts
return View::make() ... // with posts
Or even better with this clever trick:
$posts = null;
Auth::user()->load(['categories.posts' => function ($q) use (&$posts) {
$posts = $q->get();
}]);
if (empty($posts)) // no posts
return View... // with posts
Obviously, you can write joins, or even raw sql ;)
You can take those categories directly from the database from user records:
SELECT ...
FROM posts AS p
INNER JOIN category_post AS cp ON cp.id_post = p.id
INNER JOIN categories AS c on c.id = cp.id_category
INNER JOIN category_user AS cu ON cu.id_category = c.id
WHERE cu.id_user = 123 AND p.published = 1 AND ...
Joins in Laravel can be achieved, see the documentation: laravel.com/docs/queries#joins Maybe there is also an Eloquent way, I don't know, try searching :-)

Search item in MySQL tree with many to many association

We are using Doctrine 2 for database access with tree extension.
First table is tree table with locations of European Union created from this source.
Location table:
id
name
parent
lft
rgt
lvl
root
companies
There is also company table which holds list of companies with many to many relation to location table. These locations are locations where given company acts. It can be country (level 0), some region (level 1, 2, 3, 4) or just some city, town or vilage (level 5).
Company table:
id
name
locations
Than we have got one search form for companies with location select.
Now I need to create DQL which will select all countries in given location (nested).
So when I choose for example whole country, it should select all companies in this country, in regions in this country and also in cities or towns in this country.
Thank you.
Edit:
I added "auto-adding" (maybe temporary) of parent locations into companies. It will just walk through all parents and add them. So when company acts in city and user choose whole country or region, this company will be displayed.
Unfortunately there is still one problem. If some company acts in whole country and user choose city in this country, company will not be displayed.
Searching is not so expensive and people will search in just few locations in one search query.
So the first thing I do, is to load ids of all searched locations and also ids of all their parents.
Getting parents' ids: BaseTreeFacade::getPathIds
public function getPathIds($entity)
{
$ids = $this->getPathQueryBuilder($entity)
->select('node.id')
->getQuery()
->getResult(AbstractQuery::HYDRATE_SCALAR);
return array_map('current', $ids);
}
this method returns simple array with ids. Now I have to join ids from search query with parents' ids.
Expanding ids: Helpers::expandTreeValues
public static function expandTreeValues(BaseTreeFacade $facade, array $values)
{
$result = [];
foreach ($values as $id) {
$entity = $facade->findOneById($id);
$result[] = [$id];
$result[] = $facade->getPathIds($entity);
}
$result = call_user_func_array('array_merge', $result);
$result = array_unique($result, SORT_NUMERIC);
return $result;
}
Next step is creating where clause for searching in locations and theirs children.
Creating where clause: Helpers::prepareWhereClauseForChildren
public static function prepareWhereClauseForChildren(BaseTreeFacade $facade, array $values)
{
$where = [];
$parameters = [];
foreach ($values as $id) {
$entity = $facade->findOneById($id);
$where[] = "(l.lvl > :level$id AND l.id > :left$id AND l.id < :right$id)";
$parameters["left$id"] = $entity->lft;
$parameters["right$id"] = $entity->rgt;
$parameters["level$id"] = $entity->lvl;
}
$where = implode(' OR ', $where);
return (object) [
'where' => $where === '' ? null : $where,
'parameters' => count($parameters) === 0 ? null : $parameters,
];
}
There I can search in all sub-locations because of left and right branches of tree. Last step is to update original QueryBuilder with where clause created in previous step.
Finalizing QueryBuilder: Helpers::updateWithTreeEntity
public static function updateWithTreeEntity(QueryBuilder $qb, array $values, $addWhere = null, array $addParameters = null)
{
if ($addParameters === null) {
$addParameters = [];
}
$addParameters['locations'] = $values;
$appendQuery = $addWhere === null ? '' : " OR $addWhere";
$qb->andWhere("l.id IN (:locations)$appendQuery");
foreach ($addParameters as $key => $value) {
$qb->setParameter($key, $value);
}
}
Usage example:
public function createQueryBuilderForSearchingInLocations(array $locations)
{
$gb = $this->createQueryBuilderSomehow();
$facade = $this->getLocationsFacadeSomehow();
$locations = Helpers::expandTreeValues($facade, $locations);
$where = Helpers::prepareWhereClauseForChildren($facade, $locations);
Helpers::updateWithTreeEntity($qb, $locations, $where->where, $where->parameters);
return $qb;
}

Categories