Count database column text values - Laravel - php

So, I have a database table that looks something like this:
id | title | category | author | post | created_at | updated_at
The category column is a text value, so it currently has values such as 'Tech', 'Web', and 'Animal'. What I need to do, is to count each category value in the category column and have an output such as:
Tech (2)
Animal (2)
Web (1)
Now, I do kind of have it working. It currently looks like:
Tech (1) (1)
Animal (1) (1)
Web (1)
The query in my controller is:
$categoryCount = Post::select(DB::raw('count(*) as cat_count, category'))
->groupBy('category')
->count();
My view currently looks like:
#if(count($category) > 0)
#foreach($category as $cat)
<a href="{{ URL('category/'.str_replace(' ', '-', $cat->name)) }}"
class="list-group-item">{{ $cat->name }}
#foreach($posts as $post)
#if($post->category == $cat->name)
({{ $categoryCount }})
#endif
#endforeach
</a>
#endforeach
#endif
I am quite new to Laravel itself, so I'm still learning. Any help to achieve what I want would be appreciated.

You do a DB raw count and then again a count. It will indeed then return always one. Change your query:
$categoryCount = Post::select(DB::raw('count(*) as cat_count, category'))
->groupBy('category')
->get();
And your results should be different. This has by the way nothing to do with Laravel, merely that you count the count :-)

Related

I get all values from database by sql

So, I have a table countries with a column flag.Here I have codes for every country by id.I tried to join the table in my page by SQL query, but I've got this...And I need to display only the right flag, by the id of country, not all the flags.
https://imgur.com/a/2F6Qvdv
My database structure : table countries , column id, country and flag
Here is my code :
Controller:
$data['contact_users'] = DB::table('contacts')
->join('users', 'users.id', '=', 'contacts.contact_id')
->join('industries', 'industries.id', '=', 'users.industry_id')
->join('countries', 'countries.id', '=', 'users.country_id')
->join('organization_types', 'organization_types.id', '=', 'users.organization_type_id')
->join("role_users", "role_users.user_id","=","users.id")
->leftJoin("career_paths", "career_paths.user_id","=","users.id")
->select('users.*', 'industries.industry', 'countries.country', 'organization_types.organization_type', "role_users.role_id", 'career_paths.function_id')
->where('contacts.contact_id', '!=', $id)
->where('users.deleted_at', '=', null)
->whereIn('contacts.user_id', $contact_id)
->whereNotIn('contacts.contact_id', $contact_id)
->whereNotIn('contacts.contact_id', $inviter_id)
->groupBy('contact_id')
->take(4)
->get();
$flags = DB::select('SELECT flag FROM countries WHERE country = "India"');
View:
#foreach ($flags as $flag)
{{ $contact->country }} <span class="{{ $flag->flag}}"></span>
#endforeach</a><br>
With {{ $contact->country }} I get the name of country and with {{ $contact->id }} I get the id of country.How can I make a conection between id and flag column?
// try this. you should have two tables here since you mentioned something like joining two tables. sample data and query.
countries: id | country | flagid
---|---------|----
1 | US | 1
flag: id | flag
----------
1 | image
//controller. this code is assume you are selecting/inputing the country name
public function getSingleFlag(Request $request)
{
$country = $request->input('countryname')
$data['country']=DB::table('countries')
->leftjoin('flag','countries.flagid','=','flag.id')
->where('country',$country)
->first();
return view('form',$data)
}
//this code is assume you are not selecting/inputing the country name. you just want to display all the countries with corresponding flags
public function getAllFlag()
{
$data['country']=DB::table('countries')
->leftjoin('flag','countries.flagid','=','flag.id')
->get();
return view('form',$data)
}
//your blade.
//for the first function
<p> {{ $country->country }} - {{ $country->flag}}</p>
//for the second function use foreach
#foreach($country as $c)
<p> {{ $c->country }} - {{ $c->flag}}</p>
#endforeach
note: remember to use your image tag to display your flag. just giving you an insight how it will be achieved

How to get likes/dislikes from database using ternary operator in laravel php

I'm trying to retrieve the number of likes and dislikes a post have.
I've the following table in database, in which I've like column which decides like or dislike. if it is 1 it means like if it is zero it means dislike.
Problem :
I'm trying to count the number of like(s) a post has and then show it for each post, I'm trying to achieve this using ternary operator but I'm getting 1 like and 1 dislike for every post which is wrong according to the above table data.
Is there anything I'm doing wrong, because I think the code should work .
Because for post_id 1 the number of likes should be 2 according to the table , but I get 1 like and 1 dislike for each post.
Code
This is the code I'm trying to get the number of likes and dislikes
#if(count( $post->likes()->where('$post->like'==1) )>=1 )
<small>{{ count($post->likes()->where('$post->like' ==1))>=1?count($post->likes()->where($post->like ==1)). ' Likes':count($post->likes()->where($post->like ==1)).'Dislike' }}</small>
#else
<small>// similary do this for dislikes when like column in the above table is 0</small>
#endif
</small>
You can use the count and withCount method from eloquent to make this easier for you
You can count the likes and dislikes in your controller like this:
$posts = App\Post::withCount([
'likes' => function ($query) {
$query->where('like', 1);
},
'likes as dislikes_count' => function ($query) {
$query->where('like', 0);
}
])->get();
Then you can those counts this in your blade like
Likes count: {{ $post->likes_count }}
Dislikes count: {{ $post->dislikes_count }}

Laravel sort child relationship collection

I have the following 3 tables:
Movie
- id
Series
- id
- status_id
- movie_id
Status
- id
- order_number
this is the code on the controller:
$movie = Movie::where('slug', $slug)->with(['series'])->first();
this is the code for view:
#foreach ($movie->series as $series)
{{ $series->name}}
#endforeach
how to sort $movie->series based on status->order_number? if it can be written on the model, so every order is only written once the controller?
is there a code that I can use for example like this:
$movie->series->sortBy('status.order_number');
Yes, but you will need to join status with series:
$movie = Movie::where('slug', $slug)->with([
'series' => function ($query) {
// Subquery on `series` table
return $query
// select whatever you'll need
->select('series.*')
// join with status
->join('status', 'series.status_id', '=', 'status.id')
// order by order number
->orderBy('status.order_number')
// * you can drop this if you select all the fields you need and use those
->with('status');
},
])->first();
Edit this ^ method will sort on SQL level, but you could also do this with collections:
#foreach ($movie->series->sortBy('status.order_number') as $series)
{{ $series->name}}
#endforeach
In that case also add .status to your with to avoid n + 1 problem: ->with(['series.status'])
The reason your attempt didn't work is because ->sortBy(..) doesn't mutate the collection, it just returns a new sorted one. This would work:
$movie->series = $movie->series->sortBy('status.order_number');

Building query to select from 3 tables in Laravel

Normally I know how to query and join three tables but here I can't figured it how to happen. The thing is that I have followed 3 tables:
category -> columns
id
name
image
sub-category -> columns
id
table1_id
name
image
Sub-sub-category -> columns
id
table2_id
name
image
So image can be added only to Category or to Category->Sub-Category or to third level Category->Sub-Category->Sub-Sub-Category
What I'm trying to do is when I show ALL images on page to show also to which category they are added.
I've made all relations in my models but I can't figured it out how to query exactly. Currently only querying all images like
SubSubCategories::all();
Example:
I have main category(Country) which has sub-category (district) which has sub-sub-category(city).
image1 is added to Sub-Sub-Category with name city. When images are listed I want to show
images1 added to Country->District->City.
Can someone show me example query or maybe my relations eg. columns in tables are wrong?
This is what I've tried so far
$subsubcategories = DB::table('sub_sub_category')
->join('sub_category', 'sub_sub_category.sub_cat_id', '=', 'sub_category.sub_cat_id')
->join('category', 'category.category_id', '=', 'sub_category.sub_cat_id')
->select('sib_sub_category.*', 'sub_category.*', 'category.*')
->get();
Then in my view
{{ $subsubcategory->sub_category->sub_cat_name }} > {{ $subsubcategory->sub_sub_cat_name }}
error
Undefined property: stdClass::$sub_category
$subsubcategories = DB::table('category')
->join('category', 'category.id', '=', 'sub_category.table1_id')
->join('sub_category', 'sub_category.id', '=', 'sub_sub_category.table2_id')
->select('category.*', 'sub_category.*', 'sub_sub_category.*')
->get();
Actually you are almost there. Just remove the sub_category from the view and will work.
{{ $subsubcategory->sub_cat_name }} > {{ $subsubcategory->sub_sub_cat_name }}
This is happen because your array currently is looks like
object(stdClass) {
["id"]=> int(1)
["table2_id"]=> int(1)
["table1_id"]=> int(1)
...
// all other columns
}
So actually they belongs to $subsubcategory and no need to bring sub_category and category in the view. Just display them in your $subsubcategory.

Laravel 4.2 n+1 without eager loading

I have a table with products
products
------------------------------------------------
id product_code purchase_type quantity
1 106 new 1
2 107 renew 3
and a pricelist for products
price_list
----------------------------------------------------------------------
id product_code purchase_type minimum maximum unit_price
1 106 new 1 25 20
2 106 new 26 50 16
3 106 new 51 100 14
When I display the products on a page, I need to display the price with the formula
getPrice(product_code, purchase_type, quantity) for every product
Using
foreach(Product::all() as $product){
{{ $product->product_code }}
{{ $product->purchase_type }}
{{ $product->quantity }}
{{ PriceList::getPrice($product->product_code, $product->purchase_type, $product->quantity) }} - this one is the n+1 problem
}
PriceList::getPrice() is something like:
public static function getPrice($productCode, $purchaseType, $quantity){
return PriceList::where('product_code', $productCode)
->where('purchase_type', $purchaseType)
->where('minimum', '>=', $quantity)
->where('maximum', '<=', $quantity)
->get()->first()->unit_price;
}
I can't seem to find a more efficient way.
And when I display over 1000 products, then it gets really slow.
I can't seem to find a way to use eager loading.
It is not a good idea to call model from inside loop to get data.
Instead of doing that, follow below way.
You should define relationship between Product and PriceList tables.
In Model Product.php
public function price_list(){
return $this->hasMany('PriceList','product_code');
}
In Model PriceList.php
public function product(){
return $this->belongsTo('Product','product_code');
}
In Controller File
$products = Product::with('price_list')->get();
return View::make('your_view')->with('products', $products);
In View File (file must have extention .blade.php to use below syntax)
#foreach($products as $product)
{{ $product }}
#endforeach
Note:- Print $products in controller to check results.
I found a way with mysql,
SELECT
`products`.`id` AS `product_id`,
`products`.`product_code` AS `product_product_code`,
`products`.`purchase_type` AS `product_purchase_type`,
`products`.`quantity` AS `product_quantity`,
`price_list`.`product_code` AS `price_list_product_code`,
`price_list`.`purchase_type` AS `price_list_purchase_type`,
`price_list`.`minimum` AS `price_list_minimum`,
`price_list`.`maximum` AS `price_list_maximum`,
`price_list`.`unit_price` AS `price_list_unit_price`
FROM
`products`
LEFT JOIN `price_list` ON `products`.`product_code` = `price_list`.`product_code`
AND `products`.`purchase_type` = price_list.purchase_type
AND `products`.`quantity` >= price_list.minimum
AND `products`.`quantity` <= price_list.maximum
ORDER BY
`products`.`id` ASC
http://sqlfiddle.com/#!9/5d6ac/2

Categories