PostgreSQL coub express.js freeware git jquery laravel links linux macos mysql node.js php powershell python ubuntu vim virtualbox анекдот блог игры интересно стихи цитаты

Довольно давно вышла отличная серия бесплатных скринкасов "Be Awesome in PHPStorm" от Jeffrey Way. Конечно, некоторая часть материала рассматривается в контексте именно Laravel, но думаю все равно будет нелишним посмотреть всем пользователям этой IDE, весьма вероятно что узнаете что-то новое и полезное.



Laravel 4: with magick
August 12, 2014
Исходник статьи принадлежит гражданину @zwacky. А тем кто ещё не шарит на 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).
Приведенный ниже код работает так
  • Проверяет первый сегмент 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). То есть чтобы для русского по умолчанию роутинг нормально отрабатывал без языкового сегмента в ссылке, редирект по куке при этом должен остаться рабочим.
Если кто-то раздобудет решение красивее - буду благодарен за ссылку. Особо интересует момент генерации ссылок для контрола переключения языков.


Забавно что нету из коробки этой возможности. Вспоминается цитата из особенностей национальной рыбалки "Господи, неужели на такой сложной лодке, нет простого туалета". Хотя чего там, до сих пор не понятно почему с поведением окон все так ортодоксально в макоси при том что и линуксовые DE и Windows c 7ки давно уже умеют всякие пропорциональные раскрытия и по высоте и фулскрин нормальный.. Ну ладно. Сейчас надо прицепить блокировку на хоткей.
  1. Запускаем automator. Тут нам надо создать службу для запуска скринсейвера.
    Файл - Новый - Служба


  2. В библиотеке действий в утилитах выбираем "Запустить заставку", тащим направо в рабочую область


  3. Во входящих параметрах указываем что входящих данных нет


  4. Жмем Cmd+s и сохраняем службу например как "Start screen saver"

  5. Теперь нужно навесить глобальный хоткей, идем в настройки служб


    Тут находим нашу службу, назначаем ей хоткей


  6. Теперь в основных настройках из раздела "Защита и безопасность" нужно убедиться что пароль будет запрошен сразу после выхода из скринсейвра
Вот такой вот "нехитрый" способ.
Первоисточник на osxdaily.com


Для того, чтобы не ползать править постоянно /etc/hosts при каждом заведении нового проекта на локалке хорошо бы заставить машину ломится по определенному домену на локальную машину всегда. Я как-то уже писал на эту тему, но решение там мягко говоря не самое простое. Я тут и там слышал про dnsmasq но как-то все не доходили руки разобраться. В общем, это совсем-совсем просто.
  1. sudo apt-get install dnsmasq (ну или brew install dnsmasq, кстати с brew была какая-то проблема небольшая, сейчас не вспомню на ходу)
  2. Идем открываем редактором файл конфигурации /etc/dnsmasq.conf (внутри конфига все расписано, но все опции закоменчены; в случае с brew конфиг лежит /usr/local/etc/dnsmasq.conf)
  3. Добавляем (или ищем и раскоментируем+правим то что уже есть в конфиге) две строки
    address=/.dev/127.0.0.1   # прибиваем гвоздями домен к ip
    listen-address=127.0.0.1 # слушать будем на этом ип
    
    Создаем папку (если нет)
    sudo mkdir /etc/resolver
    
    Создаем такой файлик под зону
    sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/dev'
    
    Теперь все хосты вида *.dev будут завернуты на 127.0.0.1
    Любопытные граждане гуглят и читают комментарии в конфиг файле.
  4. Последний штрих, идем в свойства текущего сетевого соединения и в его свойствах указываем дополнительный DNS как свой локальный 127.0.0.1 (в формах настройки есть разница, но я думаю это просто и пояснения не нужны)
  5. И совсем последний штрих - перезапускаем dnsmasq
    sudo service dnsmasq restart
    
    Как это делается на маке я не помню, нужно поглядеть brew info dnsmasq
Вот собственно и все. Теперь /etc/hosts можно оставить в покое и прописывать везде локальные хосты в домене .dev
Жаль я забыл что у меня там с brew сломалось, но фикс нагуглился минут за 20, ничего серьезного.

P.S.:

А если ещё в nginx добавить что-то вида
server {

  server_name ~^(.*)\.my\.dev$;
  set $projectFolder $1;

  root /home/luke/projects/php/$projectFolder/public;
  index index.php;
  
  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }

  location ~ \.php$ {
    # With php5-fpm:
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  }
}
то ещё и в конфиги сервера можно будет ползать значительно реже.
В этом примере будет достаточно просто размещать проекты на диске вот так
/home/luke/projects/php/project-one/public -> http://project-one.my.dev
/home/luke/projects/php/project-two/public -> http://project-two.my.dev
/home/luke/projects/php/project-three/public -> http://project-three.my.dev
/home/luke/projects/php/project-four/public -> http://project-four.my.dev


aghr