Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Нужна подсказка как это лучше реализовать.
Есть blade страница с формой для отправки данных. В форме есть кнопка для динамического добавления полей. По сути передаются массивы данных. Я им даю нейм типа такого:
name="sections[0].list_items[0]"
Данные передаю не аяксом, а обычным сабмитом. Если валидацию не проходит, после 302 редиректа, заполняю форму старыми данными. Но есть проблема.
После редиректа пропадают все динамически созданные поля, т.к. я их создаю скриптом. Можно ли как-то после этого редиректа получить доступ ко всем отправленным данным чтобы в цикле прорисовать все айтемы (тем же js), которые были добавлены динамически? Хотя тогда мне не удастся использовать blade функцию old(). Или же может эти поля можно как-то восстановить средствами blade, но тогда нужно как-то в ГЕТ запрос на редирект (который срабатывает автоматически если есть ошибка валидации) передать все эти поля.
В общем подскажите, как это сделать грамотно. А то лезут в голову какие-то костыльные идеи типа использования кукиз или хедеров для редиректа.
Я кстати смотрел что лежит в $request уже на входе в контроллер по редирект - там уже нет данных из формы. И в принципе это логично, т.к. форма отправляет пост запрос из данными в бади, а при ошибке валидации редирект срабатывает на гет, и у него уже нет бади.
Есть таблица departments со списком отделов
В таблице users указаны айдишники этих отделов.
С фронта приходит не айдишник отдела, а его название.
Чтобы записать данные, в таблицу users, я должен узнать айди этого департамента.
Как я это сделал: просто беру сначала одним запросом узнаю айди департамента, а затем подставляю его при записи данных в таблицу users. Ну и метод по определению айди департамента я вынес в трейты, т.к. будет использоваться во многих местах.
Вопрос: может есть какое-то более красивое решение? Представьте, что кроме этого по аналогии нужно получать и подставлять айдишники языков, стран и т.п. Код получается какой-то громоздкий. Может можно как-то в данном случае заюзать рилейшены? Подкиньте идею как бы это делали вы?
В FormFequest заходят данные с фронта в виде:
paramA[0][type]=type1
paramA[0][question]=q
paramA[1][type]=type2
paramA[1][question]=q
paramB[0][type]=type3
paramB[0][question]=q
paramB[1][type]=type4
paramB[1][question]=q
Я могу их провалидировать примерно так:
paramA.*.type => 'required'
Но есть ньюанс. Мне нужно проверить обязательность наличия параметра в зависимости от конкретного значения параметра type в пределах каждой группы обьектов. На примере у меня их 4: paramA[0], paramA[1], paramB[0], paramB[1]. Т.е. в пределах каждой из 4х этих наборов данных нужно проверить значение type. Если оно такое как ожидается, значит параметр question обязательный.
Как это можно реализовать?
Я знаю что есть required_if, но как это увязать с тем, что у нас несколько наборов данных?
Работаю над проектом, на котором ожидаются миллионы юзеров. Соответственно будет огромная нагрузка на БД. Соответственно, необходимо зараньше подумать о производительности и количестве запросов к БД.
Подскажите кто знает, где по производительности проседает eloquent? Где он делает лишние запросы? Какие слабые места? Что вы используете вместо него и в каких кейсах? Буду благодарен любой информации.
Ошибку нашел. Не правильно передавал параметры в конструктор. Все заработало.
@artoodetoo ,
Кстати, если так:
dd("111");
dispatch(new CreateIssue($headers, $body));
То я получаю вывод на экран 111
А если так:
dispatch(new CreateIssue($headers, $body));
dd("222");
то не получаю.
На всякий случай приведу весь код контроллера:
class MainController extends Controller
{
public function index(Request $request){
$url = $request->request->get('url');
if (!empty($url)) {
$doc = hQuery::fromUrl($url,
['user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36']
);
try {
$errors = $doc->find('#results > ol > li');
if ( $errors ) {
foreach($errors as $error) {
$text = $error->find('span')[0]->text;
$iBody = ([
"summary" => $text,
'custom_fields' => '',
'tags' => '',
]);
$body = json_encode($iBody);
$headers = [
'Authorization' => '1111111111111111111111111111111',
'Content-Type' => 'application/json',
];
dispatch(new CreateIssue($headers, $body));
}
}
} catch (\Exception $e) {
}
}
return dd('Empty URL');
}
}
А в .env у тебя упоминается QUEUE_DRIVER ?
Да, там тоже: QUEUE_DRIVER=database
Миграции выполнил (если драйвер для базы) ?
Миграции выполнил, обе таблицы есть: jobs и failed_jobs.
Кстати, логи тоже пустые (storage\logs). Хотя отладка в .env включена.
Использую последний ларавель.
Создал джобу на отправку POST запроса на внешний ресурс
public function handle()
{
$this->client->request('POST', 'https://.....', [
'body' => $this->body, 'synchronous' => true
]);
}
public function __construct($headers, $body)
{
$this->body = $body;
$this->client = new GuzzleClient([
'headers' => $headers
]);
}
Настроил очереди и БД:
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=sitech
DB_USERNAME=sitech
DB_PASSWORD=sitech
database.php
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
],
queue.php
'default' => env('QUEUE_DRIVER', 'database'),
'connections' => [
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
],
Выполнил миграции для очередей
В контроллере вызываю:
dispatch(new CreateIssue($headers, $body));
Что интересно, dispatch находится в цикле. После первого выполнения dispatch следующая итерация цикла не начинается. Если dispatch закомментировать цикл выполняется.
Что здесь не так?
Какой у вас менеджер очередей в в config/queue стоит
В точку )))
На локалке под open server настроил отложенные задачи без задержки по времени. Если воркер не запущен, вижу как в БД падают отложенные задачи в таблицу jobs. Включаю воркер - отложенные задачи отрабатывают, рассылка на почту и в телеграмм идёт.
То же самое развернул на удаленном vps, Debian 9. Супервизор не установлен, воркер не запущен, но рассылка отправляется даже не попадая в таблицу jobs. Как такое может быть? По идее без супервизора и запущенного воркера джоба должна просто записаться в БД в очередь и все. А она отрабатывает сразу. Подскажите плз.
Ларавель последний.
Разобрался. Что-то неправильно делал перед этим. На самом деле все предельно просто:
$role->attachPermissions($permissions);
Использую Laratrust для работы с ролями. В принципе кажется понял что к чему и как с ним работать. Через сидеры заполняю таблицы:
users
roles
permissions
role_user
permission_user
Таблицы role_user и permission_user заполняю так:
$user->attachPermissions($permissions);
$user->attachRoles($role);
Но не могу заполнить таким же образом таблицу permission_role. Как это сделать?
Использую Eloquent при обращении к БД. Метод в модели:
public static function lastreport(){
$lastReport = DayReport::with('elementary')
->orderBy('id', 'DESC')
->where("username", "=", Auth::user()->name)
->first();
return $lastReport;
}
Обращаюсь к нему из контроллера:
dd(DayReport::lastReport()->toArray());
Хочу вытащить резутаты и отправить их в виде массива или json клиенту, там js это дело распарсит и отобразит на странице. Но когда добавляю toArray(), то получаю ошибку "InvalidArgumentException Trailing data". Если нет toArray(), то во вложенной структуре вижу интересующие меня данные связанных таблиц.
Как устранить ошибку или как лучше отправить джаваскрипту данные иным способом?
Да, это то, что нужно. Спасибо большое!
С чего ты взял?
По двум причинам:
Во-первых это нелогично т.к. я уже писал об этом выше:
А иначе откуда мне знать какой айдишник туда проставить? Если я этот айдишник буду проставлять самостоятельно, то теряется весь смысл использования Отношений в ларавеле.
Во-вторых потому, что об это так написано в документации на этом сайте:
https://laravel.ru/docs/v5/eloquent-relationships
Можно найти поиском по: "Метод save() автоматически добавит надлежащее значение post_id в новую модель"
@Morry, если знаешь как устранить ошибку - подскажи. А не знаешь - нечего мозги парить встречными вопросами, т.к. они не наталкивают на подсказку, т.к. бессмысленны.
А как Ларавелю узнать, к какой записи в таблице day_reports ты хочешь привязать запись из таблицы elementary_reports ?
Так я это указал Ларавелю в методе модели:
public function elementaryReports()
{
return $this->hasMany('App\ElementaryReport', 'day_reports_id', 'id');
}
И для самой БД указал в миграциях:
$table->foreign('day_reports_id')->references('id')->on('day_reports');
Может каким-то образом это еще нужно указать здесь для каждого нового обьекта ElementaryReport:
$dayReport->elementaryReports()->saveMany([
new ElementaryReport(['type' => 'Рабочее время', 'project' => 'Рабочее время', 'subproject' => 'Рабочее время', 'report' => 'Рабочее время', 'time' => 5]),
new ElementaryReport(['type' => 'Рабочее врем2', 'project' => 'Рабочее врем2', 'subproject' => 'Рабочее врем2', 'report' => 'Рабочее врем2', 'time' => 6]),
]);
Но не указывать же какое конкретно значение айдишника писать? Оно должно автоматически инкрементироваться. Что-то я либо упустил, либо недопонял. Подскажите как исправить косяк.
А значение и не должно само подставляться. Ты должен сам указать, что вставлять
Как сам, это же ключ, который связан с автоинкрементным полем. Там автоматом проставляется айдишник, который должен также проставляться и в 'day_reports_id'. Т.е. у меня добавляется одна запись в таблицу 'day_reports' и несколько записей в таблицу 'elementary_reports', которые привязаны внешним ключем 'day_reports_id' к полю 'id' таблицы 'day_reports'. Т.е. значение должно браться оттуда. А инаже откуда мне знать какой айдишник туда проставить? Если я этот айдишник буду проставлять самостоятельно, то теряется весь смысл использования Отношений в ларавеле. Поправьте если ошибаюсь (а где-то я все же ошибаюсь).
Получаю ошибку:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'day_reports_id' cannot be null (SQL: insert into `elementary_reports` (`type`, `project`, `subproject`, `report`, `time`, `day_reports_id`, `updated_at`, `created_at`) values (Рабочее время, Рабочее время, Рабочее время, Рабочее время, 5, , 2018-08-20 21:04:51, 2018-08-20 21:04:51))
Суть ее ясна, но почему автоматически не подставляется нужный id из связанной таблицы ума не приложу..
Миграции:
Schema::create('day_reports', function (Blueprint $table) {
$table->increments('id');
$table->text('username');
$table->timestamps();
});
Schema::create('elementary_reports', function (Blueprint $table) {
$table->increments('id');
$table->integer('day_reports_id')->unsigned();
$table->foreign('day_reports_id')->references('id')->on('day_reports');
$table->text('type');
$table->text('project');
$table->text('subproject')->nullable();
$table->text('report');
$table->double('time');
$table->timestamps();
});
Контроллер:
$dayReport = new DayReport();
$dayReport -> username = Auth::user()->name;
$dayReport->elementaryReports()->saveMany([
new ElementaryReport(['type' => 'Рабочее время', 'project' => 'Рабочее время', 'subproject' => 'Рабочее время', 'report' => 'Рабочее время', 'time' => 5]),
new ElementaryReport(['type' => 'Рабочее врем2', 'project' => 'Рабочее врем2', 'subproject' => 'Рабочее врем2', 'report' => 'Рабочее врем2', 'time' => 6]),
]);
Модель:
class DayReport extends Model
{
public function elementaryReports()
{
return $this->hasMany('App\ElementaryReport', 'day_reports_id', 'id');
}
Что здесь не так?
Беру относительный путь к картинке из базы и в blade проверяю - если ссылка есть, то сделать ее абсолютной и вставить в код. Если нет, то пишем тоже абсолютную, но ту, которая по дефолту.
<img src="@if (isset($config['image_name'])) {{asset($config['image_name'])}} @else {{asset('img/einstein-cut.png')}} @endif" />
Второй кейс работает - ссылка абсолютная. А в первом случае - почему-то относительная, т.е. asset не срабатывает. Что здесь не так?
Установил последнюю версию Ларавель. Все это добро заняло 37,5Мб. Это конечно не много, но у меня много мелких проектов, которые приходится бекапить на сервере. В сумме их размер уже достаточно солидный. Регулярное архивирование бекапов загружает и без того загруженную систему, а отправка бекапов по фтп еще и загружает сеть, которая всего-навсего 10Мб/сек. Ясное дело, что тариф нужно поднимать, но хотелось бы спросить у опытных людей...
1) Можно ли, и не бредовая ли это идея изначально - попытаться почистить ларавель и оставить в нем только базовые какие-то библиотеки? Дело в том, что я вешаю на него одностраничный функционал всего с парочкой скриптов и загрузкой файлов через интерфейс, который в принципе работает и так - без Ларавеля. Просто в целях безопасности хочу сделать через единую точку входа. Скорее всего более опытные в этом деле ребята не ставили бы для этого Ларавель, а просто правильно бы сконфигурировали те несколько папок и файлов своего маленького проета - и все на этом.
2) Есть проекты, где я ставил дополнительные библиотеки и таких библиотек уже достаточно много. Но не все их я по итогу использую. Можно ли как-то определить какие из сторонних библиотек я могу смело удалить?
Просто хотел услышать ваше мнение на этот счет. Спасибо!
Использую OpenServer со следующими настройками:
HTTP: Apache php-7
PHP: php-7.0
Mysql 5.7
Redis 3.2
Установлен "laravel/framework": "5.5.*"
На локалхосте отправка почты через gmail-аккаунт работает без проблем. Конфиг:
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=...myemail...
MAIL_PASSWORD=...mypassword...
MAIL_ENCRYPTION=tls
Перенес проект на удаленный сервер - почта не работает. Работаю на Debian под VestaCP. Сама VestaCP успешно отправляет свои письма. Значит mail-сервер настроен. Подскажите в какую сторону копать? Искать в документации Ларавеля, или в документации VestaCP, или независимо от Vesta и Ларавеля поднимать/настраивать свой sendmail на Debian?
Система автоматически делает бекапы в виде tar.gz архивов. Мне нужен инструмент, который сможет, например, каждый день отправлять новые бекапы на гугл-диск и по возможности - удалять старые. Но удаление не так важно, главное уметь пушить бекапы.
Какая баблиотека подойдет для такой задачи?
У меня последний ларавель.
Для наглядности попробуй database драйвер
А можно не возиться с установкой redis На удаленной машине, а просто использовать database драйвер? Так тоже работает. Или здесь есть какие-то недостатки по сравнению с редисом? Резонный вопрос, т.к. БД уже и так установлена, а РЕДИС еще придется ставить на убунту. Зачем делать больше )))
(я надеюсь ты сам воркер запустил)
В точку! Я не правильно понял значение команды queue:work. Я думал, его нужно запускать если хочешь наглядно увидеть работу воркера не дожидаясь установленного времени. Только походу без супервизора мне не обойтись. Странно, что РЕДИС в опенсервере есть, а супервизора нет. Сейчас буду разбираться как ставить супервизор на винду или в опенсервер.
Использую OpenServer со следующими настройками:
HTTP: Apache php-7
PHP: php-7.0
Mysql 5.7
Redis 3.2
Установлен "laravel/framework": "5.5.*"
Это в контроллере
$job = (new GetGuestInfo())->delay(Carbon::now()->addMinutes(1))->onConnection('redis');
dispatch($job);
Также пробовал убрать onConnection('redis')
И так пробовал
$date = Carbon::now()->addMinutes(1);
Queue::later($date, new GetGuestInfo());
Это в .env
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=redis
Таблица jobs добавлена через миграции
Это установил через композер
"predis/predis": "^1.1",
Это в queue.php
'default' => env('QUEUE_DRIVER', 'redis'),
'connections' => [
...
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => 'default',
'retry_after' => 90,
],
],
В самом задании GetGuestInfo.php
.......
public function __construct()
{
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$allData = new All();
$allData -> name = "";
$allData -> email = "";
$allData -> position = "";
$allData -> message = "";
$allData -> ip = "ip";
$allData -> country = "country";
$allData -> department = "department";
$allData -> city = "city";
$allData -> index = "index";
$allData -> lattitude = "lattitude";
$allData -> longitude = "longitude";
$allData -> timezone = "2";
$allData -> useragent = "userAgent";
$allData -> isDesktop = "isDesktop";
$allData -> isMobile = "isMobile";
$allData -> isTablet = "isTablet";
$allData -> BrowserVersion = "browser";
$allData -> MobileOS = "device";
$allData -> MobileOS = "device";
$allData->DesktopOS = "platform";
$allData -> save();
}
При переходе на главную страницу срабатывает экшн контроллера, где назначается это задание. Страница загружается, проходит минута, но задание не срабатывает. Подскажите что я не учел? Использовал эту инструкцию https://laravel.ru/docs/v5/queues , но как минимум там ничего не сказано о том, что нужно что-то менять в .env . Возможно там неполная инструкция + кривые руки.