[Laravel]calc table column specfic range question - laravel

[UPDATE]
I'm studying number sum at laravel.
I would like to calculate table's columns total amount every month.
I wrote below code and I got this dd result (image)
public function count()
{
Contact::whereYear('created_at', 2021)
->orderBy('created_at')
->get()
->groupBy(function ($row) {
return $row->created_at->format('m');
})
->map(function ($day) {
// dd($day);
return $day->sum('q1a');
});
}
However I only get white blank page at my blade file.
My blade file(count.blade.php) is like this
<h3>{{ $q1a }}</h3>
Could you teach me correct code please?
And one thing When I try to sum I got this error
Warning: A non-numeric value encountered
some of column are not number so I would like to adjust
fix controller code.
WEB.php
//calc total amount page
Route::get('count', 'ContactsController#count');
[UPDATE]
I wrote below code using Dear OMR's answer
public function count()
{
Contact::whereYear('created_at', 2021)
->orderBy('created_at')
->select(['id','sno','s_date', DB::raw("MonthName(created_at)as monthName"), DB::raw('sum(q1a)')])
->groupBy(['id','sno','s_date', 'monthName', 'q1a'])->get();
}
count.blade.php code is below
#foreach ($values as $value)
{{ $value->sumQ }}
#endforeach
Here is current dd result

you can do it in DB stage, witch would be faster:
$values= Contact::whereYear('created_at', 2021)
->orderBy('created_at')
->select(['id','sno','s_date', DB::raw("MonthName(created_at)as monthName"), DB::raw('sum(q1a) as sumQ ')])
->groupBy(['id','sno','s_date', 'monthName'])->get();
note: any column you add it to select statement, should be also added in group by statement.

Related

Call to a member function count() - I have faced the issue for View page showing error

Please check the below code for view and controller.
Controller:
$staffreply = StaffReply::where('ticket_id', '=', $ticketID)->orderBy('id', 'asc')->get();
if ($staffreply->count()) {
//Get the data values
} else {
$staffreply = "";
$supportstaff = "";
$supportteam = "";
}
return view('pages/support/service-view',compact('data','staffreply','supportstaff','supportteam'));
View Page:
#if($staffreply->count())
#foreach($staffreply as $supportDesk)
<span>Posted on {{$supportDesk->created_date;}}</span>
#endforeach
#endif
Error:
Call to a member function count() on int (View: --\htdocs\laravel\project\resources\views\pages\support\service-view.blade.php)
How to solve the issue.
Even though it is not clear what $staffreply is. You can't use count() on non-Arrayables.
First make sure that $staffreply is in fact a collection in the controller. If not, the fallback in the else should probably equal an empty collection and not a 0. If so, in the view you wouldn't need to check if $staffreply->count().
Thanks for the support, after I have edited the view page code issue solved.
Edited Code
#if($staffreply != "")
#foreach($staffreply as $supportDesk)
<span>Posted on {{$supportDesk->created_date;}}</span>
#endforeach
#endif

Laravel 5.5 - Deep Relations calling by -->

I now spent hours googling and experimenting on trying to get an relation with two intermediate tables working.
My database looks like this:
(apt_id is apartment_id in real, was shorter to write)
I have every relation one away setup correctly with belongsTo and and hasMany:
EXAMPLE FROM House.php
public function user()
{
return $this->belongsTo('App\User');
}
public function apartments()
{
return $this->hasMany('App\Apartment');
}
Isn't there a way to access these relations like:
$house->apartments->tenants->entries
in Blade:
#foreach ( $house->apartments->tenants->entries as $entry )
, since I want to display all house entries on house.show (Blade View)
The only way it's working is by using a bunch of foreach inside each others... :/ and they define the order...
Using my wanted relation calling produces:
Property [tenants] does not exist on this collection instance.
displayed on the page.
Greetings,
Pat
I don't think you can achieve what you want using the code you posted, because when calling, for example, $house->apartments it returns a Collection object. So, it is not dealing with database anymore, that's why you would need to use a bunch of #foreachs.
I don't know if this is the best way to solve this, or if it will help you in your actual problem, but you could think this problem backwards and try something like this:
$entries = \App\Entry::whereHas('tenants', function($q) use ($house) {
$q->whereHas('apartments', function($q1) use ($house) {
$q1->where('apartments.house_id', $house->id);
});
})->get();
And in the view:
#foreach ($entries as $entry)
{{ $entry->tenant->apartment->house->name }}
#endforeach

Paginator on laravel 4.2

I am new to laravel and I am trying to get a pagination function into my result pages, so I have the following function to generate results from query and I would like to have a pagination on the results page, but I don't seem to get it work correctly
public function showResults()
{
$selectedquery = Input::get('Annonces');
$what = Input::get('what');
$where = Input::get('where');
$results = DB::table('annonces')->where($selectedquery,'LIKE', '%'.$what.'%')
->where('Lieu','LIKE', '%'.$where.'%')
->get();
return View::make('results',array('results' => $results));
}
Any Help?
Well, for one, you're missing the call to ->paginate(n). Right now, your closure is ->get(), which returns all results for your annonces table. This is good, but doesn't work for pagination. Change the function like so:
$results = DB::table('annonces')->where($selectedquery,'LIKE', '%'.$what.'%')
->where('Lieu','LIKE', '%'.$where.'%')
->paginate(10);
This will return all results grouped into 10 results per page. Feel free to change that as you see fit.
Lastly, somewhere on your view where you display the results, you will need to use this code to display a page-viewer:
<?php echo $results->links(); ?>
<!-- OR -->
{{ $results->links(); }}
Also, be sure to check out the docs on Laravel's pagination. You'll find it's pretty comprehensive!
Laravel Pagination
Hope that helps!

Laravel count column of related model

I want to count the number of upvotes and downvotes from ScripRating for a certain Script.
Script.php:
public function ratings()
{
return $this->hasMany('ScriptRating');
}
ScriptRating.php:
public function script()
{
return $this->belongsTo('Script');
}
The script_rating database table:
id (primary, increments)
script_id(integer)
rating(integer) <-- Can be either 1 (upvote) or -1 (downvote)
To retrieve a script and display the ratings:
$script = Script::where('title', '=', $title)->get();
{{ $script->ratings }}
This works fine, it returns an array: [{"id":1,"script_id":1,"rating":1}]. But at this point I'm stuck. How could I count the total upvotes and downvotes for a certain script?
I also have one more small question what I'm finding confusing. This does the same as the code above:
$script = Script::where('title', '=', $title)->with('ratings')->get();
{{ $script->ratings }}
What is the difference between these two methods and which one should I use?
Thanks in advance!
Edit
I made three scopes:
public function scopeTotalRating($query, $scriptId) {
return $query->where('script_id', $scriptId)->get()->sum('rating');
}
public function scopeThumbsUp($query, $scriptId) {
return $query->where('script_id', $scriptId)->having('rating', '=', 1)->get()->sum('rating');
}
public function scopeThumbsDown($query, $scriptId) {
return $query->where('script_id', $scriptId)->having('rating', '=', -1)->get()->sum('rating');
}
And display them as following:
{{ ScriptRating::thumbsUp($script->id) }}
You can use
{{ $script->ratings->count() }}
This will display the number total ratings a script has.
However what you're interested in doing is grouping the ratings into upvotes and downvotes, so you'll need to query your relationship by a group by clause.
Script::where('title', '=', $title)->with([
'ratings' => function($query) {
$query->groupBy('rating');
})
])->get();
I believe the collection returned should be now grouped by 1 and -1. Let me know of the results!
EDIT: You can also take a look here at the documentation on querying relationships:
http://laravel.com/docs/4.2/eloquent#querying-relations
EDIT for response:
The simplest way to do this without using group by would be separate queries:
$script = Script::where('title', $title)->first();
if ($script) {
$upvotes = ScriptRating::where('script_id', $script->id)->having('rating', '>', 0)->get()->count();
$downvotes = ScriptRating::where('script_id', $script->id)->having('rating', '<', 0)->get()->count();
}
Also the difference between your scripts mentioned is called eager loading or lazy loading. When you specify ->with() in your query, this is called eager loading. If you don't do this, the query will be ran when you specify $script->ratings
More about eager/lazy loading here:
http://laravel.com/docs/4.2/eloquent#eager-loading
Edit for another response:
You would use the ->whereHas('ratings') function if you want to gather scripts that only have ratings. You can also check the existence of the script having ratings by doing an if statement:
if ($script->ratings->count() > 0) {
// The script has ratings
} else {
// The script does not have ratings
}
If you don't want to keep repeating this code you could always put a function inside your Script.php model by using the following:
public function hasRatings()
{
return $this->ratings->count() > 0;
}
Then you can do:
if ($script->hasRatings())
You can add to the Script model class those 2 functions:
public function ratingsSumRelation()
{
return $this->hasOne('ScriptRating')->selectRaw('script_id, sum(rating) as sum_all')
->groupBy('script_id');
}
public function getRatingSumAttribute()
{
return $this->ratingsSumRelation ?
$this->ratingsSumRelation->sum_all: 0;
}
and now display sum using:
{{ $script->rating_sum }}

CodeIgniter Table Class: Add a Link From a Generated Cell

I'm using the table class that auto-generates a table for me from an array of data pulled from my database.
Model:
function get_reports_by_user_id($userid)
{
return $this->db->get_where('ss2_report',array('userid' => $userid))->result_array();
}
Controller:
function index()
{
echo $this->table->generate($this->mymodel->get_reports_by_user_id('1234'));
}
The controller will eventually be moved to a view when I have it working. This generates the table just fine, but I'd like to add a link to a field. For example, the id column that would allow me to link to a page of data for just that report's id. I know I can just output the table the old fashioned way by hand. I can then add whatever links I want, but I'd love to be able to use the auto-generation as much as possible. There's got to be a way to do something as common as linking a table cell. Does anyone have any ideas?
EDIT:
User Java PHP has it mostly right below. Here's the code that makes it work:
function get_reports_by_user_id($userid)
{
$rows = $this->db->get_where('ss2_report',array('userid' => $userid))->result_array();
foreach ($rows as $count => $row)
{
$rows[$count]['id'] = anchor('report/'.$row['id'],$row['id']);
}
return $rows;
}
I just needed to replace the value in the original array with the anchor text version.
The only way is, in the function get_reports_by_user_id() , you would loop through all the results and add the <a href> tag to the ids. Something like this:
function get_reports_by_user_id($userid)
{
$rows=$this->db->get_where('ss2_report',array('userid' => $userid))->result_array();
foreach ($rows as $row)
{
$row->id=anchor('site.com/some_controller/some_function/'.$row->id,$row->id);
}
return $rows;
}
I don't use CodeIgniter's database library so I'm not sure of what format it returns $rows in, but the code above should give you the general idea of what you need to do.
One idea might be to do something like..
foreach ($row in $this->mymodel->get_reports_by_user_id('1234'))
{
$row->id = anchor(site_url(array('report', 'user', $row->id)), $row->id);
$this->table->add_row($row);
}
$this->table->generate();

Resources