Всем привет, написал свой небольшой проект на Laravel.
Можно ли от вас ребята получить небольшую обратную связь по моему первому коду в Laravel? По каким-то банальным моментам что то может не так сделал?
Основной код у меня в тут в модели User
<?php
namespace App;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
class User extends Model
{
protected $table = 'timetable_users';
protected $fillable = [
'user_id', 'morning_work_hours_from', 'morning_work_hours_before', 'afternoon_work_hours_from', 'afternoon_work_hours_before',
];
public function holiday()
{
return $this->hasMany(Holiday::class);
}
public function party()
{
return $this->hasMany(Party::class);
}
// Получение графика отпусков сотрудника
public function getHolidays($id)
{
$holidays = DB::table('timetable_holidays')
->where('user_id', '=', $id)
->get();
return $holidays;
}
// Получение праздников России с названием
public function NameHolidaysRu()
{
$apiDate = json_decode(file_get_contents('https://www.googleapis.com/calendar/v3/calendars/russian__ru%40holiday.calendar.google.com/events?key=AIzaSyC8khrJO57yl4szjLOuyQrlW7R_CKgwaH0'), 1);
$holidayDates = Arr::pluck($apiDate['items'], 'start.date');
$nameHolidayDates = Arr::pluck($apiDate['items'], 'summary');
$count = count($holidayDates);
$dateAndName = array();
for ($i = 0; $i < $count; $i++)
{
$dateAndName[] = [
"date" => $holidayDates[$i],
"name_holiday" => $nameHolidayDates[$i]
];
}
return $dateAndName;
}
// Получение праздников России
public function getApiHolidays()
{
$apiDate = json_decode(file_get_contents('https://www.googleapis.com/calendar/v3/calendars/russian__ru%40holiday.calendar.google.com/events?key=AIzaSyC8khrJO57yl4szjLOuyQrlW7R_CKgwaH0'), 1);
$holidayDates = Arr::pluck($apiDate['items'], 'start.date');
$array = array_filter($holidayDates, function ($var) {
return substr($var, 0, 4) === date("Y");
});
return $array;
}
// Получение периода дат из формы
public function getPeriodDateForm($startDate, $endDate)
{
$startDate = new Carbon($startDate);
$endDate = new Carbon($endDate);
$allDates = array();
while ($startDate->lte($endDate)) {
$allDates[] = $startDate->toDateString();
$startDate->addDay();
}
return $allDates;
}
// Добавление отпускных дат сотрудника в массив
public function getDateHolidayArr($holidaysEmployee)
{
$allHolidays = array();
$count = count($holidaysEmployee);
if ($count == 0)
{
return $allHolidays;
}
for ($i = 0; $i < $count; $i++)
{
$holidaysFrom = $holidaysEmployee[$i]->holidays_from;
$holidaysBefore = $holidaysEmployee[$i]->holidays_before;
$startDate = new Carbon($holidaysFrom);
$endDate = new Carbon($holidaysBefore);
while ($startDate->lte($endDate)) {
$allHolidays[] = $startDate->toDateString();
$startDate->addDay();
}
}
return $allHolidays;
}
// Получение дат праздников которые будут удалены
public function delPartyDays()
{
$getAllParties = $this->allParties();
$allTotalParties = array();
$count = count($getAllParties);
if ($count == 0) {
return $allTotalParties;
}
for ($i = 0; $i < $count; $i++) {
$partiesFrom = $getAllParties[$i]['party_day_from'];
$partiesBefore = $getAllParties[$i]['party_day_before'];
$startDate = new Carbon($partiesFrom);
$endDate = new Carbon($partiesBefore);
while ($startDate->lte($endDate)) {
$allTotalParties[] = $startDate->toDateString();
$startDate->addDay();
}
}
$firstDate = Arr::pluck($getAllParties, ['party_day_from']);
$resultDate = array_diff($allTotalParties, $firstDate);
return $resultDate;
}
// Получение выходных дней
public function weekend($startDate, $endDate)
{
$start = strtotime($startDate);
$end = strtotime($endDate);
$result = array();
while ($start <= $end)
{
if (date('N', $start) >= 6)
{
$current = date('Y-m-d', $start);
$result[] = $current;
} $start += 86400;
}
return $result;
}
// Получение расписания работника
public function calculate($id, $startDate, $endDate)
{
$periodDateForm = $this->getPeriodDateForm($startDate, $endDate);
$holidaysEmployee = $this->getHolidays($id);
$allDateHolidaysEmployee = $this->getDateHolidayArr($holidaysEmployee);
$allRuHolidays = $this->getApiHolidays();
$allPartyDays = $this->delPartyDays();
$allWekend = $this->weekend($startDate, $endDate);
return array_diff($periodDateForm, $allDateHolidaysEmployee, $allRuHolidays, $allPartyDays, $allWekend);
}
// Получение всех праздников компании
public function allParties()
{
$parties = Party::get();
$subset = $parties->map(function ($party) {
return $party->only(['name', 'party_day_from', 'party_day_before', 'party_time_from', 'party_time_before']);
});
return $subset;
}
// Формат даты для view
public function formatDate($date)
{
return date('d.m.Y', strtotime($date));
}
// Проверка даты в JSON
public function checkDateJson($s)
{
$allParties = $this->allParties();
foreach ($allParties as $party) {
$dateTimeParties = Arr::only($party, ['party_day_from', 'party_time_from']);
if ($s === $dateTimeParties['party_day_from']) {
$s = $dateTimeParties;
}
}
return $s;
}
// Поления первых дат праздников компании
public function partyDateJson($s)
{
$allParties = $this->allParties();
$allDate = Arr::pluck($allParties, 'party_day_from');
if (is_array($s) && in_array($s['party_day_from'], $allDate))
{
return $s['party_day_from'];
} else {
return $s;
}
}
// Максимальное время первой половины дня
public function maxMorningHour()
{
$maxMorningHour = DB::table('timetable_users')
->max('morning_work_hours_before');
return $maxMorningHour;
}
// Время для JSON с учетом праздников
public function partyTimeJson($s, $range)
{
if (!is_array($s))
{
return $range;
}
else {
foreach ($range as $val)
{
if ($s['party_time_from'] < $val['end']
&& $s['party_time_from'] > $val['start']
&& $this->maxMorningHour() > $s['party_time_from'])
{
$range = [
['start' => $this->morning_work_hours_from, 'end' => $s['party_time_from']],
];
return $range;
break;
}
elseif ($s['party_time_from'] < $range[1]['end']
&& $s['party_time_from'] > $range[1]['start'])
{
$range = [
['start' => $this->morning_work_hours_from, 'end' => $this->morning_work_hours_before],
['start' => $this->afternoon_work_hours_from, 'end' => $s['party_time_from']]
];
return $range;
break;
}
return $range;
}
}
}
// Получить JSON
public function getJSON($shedule)
{
$range = [
['start' => $this->morning_work_hours_from, 'end' => $this->morning_work_hours_before] ,
['start' => $this->afternoon_work_hours_from, 'end' => $this->afternoon_work_hours_before]
];
$data = array_map(function($s) use ($range){
return [
'day' => $this->partyDateJson($this->checkDateJson($s)),
'timeRangers' => $this->partyTimeJson($this->checkDateJson($s), $range)
];
}, $shedule);
$result = ['schedule' => $data];
return json_encode($result, JSON_PRETTY_PRINT);
}
}
Небольшой контроллер
<?php
namespace App\Http\Controllers;
use App\Holiday;
use App\Party;
use App\User;
use Illuminate\Http\Request;
class TimetableController extends Controller
{
public function index()
{
$countUser = User::All()->count();
return view('timetable', compact('countUser'));
}
public function store(Request $request)
{
$rules = [
'userId'=>'required|integer|exists:timetable_users,id',
'startDate' => 'required|date',
'endDate' => 'required|date|after:startDate'
];
$this->validate($request, $rules);
$id = $request['userId'];
$startDate = $request['startDate'];
$endDate = $request['endDate'];
$user = User::findOrFail($id);
$holidays = Holiday::findOrFail($id)->where("user_id", $id)->get()->sort();
$parties = Party::all();
$countUser = User::All()->count();
$calculate = $user->calculate($id, $startDate, $endDate);
return view('timetable', compact('holidays', 'user', 'countUser', 'parties', 'calculate'));
}
}
И вид
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts-->
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<hr>
<h2>Расписание работника компании</h2>
<hr>
<h5>В вашей компании работает {{ $countUser }} сотрудников</h5>
<hr>
@if(count($errors) > 0)
<div class="alert alert-danger">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<br>
<form method="get" action="{{ route('timetable.store') }}">
<div class="row align-items-end">
<div class="form-group col">
<label>ID user</label>
<input type="text" name="userId" class="form-control" placeholder="Name" value="{{ old('userId') }}" id="userId">
</div>
<div class="form-group col">
<label>Дата, от</label>
<input type="date" name="startDate" class="form-control" value="{{ old('startDate') }}" id="start_date">
</div>
<div class="form-group col">
<strong>Дата, до</strong>
<input type="date" name="endDate" class="form-control" value="{{ old('endDate') }}" id="end_date">
</div>
<div class="form-group col">
<button class="btn btn-success btn-submit">Расчитать</button>
</div>
</div>
</form>
<br>
<br>
<hr>
<br>
@if ($user ?? '')
<div class="row">
<div class="col-6">
<h5 class="font-weight-bolder">Информация о работнике:</h5>
<table class="table mt-5">
<thead>
</thead>
<tbody>
<tr>
<td scope="row">IdUser</td>
<td>{{ $user->id }}</td>
</tr>
<tr>
<td scope="row">График работы:</td>
<td>c {{ $user->morning_work_hours_from }} до {{ $user->morning_work_hours_before }} <br>
c {{ $user->afternoon_work_hours_from }} до {{ $user->afternoon_work_hours_before }}
</td>
</tr>
<tr>
<td scope="row">Отпуск:</td>
<td>
@if($holidays->count() == 0)
У данного сотрудника отпуск не указан
@else
@foreach ($holidays as $holiday)
от {{ $user->formatDate($holiday->holidays_from) }} до {{ $user->formatDate($holiday->holidays_before) }} <br>
@endforeach
@endif
</td>
</tr>
</tbody>
</table>
<br>
<table class="table mt-5">
<thead>
<tr>
<th scope="col">Праздник компании</th>
<th scope="col">Начало</th>
<th scope="col">Окончание</th>
</tr>
</thead>
<tbody>
@foreach ($parties as $party)
<tr>
<td>{{ $party->name }}</td>
<td>{{ $user->formatDate($party->party_day_from) }} {{ $party->party_time_from }}</td>
<td>{{ $user->formatDate($party->party_day_before) }} {{ $party->party_time_before }}</td>
</tr>
@endforeach
</tbody>
</table>
<br>
<table class="table mt-5">
<thead>
<tr>
<th scope="col">Праздники России за 2019</th>
<th scope="col">Дата</th>
</tr>
@foreach ($user->NameHolidaysRu() as $rusHoliday)
<tr>
@if ($rusHoliday['date'] > date("Y") && $rusHoliday['date'] < date('Y', strtotime('+1 years')))
<td> {{ $rusHoliday['name_holiday']}} </td>
<td> {{ $user->formatDate($rusHoliday['date']) }} </td>
@endif
</tr>
@endforeach
</thead>
</table>
</div>
<div class="col-6">
<h5 class="font-weight-bolder">JSON</h5>
<p>Выходные дни не учитываются</p>
<pre>
{{ $user->getJSON($calculate) }}
</pre>
</div>
</div>
@endif
</div>
</body>
</html>
Буду рад любым комментариям
PS на выходе то что требовалось реализовать по ТЗ все сделал, все работает.
Вся логика у вас в модели User. Это неверно, в модели должна быть только логика обработки полей модели.
Логику работы со сторонним сервисом лучше вынести в отдельный класс(например сервис GoogleApiService)
Логику выборок лучше вынести в отдельный класс, например UserRepository и реализовать в нем метод getUserHolidays()
Метод преобразования даты $user->formatDate($holiday->holidays_from) должен быть в модели Holiday
public function getFormatDate(): string
{
return date('d.m.Y', strtotime($this->holidays_from));
}
Часть методов у вас с префиксом get(getHolidays), часть без(weekend, хотя тоже что то возвращает), часть с большой буквы(NameHolidaysRu) - надо определиться с неймингом.
Вместо кострукции
DB::table('timetable_holidays')->where('user_id', '=', $id)->get();
Лучше использовать
Holiday::query()->where('user_id', '=', $id)->get();
Чтобы не дублировать название таблицы, которое и так указано в модели.
Значения типа адреса сервиса https://www.googleapis.com/calendar/v3... и его параметры лучше вынести в конфиг(.env)
Не используйте название переменных, которые поймете только вы
public function partyDateJson($s)
Используйте type hinting
Валидацию в контроллере лучше вынести в Form Request https://laravel.com/docs/5.8/validation#form-request-validation
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Всем привет, я примерно 6-7 работаю бэкенд разработчиком, всегда писал на чистом php, работаю только с какими-то библиотеками из packagistНачал изучать...