Laravel Eloquent Array Loop - php

I have an eloquent query that is returning a 'show', and any 'show_ref's relating to it:
Show::where('show_slug','=',$id)->with('showrefs')->firstOrFail();
This brings back a nested array successfully, as follows:
{
"show_id":2,
"show_name":"ShowNo1",
"show_logo":null,
"show_facebook_url":null,
"show_twitter_url":null,
"show_website_url":null,
"show_slug":"shown1",
"created_at":"2014-09-27 11:57:32",
"updated_at":"2014-09-27 11:57:32",
"showrefs":[
{
"show_ref":1,
"show_id":2,
"show_start_date":"2014-05-16",
"show_end_date":"2014-05-21",
"show_year":2014,
"show_common_name":"Mid May",
"venue_id":null,
"created_at":"2014-09-27 12:17:40",
"updated_at":"2014-09-28 06:26:54"
},
{
"show_ref":2,
"show_id":2,
"show_start_date":"2014-05-23",
"show_end_date":"2014-05-28",
"show_year":2014,
"show_common_name":"Late May",
"venue_id":null,
"created_at":"2014-09-27 12:21:24",
"updated_at":"2014-09-28 06:26:58"
},
{
"show_ref":4,
"show_id":2,
"show_start_date":"2013-02-12",
"show_end_date":"2013-02-13",
"show_year":2013,
"show_common_name":"Early February",
"venue_id":null,
"created_at":"2014-09-28 17:50:02",
"updated_at":"2014-09-28 17:50:02"
},
{
"show_ref":5,
"show_id":2,
"show_start_date":"2013-04-27",
"show_end_date":"2013-04-28",
"show_year":2013,
"show_common_name":"Late April",
"venue_id":null,
"created_at":"2014-09-28 17:50:42",
"updated_at":"2014-09-28 17:50:42"
}
]
}
What I am trying to get from my view is the following format:
ShowNo1 (show name)
2014
list of any shows in 2014
2013
List of any shows in 2013
Is there anyway this is possible from what I have coded so far? or have I gone about this the wrong way?
Thanks.

You have a showrefs function in your Show model somewhere that is defining this relationship. #Armon's answer will work, but will run on the order of O(n * years) where years is the number of years you want to show. Your example only has 2, but could be many more, and you can instead display your data in O(n) time.
You can orderBy in the methods defining relationships.:
// app/models/Show.php
public function showrefs()
{
return $this->hasMany('ShowRef')->orderBy('show_start_date', 'DESC');
}
If the tables you are joining together both contain a column which you want to order by, you may need to qualify the order by by appending the table name, as in:
->orderBy('`show_refs`.`show_start_date`', 'DESC')
After that, its just a matter of keeping track of the current year and noticing when it changes when looping over your data:
$show = Show::where('show_slug','=',$id)->with('showrefs')->firstOrFail();
$currentYear = '';
foreach($show->showrefs as $showref) {
$showRefYear = strtok($showref->show_start_date, '-');
if($currentYear != $showRefYear) {
$currentYear = $showRefYear;
// Output Year heading
}
// Output show details
}

Without knowing anything about Eloquent, you can use a simple function to walk through your nested array and collect your shows for a given year:
function collect_shows_with_year($shows, $year)
{
$result = array();
foreach($shows["showrefs"] as $show_ref)
{
if($show_ref["show_year"] == $year)
{
$result[] = $show_ref;
}
}
return $result;
}
$shows_in_2014 = collect_shows_with_year($shows, 2014);
$shows_in_2013 = collect_shows_with_year($shows, 2013);

Related

Laravel get rows from table using timestamp column

In my table, I have 2 columns:
1-count_of_h 2- updated_at
Now I want select rows which is past the updated_at, count_of_h hours.
A code like this:
$rows = Model::where('updated_at', '<', Carbon::now()->subHours($row->count_of_h))->get();
But I don't know how can I do it.
My code is kinda dirty ( but it works )
$arrayOfData = [];
Model::chunk(100, function($model) {
foreach($model as $m) {
if($m->updated_at < Carbon::now()->subHours($m->count_of_h)) {
$arrayOfData[] = $m;
}
}
});
First is make an array. After that, it will take every 100 rows then check if its past count_of_h hours

Graphic count based on the Month using Lavachart on laravel 5.2

Hello i get stuck on this proble, hope you guys can give me some advice to solve this matter. So, i want to show graph that count basen on month, how many keluhan (complain) on that month. so the table will be like january has 3 complain, febuary has 5 complain, etc (example)
public function lihatkeluhan(){
$halaman="tindaklayanan";
$keluhan_list=DB::table('keluhans')
->select(DB::raw('id,tanggal,produk,username,area,masalah,status'))->get();
$count = count($keluhan_list); //this still not count based on month
$population = Lava::DataTable();
$population->addDateColumn('Year')
->addNumberColumn('Keluhan')
->addRow(['?',$count]);
Lava::LineChart('Population', $population, [
'title' => 'Tahun : 2017',
]);
return view('layanankonsumen.daftarkeluhan',compact('halaman','keluhan_list','lava'));
}
try query like this.
it will gives you groupby result with count of that particular month,
no need for $count = count($keluhan_list); because you will get count in result.
$keluhan_list=DB::table('keluhans')
->select(DB::raw('id,tanggal,produk,username,area,masalah,status,count(*) as count'))
->get()
->groupBy(function($date) {
return Carbon::parse($date->created_at)->format('m'); // grouping by months
});

Laravel Eloquent: how to filter multiple and/or criteria single table

I am making a real estate related app and I've been having a hard time figuring out how to set up the query so that it would return "Only Apartments or Duplexes within selected areas" I'd like to user to be able to find multiple types of property in multiple selected quadrants of the city.
I have a database with a column "type" which is either "Apartment", "House", "Duplex", "Mobile"
In another column I have quadrant_main with values: "NW", "SW", "NE", "SE".
My code works when there is only 1 quadrant selected, but when I select multiple quadrants, I seem to get results which includes ALL the property types from the second or third or 4th quadrant, instead of only "Apartment" and "Duplex" or whatever types the user selects... Any help will be appreciated! thx in advance.
My controller function looks like this:
public function quadrants()
{
$input = \Request::all();
$currentPage = null;
$column = "price";
$order = "desc";
//
// Looks like the input is like 0 => { key: value } ...
// (an Array of key/value pairs)
$q = Listing::where('status','=','Active')->where(function($query) {
$input = \Request::all();
$currentPage = null;
$typeCount = 0;
$quadrantCount = 0;
foreach( $input as $index => $object ) {
$tempObj = json_decode($object);
$key = key((array)$tempObj);
$val = current((array)$tempObj);
if ( $key == "type" ) {
if ( $typeCount > 0 ) {
$query->orWhere('type', '=', $val );
}
else {
$query->where('type', '=', $val );
$typeCount++;
}
}
if ( $key == "quadrant_main" ) {
if ( $quadrantCount > 0 ) {
$query->orWhere('quadrant_main', '=', $val );
}
else {
$query->where('quadrant_main', '=', $val );
$quadrantCount++;
}
}
// else {
// $query->orWhere($key,$val);
// }
}
if( $currentPage ) {
//Force Current Page to Page of Val
Paginator::currentPageResolver(function() use ($currentPage) {
return $currentPage;
});
}
});
$listings = $q->paginate(10);
return $listings;
Looking at your question, its a bit confusing and not much is given to answer definitely. Probable causes of your troubles may be bad data in database, or maybe corrupted input by user.
Disclaimer: Please note that chances are my answer will not work for you at all.
In that case please provide more information and we will work things
out.
There is one thing that I think you have overlooked and thus you are getting awry results. First let me assume a few things.
I think a sample user input should look like this:
array(
0: '{type: Apartment}',
1: '{type: Duplex}',
2: '{quadrant_main: NW}',
3: '{quadrant_main: SW}',
)
What the user meant was give me any apartment or duplex which belongs in NW or SW region.
So after your loop is over, the final SQL statement should be something like this:
Oh and while we are at SQL topic, you can also log the actual
generated SQL query in laravel so you can actually see what was the
final SQL getting generated. If you can post it here, it would help a
lot. Look here.
select * from listings where status = 'Active' and (type = 'Apartment' or type = 'Duplex' and quadrant_main = 'NW' or quadrant_main = 'SW');
What this query will actually produce is this:
Select any listing which is active and:
1. Type is an apartment, or,
2. Type is a duplex, or,
3. Quadrant is SW, and,
4. Quadrant is NW
So assuming you have a database like this:
id|type|quadrant_main
=====================
1|Apartment|NW
2|Apartment|SW
3|Apartment|NE
4|Apartment|SE
5|Duplex|NW
6|Duplex|SW
7|Duplex|NE
8|Duplex|SE
9|House|NW
10|House|SW
11|House|NE
12|House|SE
You will only receive 1, and 5 in the result set. This result set is obviously wrong, plus it is depended on NW because that was the and condition.
The correct SQL query would be:
select * from listings where status = 'Active' and (type = 'Apartment' or type = 'Duplex') and (quadrant_main = 'NW' or quadrant_main = 'SW');
So structure your L5 app such that it produces this kind of SQL query. Instead of trying to cram everything in one loop, have two loops. One loop should only handle type and another loop should only handle quadrant_main. This way you will have the necessary and condition in the right places.
As a side note:
Never directly use user input. Always sanitize it first.
Its not a best practice to put all your logic in the controller. Use repository pattern. See here.
Multiple where clauses are generally applied via Criteria. Check that out in the above linked repository pattern.
You code logic is very complicated and utterly un-necessary. Instead of sending JSON objects, simply send the state of checkboxes. Don't try to generalize the function by going in loop. Instead handle all checkboxes one by one i.e. is "Apartments" selected, if yes, add that to your clause, if not, don't add.

laravel show "stats" ordered by date and counts

I want to show the stats of visitors on my website,
What I have:
AdminClontroller
public function index()
{
$select_stats = DB::table('visitor')->whereBetween('visit_date', array(date('Y-m-01'), date('Y-m-t')))->get();
$month = date('m');
$get_count = DB::select(DB::raw("SELECT count(*) FROM visitor WHERE MONTH(date) = $month GROUP BY DAY(date)"));
foreach($select_stats as $statics) {
//change our object to an array
$statics = array();
}
return View::make('admin.home.index')->with('stats', $select_stats)/*->with('count', $get_count)*/;
}
database model
View
var visitors = [
#foreach($stats as $stat)
['{{ date("d/m/Y", strtotime($stat->date)) }}', 55],
#endforeach
];
I want to get a stat like this:
But with the correct data from the database.
I want that I get the count of all IP's that visited my site on day 'x', and that for a month long.
So: on 2015-04-14 I got 20 visits, that is what I want to get, but looped in my template.
I hope you guys do understand me.
Kindest regards,

Only show todays news - Silverstripe

Hello Silverstripe Specialists!
I made the tutorial "extending a basic site"
(http://doc.silverstripe.org/en/tutorials/extending_a_basic_site)
That all worked very well so far.
I made this to show the latest news on the HomePage:
In HomePage.php:
// ...
public function LatestNews($num=5) {
$holder = ArticleHolder::get()->First();
return ($holder) ? ArticlePage::get()->filter('ParentID',
$holder->ID)->sort('Date DESC')->limit($num) : false;
}
And this in HomePage.ss:
// ...
public function LatestNews($num=5) {
$holder = ArticleHolder::get()->First();
return ($holder) ? ArticlePage::get()->filter('ParentID',
$holder->ID)->sort('Date DESC')->limit($num) : false;
}
That works very well!
Now my Question: All my News have a Date-Field. Is it possible to show only
the News of the current Date on the HomePage?
I tried this, but this wont work (Server Error) (Datum is my Date of the News):
public function LatestNews($num) {
$holder = ArticleHolder::get()->First();
return ($holder) ? ArticlePage::get()->filter('ParentID', "datum == CURDATE()",
$holder->ID)->sort('Date DESC')->limit($num) : false;
}
Thank you very much for your help!
filter() needs either two values (column and value) or an array of key-value pairs of what to filter. So if you want to filter for more than one thing you need an array as parameter:
$today = date('Y-m-d');
$todaysNews = ArticlePage::get()->filter(array(
'ParentID' => $holder->ID,
'datum' => $today
));
This will return a DataList you can sort and limit like you did in your example.
See also in docs:
Data Model and ORM general overview
Search filters how to filter "greater than" etc...
EDIT:
So a method in your controller could look like:
public function getTodaysNews($num=5) {
$holder = ArticleHolder::get()->First();
$today = date('Y-m-d');
return $holder
? ArticlePage::get()->filter(array(
'ParentID' => $holder->ID,
'datum' => $today
))->sort('Date DESC')->limit($num)
: false;
}

Categories