Laravel 5.4 pluck, where - laravel

I'm working on an assignment system for radio newscasts. Trying to return a view of all assignments for a particular newscast, and I'm stymied.
Tables
users table
id | name
---|-------
1 | Admin
2 | Susan
3 | Ed
4 | Jen
newscasts table
id | forStation_id | name
---|---------------|-----
1 | 1 | AM
2 | 1 | PM
3 | 2 | Sports
stations table
id | calls
---| -----
1 | JNDV
2 | YXWQ
assignments table
id | anchorId | newscastId | startDate | endDate | isTemp
---|----------|------------|-------------|-------------|--------
1 | 2 | 1 | 01 May 2017 | 31 Dec 2999 |
2 | 3 | 1 | 02 May 2017 | 06 May 2017 | True
3 | 4 | 2 | 01 Apr 2017 | 31 Dec 2999 |
4 | 3 | 3 | 01 Apr 2017 | 28 Apr 2017 |
(part of) Assignment model
public function anchor()
{
return $this->belongsTo(User::class, 'anchor_id')->withTrashed();
}
public function cast()
{
return $this->belongsTo(Newscast::class, 'cast_id')->withTrashed();
}
(part of) Newscast model
public function for_station()
{
return $this->belongsTo(Station::class, 'for_station_id')->withTrashed();
}
function getNameInputStationAttribute() {
return $this->for_station->calls . "-" . $this->name_input;
}
(part of) Assignment controller
/**
* Display all Assignments for one input name.
*
* #param int $name
* #return \Illuminate\Http\Response
*/
public function showAssignmentsByCastName($castName)
{
if (! Gate::allows('assignment_view')) {
return abort(403);
}
$relations = [
'anchors' => \App\User::get()->pluck('name', 'id'),
'casts' => \App\Newscast::with('for_station')->get()->pluck('name_input_station', 'id'),
'assignments' => \App\Assignment::with('cast')->get(),
];
dump($relations);
return view('assign.list', compact('castName') +$relations);
}
As I'd expect, this code returns the full collection of assignments.
Output
Anchor | Cast Name | Start Date | End Date
---------|-------------|-------------|-------------
Susan | JNDV-AM | 01 May 2017 | 31 Dec 2999
Ed | JNDV-AM | 02 May 2017 | 06 May 2017
Jen | JNDV-PM | 01 Apr 2017 | 31 Dec 2999
Ed | YXWQ-Sports | 01 Apr 2017 | 28 Apr 2017
I've tried several ways to limit the assignments to only one newscastId, thus far without success.
Desired Output for /assignment/list/JNDV-AM on 01 May 2017
Anchor | Cast Name | Start Date | End Date
---------|-------------|-------------|-------------
Susan | JNDV-AM | 01 May 2017 | 31 Dec 2999
Ed | JNDV-AM | 02 May 2017 | 06 May 2017
The shorter-term assignment is a temporary one (isTemp=True). During the days it is valid, it should be listed on top.
Desired Output for /assignment/list/JNDV-AM on 02 May 2017 through 06 May 2017
Anchor | Cast Name | Start Date | End Date
---------|-------------|-------------|-------------
Ed | JNDV-AM | 02 May 2017 | 06 May 2017
Susan | JNDV-AM | 01 May 2017 | 31 Dec 2999
I'm modifying code produced by an admin panel generator tool. It seems to me that querying for all users and all casts is not the most efficient way to go about it. I'd think, since I'm looking for only the current & future assignments for one newscast, that the anchors and casts relations should be filtered.
Basic question
What changes should I make to
'assignments' => \App\Assignment::with('cast')->get(),
to get only the assignments for JNDV-AM (newscastId = 1)?
Advanced Question
How do you recommend changing relations to return only the current and future assignments for JNDV-AM, today's assignment first, with the fewest queries possible?

You can pass a function into your with statement:
'assignments' => \App\Assignment::with(['cast' => function ($query) {
$query->where('newscastId', '=', 1);
}])->get()

Here is the working code I came up with:
(part of) Assignments controller
public function showAssignmentsByCastName($calls, $name_input)
{
if (!Gate::allows('assignment_view')) {
return abort(403);
}
$castName = strtoupper($calls). "-" . $name_input;
$station_id = \App\Station::where('calls', $calls)->get();
$station = \App\Station::findOrFail($station_id);
$cast_id = \App\Newscast::where([
['for_station_id', $station->id],
['name_input', $name_input]
])->get();
$cast = \App\Newscast::findOrFail($cast_id);
$relations = [
'anchors' => \App\User::get()->pluck('name', 'id'),
'casts' => \App\Newscast::where('cast_id', $cast->id),
'assignments' => \App\Assignment::where('cast_id', $cast->id)->get(),
];
return view('assign.list', compact('castName') + $relations);
}
web route
Route::get('assign/{calls}-{name_input}', 'AssignmentsController#showAssignmentsByCastName')->name('assign.list');

Related

Laravel GroupBy multiple columns with date

I have these fields in my table, I want get the data by month of the selected year & type_id, then SUM the amount on each month.
Ex: selectYear = 2019
Here is my account_table
id | type_id | amount | kind | created_at
1 | 2 | 200 | expense | 2019-01-15 10:14:31
2 | 2 | 400 | income | 2019-01-15 10:14:31
3 | 2 | 300 | expense | 2018-01-15 10:14:31
4 | 5 | 100 | expense | 2019-02-15 10:14:31
5 | 5 | 200 | income | 2019-03-15 10:14:31
this what I expected output.
if kind is expense the amount is -,
if kind is income the amount is +
Ex. on the month of Jan.
id 1 has 200 expense, and id 2 has 400 income
formula -200 + 400
Jan | Feb | Mar | ... so on
200 | 100 | 200 | ... so on
I hope I delivered and explain well, I am stuck on this functions, please I need help,
UPDATE.
Expected OUTPUT
Thanks in advance.
first, you must define or parse your year and month to numeric value. ex : January become 01, February become 02 etc.
in example :
$year = 2019;
$month = 01;
And you can use this :
$total = 0;
$data = DB::table('account_table')->whereMonth('created_at',$month)->whereYear('created_at',$year)->where('type_id',$type_id)->get;
foreach($data as $value){
if($value->kind == 'income'){
$total += $value->amount;
else{
$total -= $value->amount;
}
}
return $total;
Try following query on your account table:
Account::select(
DB::raw('SUM(IF(kind = "expense", amount * -1, amount)) as sum'),
DB::raw('YEAR(date) as year'),
DB::raw('MONTH(date) as month'),
)
->where('type', $type)
->where(DB::raw('YEAR(date)'), $selectYear)
->groupBy(DB::raw('MONTH(date)'));
You will get data like this:
[
[ sum: 400, year: 2020, month: 7, ]
[ sum: 500, year: 2020, month: 8, ]
...
]

Use a non-unique route key name?

We have rows which are sequenced and scoped to each organisation. So:
Processes tbl:
| id | org_id | sequence | name |
|---- |-------- |---------- |------------------- |
| 23 | 1 | 1 | New person |
| 56 | 1 | 2 | Person leaves |
| 84 | 1 | 3 | Person absent |
| 26 | 2 | 1 | Something happens |
| 34 | 2 | 2 | Something else |
| 77 | 2 | 3 | And another |
We do this so they can have a simple numbering system for their own records rather than a UUID, hash or something else. We prefer to have this in the url as well, so:
example.com/processes/1
Once logged in, we know their org_id, so for each query we can use org_id along with the sequence from the url.
Is there a clean laravel-esque kind of way to achieve this, maybe using the Model's getRouteKeyName?
I got the answer with some help from the laracasts forum:
/**
* Retrieve the model for a bound value.
*
* #param mixed $value
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value)
{
return $this->where('sequence', $value)
->where('org_id', /* however you get your org_id */)
->first() ?? abort(404);
}

How can i get all date even dates that don't have a record by eloquent with group by?

I have a method that get a month parameter to select rows of that month from users table. I want to show count of registered user for a month.
public function registeredUsersDaily($month)
{
$countOfDailyRegisteredUsersForAMonth = User::user()
->where(DB::raw('created_at'), '=', $month)
->groupBy('date')
->orderBy('date')
->get([
DB::raw('DATE(created_at) as date'),
DB::raw('COUNT(*) as count')
]);
dd($countOfDailyRegisteredUsersForAMonth);
}
It return count only for dates that exists in users table, so i want to have zero for dates that don't exists.
|date|count|
| 5 | 10 |
| 15 | 3 |
I want to have a result like this:
|date |count |
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 10 |
| 6 | 0 |
| 7 | 0 |
| 8 | 0 |
| 9 | 0 |
| 10 | 0 |
| 11 | 0 |
| 12 | 0 |
| 13 | 0 |
| 14 | 0 |
| 15 | 3 |
....
Please check out like this
$dateValues = array_column($countOfDailyRegisteredUsersForAMonth, "date");
$maxDate = max($dateValues);
$likeYouWant=[];
for ($i = 1; $i <= $maxDate; $i++)
{
$likeYouWant[] = ["date" => $i, "count" => in_array($i, $dateValues) ? $countOfDailyRegisteredUsersForAMonth[array_search($i, $dateValues)]["count"] : 0];
}
print_r($likeYouWant);
If you want default date than you can mention in that migration file or you can also do that in your model from where you can retrieve data when there is no date given by user.
You can also refer this for more
How to pass default values to controller by routing in Laravel 5?
From what I've got from the comments:
I think the best thing here is to count the number of users created each day of the month. This will get you zero's in case no one registered on a given date.
With this, you'd probably loop through the dates checking the total users registered each date.
For instance, let's try to get the users created the last 30 days from now:
$results = [];
$startOfDay = now()->createMidnightDate();
for($i=0; $i<=30; $i++)
{
$total_count = User::whereBetween('created_at', [$startOfDay->subDays($i-1), $startOfDay->subDays($i)])
->count();
array_push($results[ $startOfDay->subDays($i)->format('d')], $total_count);
}
With this I think you can now work with the results from the array.

mysql splitting a very big row to 4 columns at a time

Hi all im trying to scrape data from this website and enter it to my database
$html = file_get_html('http://www.matchmoney.com.gr/odds-comparison/');
using this code (php simple dom)
$table = $html->find('table', 2);
//OMADES
foreach($table->find('tr') as $fuck){
$one0= $fuck->find('td', 1)->plaintext;
$one1= $fuck->find('td', 2)->plaintext;
$one2= $fuck->find('td', 3)->plaintext;
$one3= $fuck->find('td', 4)->plaintext;
echo $one0." | ".$one1." | ".$one2." vs ".$one3."<br>";
ins1($DBHOST,$DBUSER,$DBPASS,$DBNAME,$TABLE_NAME,$one0,$one1,$one2,$one3);
}
what i want is like i echo it on php every 4 records and change row to insert it the same way to mysql, what happens now is all records are outputted on mysql in row1 while i want to insert it like row1,row2,row3,row4 then row1,row2 again etc
output on php is like this
13:05 | 799 | ΣΑΠΟΡΟ vs ΡΟΑΣΟ ΚΟΥΜΑΜΟΤΟ
14:30 | 800 | ΓΚΙΛΑΝΓΚ vs ΜΠΑΛΕΣΤΙΕ ΣΕΝΤΡΑΛ
18:00 | 801 | ΛΙΕΤΑΒΑ ΖΟΝΑΒΑ vs ΟΥΤΕΝΙΣ ΟΥΤΕΝΑ
18:30 | 802 | ΛΑΧΤΙ ΑΚΑΤΕΜΙΑ vs ΒΑΖΑΚΟΣΚΙ
18:30 | 803 | ΜΠΣ vs ΣΟΥΝΤΕΤ
18:30 | 2862 | ΧΟΛΒΙΚΕΝ vs ΕΡΓΚΡΙΤΕ
19:00 | 2855 | ΙΝΟΦΕΤ ΙΙ vs ΤΟΥΛΕΒΙΚ
on mysql i get
13:05 | 799 | ΣΑΠΟΡΟ vs ΡΟΑΣΟ ΚΟΥΜΑΜΟΤΟ | 14:30 | 800 | ΓΚΙΛΑΝΓΚ vs ΜΠΑΛΕΣΤΙΕ ΣΕΝΤΡΑΛ | 18:00 | 801 | ΛΙΕΤΑΒΑ ΖΟΝΑΒΑ vs ΟΥΤΕΝΙΣ ΟΥΤΕΝΑ | 18:30 | 802 | ΛΑΧΤΙ ΑΚΑΤΕΜΙΑ vs ΒΑΖΑΚΟΣΚΙ |18:30 | 803 | ΜΠΣ vs ΣΟΥΝΤΕΤ | 18:30 | 2862 | ΧΟΛΒΙΚΕΝ vs ΕΡΓΚΡΙΤΕ | 19:00 | 2855 | ΙΝΟΦΕΤ ΙΙ vs ΤΟΥΛΕΒΙΚ
all in row1 (without the |'s)
my insert function
function ins1($dbhost,$dbuser,$dbpass,$dbname,$table_name,$one1,$one2,$one3,$one4){
$conn=mysql_connect($dbhost,$dbuser,$dbpass) or die(mysql_error());
mysql_select_db($dbname) or die(mysql_error());
$sql=sprintf("INSERT INTO %s(id, time, team1, team2) VALUES('%s','%s','%s','%s')",
mysql_real_escape_string($table_name),
mysql_real_escape_string($id),
mysql_real_escape_string($time),
mysql_real_escape_string($team1),
mysql_real_escape_string($team2));
mysql_query($sql) or die(mysql_error());
mysql_close($conn);
}
thanks
got it solved it was my stupid mistake ignore the above cheers

Find Date and Time clashes

I'm having a hard time identifying booking clashes in my system. I've developed a booking system that integrates with our core system. The column data that is stored in my booking system is:
ResourceID, StartDate, EndDate, StartTime, EndTime
I need to ensure that when another user tries to book a resource, the resource is available. This question has been asked by many, but its usually with one date and start and end time or intersecting between a start date and enddate .
If I wanted to solely check on intersecting dates or time, the formula to use would be
a=existing_booking
b=new_booking
overlap = a.start < b.end && b.start < a.end;
I then found a really good and interesting post regarding overlapping resources containing both start time and end time Code Logic to prevent clash between two reservations but they deal with a reoccurring event over multiple days.
I need to ensure if a resource is booked between 8:50 to 22:00 from the 07-23-2016 to 07-29-2016 ; that someone trying to book on the 07-25-2016 to 07-25-2016 at 08:00 to 08:30 can't book it as it is booked out. After numerous searches I can't seem to find the formula for this, can anyone help post the algorithm or send me a link to an existing answer as its driving me nuts.
could you try the below logic?
01 if (new.StartDate > existing.EndDate OR new.EndDate < existing.StartDate) {
02 resource is available for booking
03 } else if (new.EndDate = existing.StartDate AND new.StartDate <= existing.StartDate) {
04 if (new.EndTime =< existing.StartTime OR new.StartTime >= existing.EndTime) {
05 resource is available for booking
06 } else {
07 resource is NOT available for booking
08 }
09 } else if (new.StartDate = existing.EndDate) {
10 if (new.StartTime >= existing.EndTime) {
11 resource is available for booking
12 } else {
13 resource is NOT available for booking
14 }
15 } else {
16 resource is NOT available for booking
17 }
lets check on a case to case basis;
pass - resource is available
fail - resource is NOT available
An existing booking is in place
ResourceID | StartDate | EndDate | StartTime | EndTime
ID1234 | 07-23-2016 | 07-29-2016 | 08:50 | 22:00
Case 1
ResourceID | StartDate | EndDate | StartTime | EndTime
ID1234 | 07-25-2016 | 07-25-2016 | 08:00 | 08:30
result - this case would fail; #line 16 in the code above
Case 2
ResourceID | StartDate | EndDate | StartTime | EndTime
ID1234 | 07-23-2016 | 07-23-2016 | 08:00 | 08:30
result - this case would pass; #line 05 in the code above
Case 3
ResourceID | StartDate | EndDate | StartTime | EndTime
ID1234 | 07-29-2016 | 07-29-2016 | 22:01 | 22:30
result - this case would pass; #line 11 in the code above
Case 4
ResourceID | StartDate | EndDate | StartTime | EndTime
ID1234 | 07-23-2016 | 07-23-2016 | 09:00 | 11:30
result - this case would fail; #line 07 in the code above
Please do check and let me know if for any case the above logic would be giving an in correct answer.

Resources