Get User Ranking based on number of posts (Codeigniter) - 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();
}

Related

How to add a momentary value to a sql query in Laravel

I have this query in Laravel 8:
$articles = Article::whereIn('category_id', $categories)->where(function ($query) {
$query->where(function ($query2) {
$query2->where('draft', 0)->whereNull('publication_date');
})->orWhere(function ($query2) {
$query2->where('draft', 0)->where('publication_date', '<=', DateHelper::currentDateTime());
});
})->orderBy('publicated_at', 'DESC')->get();
I need to add a momentary id to this query named desc_id, so that the values $articles that i query have a desc_id based on the publication_date.
The result that i need to achieve is like this:
id
name
category
publication_date
desc_id
3
bananas
news
2022-01-16 17:30:00
1
27
kiwis
news
2021-12-05 21:30:00
3
50
apples
news
2022-01-07 09:14:00
2
I've tried adding it by passing all the elements of $articles into an empty array adding a value:
$count =0;
$allArticles = [];
foreach ($articles as $article) {
$count++;
$allArticles[] = $article->with('desc_id', $count);
}
I know that my method is incorrect but i hope that it helps understanding my question.
It looks like you want to have the line number of each row which can be achieve like this :
Article::whereIn(...)->select()
->addSelect(DB::raw('RANK() OVER(ORDER BY publicated_at DESC) as desc_id'))
->orderBy('publicated_at', 'DESC')
->get();

Laravel 7: How to match two tables column?

Please see my code first,
Measurement Table:
id
customer_id
service_id
1
1
2
2
1
3
2
2
Controller:
$customer = Customer::findOrFail($id);
$ex = Measurement::where('customer_id', $id)->pluck('service_id');
if(count($ex) == 0){
$service = Service::where('status', 0)->get();
}
else{
$service = Service::where('id', '!=', $ex)->where('status', 0)->get();
}
In Measurement table, if a customer doesn't have any service_id then $service = Service::where('status', 0)->get(); this will pass in view file.
If a customer have a service_id, then in view file all services will pass except that service_id.
Can anyone suggest me a better way for this?
How about this
$customer = Customer::with('services')->where('customer_id', $id)->first();
$serviceRowCount = 0;
if ($customer->services->count() > 0) {
$services = $customer->services->whereNotNull('service_id');
$serviceRowCount = $services->count();
}
if ($serviceRowCount > 0) {
$services = Service::whereNotIn('id', $services->pluck('service_id'))->get();
} else {
$services = Service::where('status', 0)->get();
}
return view('test')->compact('services');
I am assuming that Customer has primary key as customer_id, has relation with Measurement model as services and service_id has default value as null.

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 object value on an array iteration with foreach

In the following very simplified example and study case, we get the list of posts and the count of comments for each post.
However, I intended to send to client side only the value, i.e. 2, and not the array object [{total: 2}]
Is there a simplified way to do this with the laravel?
Note: DB::select must be used
public function readPosts(Request $request) {
$posts = DB::select("SELECT * FROM posts");
foreach ($posts as $key => $post) {
$idComment = $post->id_comment;
$post->nComments = DB::select('SELECT COUNT(id_comment) As total FROM post_comments WHERE id_comment = ? ', [$idComment]);
}
if($posts){
return response()->json(['success'=>true, "output"=>$posts);
}else{
return response()->json(['success'=>false]);
}
}
response
data:
0:
id_post: 1
post: "post text"
nComments: [{total:2}]
1:
id_post: 2
post: "post text 2"
nComments: [{total:1}]
Expected
data:
0:
id_post: 1
post: "post text"
nComments: 2
1:
id_post: 2
post: "post text 2"
nComments: 1
I suggest that you can use Eloquent with eager loading to get the count.
However you need to reconstruct your tables, and build relationship with your models.
If you really want to use DB::select(),
You can just use subquery
$posts = DB::select('
SELECT posts.*, (
SELECT COUNT(id_comment) AS total
FROM post_comments
WHERE id_comment = posts.id_comment) AS total
FROM posts')
you can try this
public function readPosts(Request $request) {
$posts = DB::select("SELECT * FROM posts");
foreach ($posts as $key => $post) {
$idComment = $post->id_comment;
$total = DB::select('SELECT COUNT(id_comment) As total FROM post_comments WHERE id_comment = ? ', [$idComment]);
$post->nComments = $total[0]['total'];
}
if($posts){
return response()->json(['success'=>true, "output"=>$posts);
}else{
return response()->json(['success'=>false]);
}
}
Cleanest way would be to use the relations comments of the post
public function readPosts(Request $request) {
$posts = DB::withCount('comments')->get();
if($posts){
return response()->json(['success'=>true, "output"=>$posts);
}else{
return response()->json(['success'=>false]);
}
}
response
data:
0:
id_post: 1
post: "post text"
comments_count: 2
1:
id_post: 2
post: "post text 2"
comments_count: 1
Plus: this will take advantage of the eager loading in Eloquent and the results will be way faster and performant.
Try this simple
$posts = Post::withCount('comments');
dd($post);
You can use count() for the collections count.
foreach ($posts as $key => $post) {
$idComment = $post->id_comment;
$comments = DB::select('SELECT COUNT(id_comment) As total FROM post_comments WHERE id_comment = ? ', [$idComment]);
$post->nComments = $comments[0]['total'];
}

Codeigniter, how to pass COUNT result too my view

i have problem with passing data from model to my view. In Database i have Project with a few tasks i need to COUNT it. My problem is: How to pass the results to the view with foreach.
(echo $this->db->count_all_results(); in MODEL show good results)
Project 1: 5 tasks
Project 2: 10 tasks
Project 3: 1 task
MODEL:
function wyswietl($arrayid){
$query = $this->db->query("SELECT COUNT( id_zadania ) AS zlicz
FROM projekty_zadania
WHERE id =$arrayid");
return $query->result();
CONTROLLER
function WszystkieProjekty(){
$data['moje'] = $this->Todo_model->wyswietlWszystkieProjekty();
$arrayid = array();
foreach( $data['moje'] as $row ){
$row->id;
$aaa = $row->id;
$arrayid[] = $this->Todo_model->wyswietl($aaa);
}
$data['tabid'] = $arrayid;
$this->load->view('Projekty.html', $data);
}
MODEL:
function wyswietlWszystkieProjekty(){
$query = $this->db->query("SELECT * FROM todo");
return $query->result();
}
You're passing back to your controller a result set, so all you need to do is iterate over the result set, generating actual rows. It's not too hard, and you've got the right idea.
You have:
function wyswietl($arrayid){
$query = $this->db->query("SELECT COUNT( id_zadania ) AS zlicz
FROM projekty_zadania
WHERE id =$arrayid");
return $query->result();
As your model function that is supposed to return the count, right? Easiest way to do this is right from the model to keep your controller from having to do the legwork. When you run the count function in mysql, you'll only get back one row in your case, so using num_rows() isn't going to help because this query will always generate 1 row.
function wyswietl($arrayid){
$query = $this->db->query("SELECT COUNT(id_zadania) AS zlicz
FROM projekty_zadania
WHERE id =$arrayid");
$rs = $query->result();
return $rs[0]['COUNT(id_zaedania)'];
}
In your query, you have counted the data, so i think you can get the total data in the model from $query->rows()->zlics. And in the controller, just pass it to the view like usual
$data['moje'] = $this->Todo_model->wyswietlWszystkieProjekty(); $this->load->view('Projekty.html', $data);

Resources