How to calculate each column and display using Eloquent - laravel-5

I'm studying about search.
I can get a only one first result.
Table name is "color"
here is column info
id | colorname
-----------------
1 black
2 pink
3 blue
4 pink
5 green
I would like to calculate each 'colorname' amount
and display list.
this is my current code
public function search(Request $request)
{
$colors = Color::select('colorname', DB::raw('COUNT(colorname) count'))
->groupBy('colorname')
->get();
$param = ['input' => $request->input, 'colors' =>$colors];
return view('contacts.find', $param);
}
blade file
#if (isset($colors))
<table>
<tr>
<td>{{$colors->getData()}}</td>
</tr>
</table>
</div>
#endif
MODEL
class Color extends Model
{
public function getData()
{
return $this->color;
}
}

Use this:
$colors = Color::select('colorname', DB::raw('COUNT(colorname) count'))
->groupBy('colorname')
->get();

You need to count all the colors, and then group them by their name :
SELECT COUNT(colorname), colorname FROM color
GROUP BY colorname;
Here a SQLFiddle : http://sqlfiddle.com/#!9/821d57/7/0

Related

How to create a hasMany relationship with different models in folder?

I have a strange Laravel 9 setup due to being constrained to a very ancient database.
I'm trying to come up with a clean way to create a hasMany relationship to multiple models located in a folder. I believe it would be easiest explained with diagrams:
app/Models/
- Customer
app/Models/Records/
- Orange
- Green
- Blue
Now, all of these records has some connection to customer, but these are all different as well, for example, orange refers to customer using cid, where Green might use customerid.
I've already set up logic where every record model has a customer belongsTo relationship depending on the different field names.
public function customer()
{
return $this->belongsTo('App\Models\Customer', 'CustomerId');
}
I need to create a records() function in the Customer model, that pulls in all of these Records where found. I can't create any new tables that would be stored on the DB.
For multiple tables (models) to be connected as hasMany is probably not possible out of the box in Laravel.
However if you do really need to combine them all, I did once but it is not pretty.
First add following to each of your App\Records\Model in example is Green
class Green extends Model
{
protected $table = 'GreenRecords';
....
....
// this is to append/add extra fields into your model
// that not exist inside the table it self
protected $appends = [
'product_data',
'stuffs',
];
// relationship to App\Models\Customer
public function customer()
{
return $this->belongsTo(Customer::class, 'customerid', 'id');
}
// you can use it later as Green::query()->customer($id)->get()
public function scopeCustomer($query, $id)
{
return $query->where('customerid', $id);
}
// you can add here as many data as you like from table GreenRecords,
// this will make Green Orange and Blue as if they have common fields
// you can also separate them by adding add each custom field to $appends
public function getProductDataAttribute()
{
return [
'name' => $this->name,
'color' => $this->color,
'stuffs' => $this->stuffs,
'other_stuffs' => $this->other_stuffs,
];
}
public function getStuffsAttribute()
{
return $this->stuffs;
}
}
And now for the Customer model
class Customer extends Model
{
// your Customer relation to Orange
public function oranges()
{
return $this->hasMany(Orange::class, 'cid', 'id');
}
// your Customer relation to Green
public function greens()
{
return $this->hasMany(Green::class, 'customerid', 'id');
}
public function getRecords(): Collection
{
// we can not use collection merge due to same 'id' in Orange and Green
$collections = collect();
if ($oranges = Orange::query()
->customer($this->id)
->get()
) {
foreach ($oranges as $record) {
$collections->push($record);
}
}
if ($greens = Green::query()
->customer($this->id)
->get()
) {
foreach ($greens as $record) {
$collections->push($record);
}
}
return $collections;
}
}
So now you can do
$customer = Customer::find(3);
$records = $customer->getRecords(); // result will be a collection
And inside your blade you can access them
#foreach ($records as $record)
{{ $record->stuffs }}
{{ $records->product_data['other_stuffs'] }}
#endforeach
A collection can be filtered and sorted
$records->where('product_data.stuffs', 'abc')->sortBy('name');
The only problem here is the records id where Orange can have the same id as Green and Blue.
Best is to add new field into Orange Green and Blue
$table->uuid('record_id')->nullable();
Hope this can help you out.
None of these solutions quite achieved what I was looking for in terms of simplicity, and in my case my database is quite out of date and slow, so I ended up landing on a solution that is quite simple and faster than everything posted for my use case:
public function records()
{
return [
"Orange" => $this->hasMany(\App\Models\Records\Orange::class, 'CustomerId', 'Id')->get(),
"Blue" => $this->hasMany(\App\Models\Records\Blue::class, 'Customerid', 'Id')->get(),
"Purple" => $this->hasMany(\App\Models\Records\Purple::class, 'customerid', 'Id')->get(),
"Black" => $this->hasMany(\App\Models\Records\Black::class, 'CustomerId', 'Id')->get(),
"Green" => $this->hasMany(\App\Models\Records\Green::class, 'Customerid', 'Id')->get(),
"Cyan" => $this->hasMany(\App\Models\Records\Cyan::class, 'CustomerId', 'Id')->get()
];
}
This achieves what I was looking for in terms of setting up the relationships when the customerId field was subject to change on the other tables, and is pretty readable overall.

Get Data through relation in laravel

I'm using this query to get data using relation
return Product::with('attributes')
->whereHas('attributes', function ($query) use ($attribute_id,$attribute_value){
$query->whereIn('attribute_id', $attribute_id);
$query->whereIn('value', $attribute_value);
})
->paginate(10);
$attribute_id and $attribute_value are arrays, i'm getting data using this relation but when $attribute_id and $attribute_value are empty then i'm not getting any result but it should return result through product table if there are no attributes.
I have changed it to something like this:
if(!empty($attribute_id))
{
$query->whereIn('attribute_id', $attribute_id);
}
if(!empty($attribute_value))
{
$query->whereIn('value', $attribute_value);
}
model relation :
public function attributes()
{
return $this->hasMany(ProductsAttribute::class, 'product_id ');
}
Table:
id | Title | Price
1 Title 1 5000
2 Product 2 7000
this is related to product_attribute table
id | product_id | attribute_id | attribute_name | value
1 1 5 Color Red
2 1 6 Size XL
3 2 5 Color Green
Is there any other way to make a check in query so that if attributes are not provided then atleast product data should return.
A cleaner way might be to use local scopes. That way, your controllers will look cleaner. It also makes the code easily testable. Here is how I might approach this.
NOTE: Code hasn't been tesed.
In your controller:
return Product::with([
'attributes' => function ($query) use ($attribute_id, $attribute_value) {
return $query->inAttributeId($attribute_id)
->inAttributeValue($attribute_value);
}
])->paginate(10);
In your ProductsAttribute model:
public function scopeInAttributeId($query, $attributeId)
{
if (empty($attributeId)) {
return $query;
}
return $query->whereIn('attribute_id', $attributeId);
}
public function scopeInAttributeValue($query, $attributeValue)
{
if (empty($attributeValue)) {
return $query;
}
return $query->whereIn('value', $attributeValue);
}
As you can see, the scopes modify the query only if there are values in the passed in array. If the passed in array is empty, it returns the original query.

Get User Ranking based on number of posts (Codeigniter)

I have a number of users who are posting content to the POSTS Table.
id user_id content
1 1 text
2 3 text
3 1 text
4 1 text
5 2 text
6 3 text
Now, I would like to get a single user rank by highest posts(row). I'm confused about how to get the result!
Asuming that you are using the query builder, from the model, you can use the following statement to obtain the required result:
$this->db->select('user_id, count(content) as total_posts')
->group_by('user_id')
->order_by('total_posts', 'DESC')
->limit(1)
->get('POSTS')
->row();
The issue has been solved. Here is the explanation of how I've done this:
model
public function get_user_ranking()
{
$this->db->select('user_id, count(id) as total_posts');
$this->db->group_by('user_id');
$this->db->order_by('total_posts', 'DESC');
$query = $this->db->get('posts');
return $query->result();
}
controller
$data['user_ranking'] = $this->post_model->get_user_ranking();
view
$rank = 1; foreach($user_ranking as $row)
{
if( $row->user_id == $user->id)
{
echo $rank;
break;
}
$rank++;
}
public function get_user_ranking()
{
$this->db->select('user_id, count(id) as total_postings');
$this->db->from('posts');
$this->db->group_by('user_id');
$this->db->order_by('total_posts', 'DESC');
return $this->db->get()->result();
}

How to group similar records in Laravel?

I have a problem with grouping records based on their name of the color. Here I would like to explain with an example. I have "BLUE JEAN(3)" with the quantity 3 & "BLUE JEANS MET(7)" with the quantity 7, can we group together ? I want the output BLUE JEAN(10).
Note: These are already distributed in database with different ID. I have lots of colors so I need to group only those similar colors and need to populate for searching.
Here is my structure of coding:
Model:
class MyVehicle extends Model
{
protected $fillable = [
'name',
'color_id',
'stock_number'
];
}
Controller:
public function searchVehicleColor()
{
$vehicles_colors = DB::table('vehicles')
->select(DB::raw('COUNT(vehicles.color_id) as color_count'), 'colors.color')
->leftjoin('colors', 'colors.id', '=', 'vehicles.color_id')->get();
return view('public/search_result', compact('vehicles_colors'));
}
View:
#foreach($vehicles_colors as $vehicles_color)
<li>
{{ Form::checkbox('color[]', $vehicles_color->color, null, ['class' => 'color field','id'=>$vehicles_series_color->color,'onClick'=>'reply_click(this.id)']) }}
<label for="{{$vehicles_color->color}}">{{$vehicles_color->color}}({{$vehicles_color->color_count}})</label>
<div class="check"></div>
</li>
#endforeach
Here is the output , I just want to merge highlighted data.
Please help, Thanks in advance.
public function searchVehicleColor(){
$vehicles_colors = DB::table('vehicles')
->select(DB::raw('COUNT(vehicles.color_id) as color_count'),'colors.color')
->leftjoin('colors', 'colors.id', '=','vehicles.color_id')->groupBy('name')->get();
return view('public/search_result', compact('vehicles_colors'));
}

How to best get results from 3 different tables based on ID matches in Laravel.

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

Resources