PostgreSQL
coub
express.js
freeware
git
jquery
laravel
links
linux
macos
mysql
node.js
php
powershell
python
ubuntu
vim
virtualbox
анекдот
блог
игры
интересно
стихи
цитаты
Натолкнулся на интересный вопрос. Проект большой, контроллеров много становится, захотелось как-то структурировать их чтобы не искать каждый раз. Красноглазие же развивается от этого. Натолкнулся на тему с namespace-ами для групп роутов, да, все работает, но надо изрядно перепиливать все вызовы фасадов, размечать неймспейсы.. короче рутинной возни ненужной куча. Если просто попробовать впилить папку в роут в стиле
REM: см. git diff vendor/composer/autoload_classmap.php
Route::post('/lala-page', ['as' => 'lalala', 'uses' => 'subfolder/LalaController@myfinc']);То оно мало того что выглядит убого так ещё и не работает. А решение было элементарнейшее: перестроить карту классов композером. То есть просто создаем все свои папки где будут жить контроллеры, раскладываем туда контроллеры
app/controllers app/controllers/my app/controllers/admin ...В самих контроллерах ничего не меняем. Просто перестраиваем автозагрузку (из папки проекта разумеется)
composer dump-autoloadИ вуаля, все вложенные контроллеры заработали. Мне бы такие инструменты лет 10 назад.. Ну пять хотя-бы :)
REM: см. git diff vendor/composer/autoload_classmap.php
Laravel4: Валидация и кастомные название полей в сообщениях об ошибках
September 21, 2014
Есть ли у вас такая проблема что.. Нет, правильнее будет сразу скриншот показать.
Маркером отмечены сообщения о том, что валидатору не нравятся данные которые вы пытаетесь сохранить через модель. Все хорошо и здорово кроме названия поля в сообщениях. Смышленый пользователь конечно способен догадаться что за поле имеется ввиду, но очевидно чем больше полей в исходной форме, тем сложнее придется пользователю. Да и как-то.. в общем перфекционисты от этого страдают. Есть "способ вылечить" это (на самом деле документированная возможность). Выглядит это примерно так.
Теперь сообщения будут выглядеть вот так
Стало куда веселее. Осталось почитать оф. документацию по валидации.
Метод setAttributeNames можно поискать в API, он там есть, но описание скромненькое конечно.
Что касается метода isValid, то это метод модели который используется для валидации вот так
Пример использования такой модели в контроллере выглядит примерно так
P.S.: Для поддержки языковых версий можно вписывать названия свойств вот так
Маркером отмечены сообщения о том, что валидатору не нравятся данные которые вы пытаетесь сохранить через модель. Все хорошо и здорово кроме названия поля в сообщениях. Смышленый пользователь конечно способен догадаться что за поле имеется ввиду, но очевидно чем больше полей в исходной форме, тем сложнее придется пользователю. Да и как-то.. в общем перфекционисты от этого страдают. Есть "способ вылечить" это (на самом деле документированная возможность). Выглядит это примерно так.
public function isValid() { $validator = Validator::make( $this->toArray(), [ 'name' => 'required', 'full_link' => 'required|url|unique:table_links,full_link,' . $this->id, ] ); $validator->setAttributeNames([ 'name' => 'Название ссылки', 'full_link' => 'Ссылка для подсчета кликов', ]); if ($validator->fails()) { $this->errors = $validator->errors(); } return $validator->passes(); }
Теперь сообщения будут выглядеть вот так
Стало куда веселее. Осталось почитать оф. документацию по валидации.
Метод setAttributeNames можно поискать в API, он там есть, но описание скромненькое конечно.
Что касается метода isValid, то это метод модели который используется для валидации вот так
public static function boot() { parent::boot(); // before update and create MyModel::creating(function($item) { if (!$item->isValid()) return false; }); MyModel::saving(function ($item) { if (!$item->isValid()) return false; }); }То есть на модель вешаются хуки, как видно на события сохранения и создания объекта, которые собственно и вызывают наш метод валидации при соответствующих обстоятельствах.
Пример использования такой модели в контроллере выглядит примерно так
public function itemSave() { $item = MyModel::find(Input::get('id')); if (!$item) { App::abort(404); } $item->name = Input::get('name'); $item->full_link = Input::get('full_link'); if (!$item->save()) { return Redirect::route('item-edit', [$item->id])->withErrors($item->errors); } return Redirect::route('item-edit', [$item->id])->withItemSaved(1); }Пример я упростил, но суть та же. Если сохранение отработало с ошибкой, возвращаемся назад с ошибками из валидатора, иначе всё тип-топ, сообщаем об успешном сохранении. Это всё.
P.S.: Для поддержки языковых версий можно вписывать названия свойств вот так
$validator->setAttributeNames([ 'name' => Lang::get('error.name'), 'full_link' => Lang::get('error.full_link'), ]);
Laravel 4: with magick
August 12, 2014
Исходник статьи принадлежит гражданину @zwacky. А тем кто ещё не шарит на medium в поисках интересного - рекомендую попробовать. Темы совершенно любые, отдельной строкой отрадно, что разработка на чем угодно - в том числе.
Заметка маленькая, но приятная. Есть в Laravel такая замечательная "штука" как with. Пример классического использования можно встретить при передаче данных в шаблон или при редиректе
Пояснить словами мне трудно, поясню примером ниже.
Внимательный читатель документации (которым я тоже не являюсь к сожалению) нашел бы в ней более ловкий вариант передачи данных в шаблон или редирект самостоятельно. Возможно эта фишка несколько усложняет понимание кода, но мне кажется привыкаешь к этому моментально и пересаживаться обратно уже не хочется.
Да. В оф. документации можно увидеть описанное здесь поведение вот тут в параграфе "Passing Data To Views". Возможно такое поведение with встретится где-то ещё. Практически тоже самое есть в работе с Eloquent (см. статью на medium).
Заметка маленькая, но приятная. Есть в Laravel такая замечательная "штука" как with. Пример классического использования можно встретить при передаче данных в шаблон или при редиректе
// template return View::make('template.blade.php')->with('say', 'yahoo'); // redirect return Redirect::to('user/login')->with('msg', 'wow, u failed');Здесь все понятно, просто передаем ключ и значение. Так в чем же собственно "with magick"?
Пояснить словами мне трудно, поясню примером ниже.
Внимательный читатель документации (которым я тоже не являюсь к сожалению) нашел бы в ней более ловкий вариант передачи данных в шаблон или редирект самостоятельно. Возможно эта фишка несколько усложняет понимание кода, но мне кажется привыкаешь к этому моментально и пересаживаться обратно уже не хочется.
// template return View::make('template.blade.php')->withSay('yahoo'); // в шаблоне будет доступно как {{ $say }} // redirect return Redirect::route('some-cool-route')->withAuthError('woww, auth error dude'); // в шаблоне будет доступно как {{ Session::get('auth_error') }}То есть во все методы начинающиеся с with обрабатываются как магические. Кроме того в их названиях обрабатывается CamelCase заменяя смену регистра на нижнее подчеркивание (что демонстрирует второй пример). Таким образом на отбивании кавычек и запятых можно немного сэкономить. Вот мелочь же, а как приятно.
Да. В оф. документации можно увидеть описанное здесь поведение вот тут в параграфе "Passing Data To Views". Возможно такое поведение with встретится где-то ещё. Практически тоже самое есть в работе с Eloquent (см. статью на medium).
Само решение принадлежит Barry vd. Heuvel и приведено им на форуме forumsarchive.laravel.io, я только немного дорихтовал детали, довольно неуклюже пока как мне кажется, но работает.
Для понимания кода примера нужно ознакомиться с документацией по Localization (надо прочитать всё, там не много) и Routing (prefixing).
Приведенный ниже код работает так
Создадим языковые файлы для этой цели, под английский и русский языки из примера
Если кто-то раздобудет решение красивее - буду благодарен за ссылку. Особо интересует момент генерации ссылок для контрола переключения языков.
Для понимания кода примера нужно ознакомиться с документацией по Localization (надо прочитать всё, там не много) и Routing (prefixing).
Приведенный ниже код работает так
- Проверяет первый сегмент uri запроса (http://hostname/ru/one/two/?p=1)на соответствие какому-либо из установленных языков
- Если первый сегмент uri соответствует какому-либо установленному языку, то устанавливается кука с этим языком на месяц, чтобы в дальнейшем пользователь мог зайти на страницу набрав только имя хоста и тут же перейти на свою языковую версию
- В случае если первый сегмент не соответствует ниодному из установленных языков ту же проверку пробуем провести с кукой, содержащей выбранный язык
- Далее добавляем к запрошенной ссылке текущую локаль и насильно редиректим на "правильную" ссылку. Причем локаль берется из текущего состояния приложения, то есть если ничего ни в uri ни в cookie небыло найдено, то локаль будет установлена та, что указана в конфиге приложения app/config/app.php
// set language prefix $locale = Request::segment(1); $langs = ['ru', 'en']; if (in_array($locale, $langs) !== false) { \App::setLocale($locale); Cookie::queue('language', $locale, 60 * 24 * 30); } else { // if no url param - try to get lang from cookie $locale = Cookie::get('language'); if (in_array($locale, $langs) !== false) { \App::setLocale($locale); } if (!\App::runningInConsole()) { // save all uri & force redirect to "correct" link $qp = Input::query(); $qp = (!empty($qp)) ? '?' . http_build_query($qp, null, '&') : ''; Redirect::to('/' . Lang::getLocale() . '/' . Request::path() . $qp, 301)->send(); exit(); } } // front part routing Route::group(['prefix' => $locale], function () { Route::get('/', ['as' => 'main-page', 'uses' => function () { return View::make('main'); }]); Route::get('/yey', ['as' => 's-yey', 'uses' => 'HomeController@sayYey']); Route::get('/wow', ['as' => 's-wow', 'uses' => 'HomeController@sayWow']); }); // front part with language prefixЯ уверен что это не самое лучшее решение но оно работает. Далее, интересный вопрос с кнопкой переключения языков, то есть с той самой переключалкой из ссылок вида Ru | En которая собственно переключает текущий язык. Думаю логично хотеть чтобы при таком переключении в текущем урле ничего кроме языкового сегмента не менялось. Предлагаю свой велосипед, основанный на мане по Localization
Создадим языковые файлы для этой цели, под английский и русский языки из примера
// app/lang/en/lang_toggle.php $segsEn = $segsRu = Request::segments(); $segsRu[0] = 'ru'; $qp = Input::query(); $qp = (!empty($qp)) ? '?' . http_build_query($qp, null, '&') : ''; return [ 'en' => [ 'text' => 'En', 'href' => '/' . implode('/', $segsEn) . $qp, ], 'ru' => [ 'text' => 'Ru', 'href' => '/' . implode('/', $segsRu) . $qp ], ];И ещё один
// app/lang/ru/lang_toggle.php $segsEn = $segsRu = Request::segments(); $segsEn[0] = 'en'; $qp = Input::query(); $qp = (!empty($qp)) ? '?' . http_build_query($qp, null, '&') : ''; return [ 'en' => [ 'text' => 'En', 'href' => '/' . implode('/', $segsEn) . $qp, ], 'ru' => [ 'text' => 'Ru', 'href' => '/' . implode('/', $segsRu) . $qp ], ];Практически это копипаста которую я пока не придумал как залечить. Теперь у нас есть роутинг с языковым сегментом и языковые варианты контрола переключения с сохранением всех параметров uri. Осталось сделать шаблон для отображения этого контролла, вот он
{{-- app/views/lang-toggle.blade.php --}} <div style="float:right; padding:5px;"> <a href="@lang('lang_toggle.en.href')">@lang('lang_toggle.en.text')</a> | <a href="@lang('lang_toggle.ru.href')">@lang('lang_toggle.ru.text')</a> </div>Теперь осталось только подключить этот контрол где-то в лэйауте
{{-- app/views/layout-main.blade.php --}} ... @include('lang-toggle') ...На этом все. Повторюсь что решение наверняка не идеальное, но в масштабах вселенной не должно создавать невероятную нагрузку. В качестве упражнения, можно попробовать отпилить языковой префикс для языка по умолчанию (настройка в app/config/app.php). То есть чтобы для русского по умолчанию роутинг нормально отрабатывал без языкового сегмента в ссылке, редирект по куке при этом должен остаться рабочим.
Если кто-то раздобудет решение красивее - буду благодарен за ссылку. Особо интересует момент генерации ссылок для контрола переключения языков.