• Как правильно спроектировать Laravel приложение с уклоном в enterprise?

    @Finsh
    Взять Symfony.
    Только вот серьёзно, зачем делать из отвертки дрель, когда она уже есть. Вы думаете, что это будет быстрее? Вы думаете что это будет дешевле? Laravel прекрасен для своих, средних, задач, для "enterprise" берите Symfony.
    Ответ написан
    Комментировать
  • Как учить Node.js?

    @kirill-93
    Замечательный список. На счет книг не скажу, а курсы Кантора хорошие. Есть еще замечательный курс от Игоря Борисова из specialist.ru
    Ответ написан
    Комментировать
  • "Сильные" книги по Symfony и архитектуре приложений?

    by25
    @by25
    Веб-разработчик
    1. Мэтт Зандстра "PHP: объекты, шаблоны и методики программирования" - Врубиться в ООП
    2. Эрик Фримэн и ко "Паттерны проектирования" (Head First) - Влюбиться в ООП
    3. Эрик Эванс "Предметно-ориентированное проектирование" - научиться проектировать сложные системы
    4. Крэг Ларман "Применение UML 2.0 и шаблонов проектирования" - про проектирование, глубокое понимание ООП
    Ответ написан
    Комментировать
  • Как извлечь обьект из Service Container в зависимости от аргумента?

    miraage
    @miraage
    Старый прогер
    Так нельзя делать.
    Вернее, можно, но это полный моветон и архитектурная ошибка.
    Инжектите в контроллер someotherservice и вызывайте его метод getDataById.
    Ответ написан
    2 комментария
  • Что такое "инвертированный" цикл for в JS?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Классический цикл for в javascript состоит из 3х операторов: init, predicate, nextIteration
    В общей записи это выглядит так:for(init; predicate; nextIteration) { body }

    Цикл for исполняется следующим образом:
    1. Выполняется оператор init в области видимости блока цикла
    Обычно здесь объявляют переменную-счетчик и присваивают ей начальное значение
    Определение "в области видимости блока цикла" означает, что если init-оператор представляет собой оператор let - то объявленные переменные будут видны в цикле, но не за его пределами
    2. Вычисляется predicate, его результат приводится к boolean и последующее выполнение зависит от результата этого приведения:
    Если результат === false - то цикл завершается
    Если результат === true - то переходим к шагу 3
    3. Исполняется тело цикла - блок body, официально блоком быть не обязан, может быть и единичным оператором, но лучше всегда писать блок (фигурные скобки)
    4. Исполняется оператор nextIteration и переходим к пункту 2

    Теперь разберемся на конкретных примерах:
    Прямой цикл
    for(let i = 0; i < 10; i++) {
      console.log(i);
    }

    Объявляется переменная i и ей присваивается начальное значение 0
    Получается результат выражения Boolean(i < 10) -> 0 < 10 - true -> Boolean(true) - true -> можем выполнять тело
    Выполняется тело console.log(i); -> видим 0 в консольке
    Выполняется i++ -> i становится 1
    Получается результат выражения Boolean(i < 10) -> 1 < 10 - true -> Boolean(true) - true -> можем выполнять тело
    ...
    Так все продолжается 10 раз, на 10 итерации появляются изменения после этого момента:
    Выполняется i++ -> i становится 10
    олучается результат выражения Boolean(i < 10) -> 10 < 10 - false -> Boolean(false) - false -> завершаем цикл

    инвертированный цикл
    for(let i = 10; i--;) {
      console.log(i);
    }

    Объявляется переменная i и ей присваивается начальное значение 10
    Получается результат выражения Boolean(i--) -> i-- - 10, i = 9 -> Boolean(10) - true -> можем выполнять тело
    Выполняется тело console.log(i); -> видим 9 в консольке
    Оператор nextIteration - пустой, ничего выполнять не надо
    Получается результат выражения Boolean(i--) -> i-- - 9, i = 8 -> Boolean(9) - true -> можем выполнять тело
    ...
    Цикл по прежнему работает 10 раз, последняя итерация (когда i к моменту исполнения predicate равна 0):
    Получается результат выражения Boolean(i--) -> i-- - 0, i = -1 -> Boolean(0) - false -> завершаем цикл

    Как видим, за счет отсутствия nextIteration оператора, на каждой итерации выполняется на одно действие меньше, поэтому цикл отрабатывает быстрее
    Ответ написан
    2 комментария
  • Можно ли посмотреть, что печатает в консоли Linux пользователь подключенный по SSH?

    saboteur_kiev
    @saboteur_kiev Куратор тега Linux
    software engineer
    Если вы админ на этом линуксе, то вариантов много.
    * Поставьте conspy
    * смотрите что в /dev/vcsa1...
    * запускайте screen и шарьте экран
    * смотрите ttylog pts/1
    Ответ написан
    1 комментарий
  • Как быстро посмотреть css код в phpStorm?

    BOOMER_74
    @BOOMER_74
    Full-Stack разработчик
    По конкретному классу не получится, но можно увидеть все стили, примененные к выбранному тегу. Правой кнопкой по нужному тегу -> Show Applied Styles for Tag (настройте хоткеи если нужно).
    Ответ написан
    Комментировать
  • В каких случаях вы использовали Redis?

    @chronic86
    Ruby on Rails junior
    1. Хранилище сессий и профилей пользователей;
    2. Сервер очередей, плюс держим в уме механизм publish/subscribe;
    3. Полноценная замена Memcached, притом в случае с Redis мы получим репликацию, более длинные ключи и значения, возможность восстановления кэша с диска и тп;
    4. Место для хранения количества пользователей онлайн, кодов капч, различных флагов, саджестов поисковых запросов;
    5. СУБД для небольших приложений — сокращалок ссылок, имиджбордов, возможно даже блогов;
    6. Роль «словаря» в шардинге, то есть сервер, который знает, какие шарды на каких серверах искать;
    7. Хранилище промежуточных результатов вычислений при обработке больших объемов данных;


    eax.me/redis
    Ответ написан
    Комментировать
  • Как обезопаситься от шеллов на сервере?

    Vamp
    @Vamp
    Для начала необходимо разделить сайты друг от друга физически. Сами скрипты сайта, временные файлы и файлы сессий.

    Например, структура может быть такая:
    /var/www
      + toster.ru
      |  + site
      |  + sessions
      |  + temp
      + example.com
      |  + site
      |  + sessions
      |  + temp
      + остальные сайты


    В папке site расположены скрипты сайта. Обычно эта папка (или одна из вложенных) является document root сайта.

    В sessions находятся файлы сессий посетителей сайта. Если их не разделять, то взлом одного сайта автоматически дискредитирует сессии всех пользователей остальных сайтов. То есть, взломав example.com, можно стырить сессию администратора toster.ru. Путь к этой папке настраивается директивой session.save_path.

    А в temp находятся временные файлы, загружаемые пользователями через html формы (директива upload_tmp_dir). Туда же неплохо направить и остальные временные файлы, генерируемые функциями tmpfile(), tempnam(), самостоятельным образом (используя результат функции sys_get_temp_dir() для построения пути) или любой другой функцией, которая использует системную временную директорию. К сожалению, директива sys_temp_dir, ответственная за это, появилась только в php 5.5.0. Если у вас более ранняя версия, тогда нужно учитывать момент, что сайты могут ходить в /tmp и нельзя блокировать доступ к этой папке.

    ---

    Далее необходимо настроить нормальные права доступа. Часто в интернете можно видеть советы "делайте chmod 777 на всё". Так делать нельзя. Подобные права доступа как раз наихудшим образом сказываются на безопасности, потому что дают возможность отредактировать любой скрипт на сайте и встроить маленький бэкдор в самый незаметный скрипт, принадлежащий CMS. Надежно избавиться от такого довеска можно будет только полной переустановкой CMS. Или можно загнать весь сайт в систему контроля версий, как предложил Максим Гречушников, и одной командой узнать какие скрпиты были заражены. Тем не менее, одно другое не исключает. Система контроля версий позволит выявить заражение постфактум, а нормальные права не дадут возможности заразить файл в принципе.

    Я рекомендую на папки устанавливать права 755, а на файлы 644. При этом, владельцем всех папок и файлов должен быть кто угодно, но не пользователь, из-под которого запущен веб-сервер или php (например, пользователь, под которым вы сами заходите на сервер по ssh). Но такие права на всё устанавливать тоже нельзя. Сайт в процессе своей работы может генерировать свои временные файлы (например, кешировать что-то в файл, компилировать шаблоны, хранить какие-нибудь настройки), поэтому для папок, в которые сайт может что-то записать, права должны быть другие. Вот здесь уже можно ставить 777 для папок и 666 для файлов. Это довольно кропотливая работа, потому что у каждого сайта (особенно если они на разных CMS) свои папки и часто определение таких папок нетрвиально.

    И права доступа не решают всех проблем. Злоумышленник может встроить вредоносный код в скомпилированный шаблон или отравить кеш. Тогда не помогут ни права (так как для нормальной работы сайту нужно иметь права на запись в такие файлы), ни система контроля версий (так как подобные файлы слишком часто меняются и, как правило, не хранятся в репозитории). Хотя надо сказать, этот способ внедрения сложнее и недолговечнее, чем встраивание в нормальный скрипт.

    И ещё автоматическое обновление сайта перестанет работать. Если CMS позволяет обновить себя через кнопку в веб-интерфейсе админки, то такое обновление не будет работать, так как права доступа не разрешают веб-серверу модифицировать скрипты. Обновлять скрипты теперь можно только вручную от имени пользователя, которому принадлежат все файлы. Безопасность и удобство - разные концы одной палки.

    Даже с учётом всех недостатков - нормально настроенные права доступа на файлы и папки значительно сокращают вектор возможных атак. Так что обязательно разберитесь с этим вопросом.

    ---

    После раскидывания сайтов по своим папкам и настройки прав, необходимо ограничить доступ сайтов друг к другу. Проще всего это сделать настройкой php директивы open_basedir. Эта директива определяет список директорий, внутри которых (а так же во всех вложенных папках) скрипты могут читать и писать. Доступ за пределы этих директорий будет пресекаться. То есть нужно каждому сайту прописать в open_basedir путь к своей папке и к /tmp (если версия php < 5.5.0 и нельзя установить sys_temp_dir).

    Для Apache с mod_php конфигурация прописывается в httpd.conf:

    <VirtualHost *:80>
      ServerName example.com
      php_admin_value open_basedir /var/www/example.com/:/tmp/
      php_admin_value upload_tmp_dir /var/www/example.com/temp/
      php_admin_value sys_temp_dir /var/www/example.com/temp/
      php_value session.save_path /var/www/example.com/sessions/
    </VirtualHost>


    Для php-fpm в конец php.ini файла вписывается специальная секция, определяющая индивидуальную конфигурацию для каждого сайта:

    [HOST=example.com]
    open_basedir /var/www/example.com/:/tmp/
    upload_tmp_dir /var/www/example.com/temp/
    sys_temp_dir /var/www/example.com/temp/
    session.save_path /var/www/example.com/sessions/
    
    [HOST=toster.ru]
    ; конфиг для toster.ru и т.д.


    У open_basedir есть недостатки:

    1. Замедление файловых операций, так как необходимо проверить вхождение каждого открываемого файла в список open_basedir. Если проекты не highload, то некритично.
    2. Есть варианты обхода. Но их далеко не всегда удаётся эксплуатировать. Тем более они закрываются со временем в новых версиях php.
    3. Realpath cache не работает вместе с включенной open_basedir.

    ---

    Есть вариант запускать каждый сайт от своего пользователя. В apache это делается опцией AssignUserId. В php-fpm - отдельной конфигурацией pool. Но в любом случае нужно для каждого сайта создавать не только отдельного юзера, но и группу. При этом права на основную папку сайта (/var/www/example.com) должны быть 750, а группа должна соответствовать той, от которой будет запускаться процесс apache (или пул php-fpm), ответственный за обслуживание сайта.

    Проще показать на примере. После имени файла я буду указывать права, владельца и группу в формате (права, владелец:группа)
    /var/www         (755, root:root)
      + toster.ru    (750, my_user:toster)
      |  + site      (755, my_user:toster)
      |  + sessions  (777, my_user:toster)
      |  + temp      (777, my_user:toster)
      + example.com  (750, my_user:example)
      |  + site      (755, my_user:example)
      |  + sessions  (777, my_user:example)
      |  + temp      (777, my_user:example)
      + остальные сайты - всё аналогично


    my_user - это пользователь, под которым ни в коем случае нельзя запускать веб-сервер и php. Это может быть ваш собственный пользователь, под которым вы заходите на сервер по ssh. В этом случае у вас будут все права на сайт, а у сайта только необходимый минимум.

    <VirtualHost *:80>
      ServerName example.com
      AssignUserId exapmle example
    </VirtualHost>
    <VirtualHost *:80>
      ServerName toster.ru
      AssignUserId toster toster
    </VirtualHost>


    Разумеется, в системе должны быть заранее созданы пользователи с именами toster, example и с одноимёнными основными группами.

    Вобщем, рекомендую более подробно ознакомиться с системой прав и пользователей в линуксе. Пригодится всегда.

    ---

    Более сложным и предпочтительным вариантом является упаковка каждого сайта в свой отдельный виртуальный контейнер lxc/docker. Я не смогу в двух словах описать как это добро настраивать, но эффект будет такой, как будто каждый сайт работает на своём собственном VPS сервере.

    ---

    Ещё немного про базу. Для доступа к базе у каждого сайта должен быть свой собственный логин с паролем. Причем, доступ должен ограничиваться исключительно той базой, в которой находятся данные сайта. И права должны быть не все подряд, а только SELECT, INSERT, UPDATE, DELETE. В редких случаях CMS может самостоятельно создавать таблицы для своих нужд в процессе своей работы (не в процессе первичной установки). В этом случае можно добавить права CREATE, ALTER, INDEX юзеру этого сайта. Иногда бывает в базе есть какие-то процедуры/функции. Для их вызова требуются права EXECUTE.

    ---

    Безопасность - дело большое и очень разнообразное. И уж точно не простое. Всё что я здесь написал - это далеко не полный список. Есть ещё настройки уровня операционной системы (особенно фаервол) и прочего установленного в системе софта. Так же отдельным пунктом идёт система мониторинга и оповещения, которые почему-то никто не делает - не считают нужным разбираться ещё и в этом. Так что если у вас нет хорошего админа в запасе, то проще будет заказать услугу администрирования прямо у того же хостера, у которого вы арендуете VPS. Или найти админа-фрилансера. Или же перевезти сайты на shared хостинг, где администрирование уже включено в ценник, да и сам переезд хостеры часто предлагают сделать бесплатно силами своих админов.
    Ответ написан
    Комментировать
  • Почему метод server.address() вместо IP-адреса выдает два двоеточия в поле address?

    SagePtr
    @SagePtr
    Еда - это святое
    Два двоеточия в IPv6 - это аналог 0.0.0.0 в IPv4
    Означает, что сервер слушает на всех сетевых интерфейсах, а не на определённом.
    Ответ написан
    Комментировать
  • Можно ли сохранять в git папку vendor после composer update?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Если одни разработчик обновил библиотеки, другие должны как то об этом узнать, чтобы обновится у себя

    Если другие разработчики делают git pull и не обращают внимания на изменения - это их проблемы. Хорошим тоном является уведомление от автора правок в composer.json, что остальным стоит его обновить.

    Список библиотек и версии обновляются не очень часто, а при каждом релизе, приходится выкачивать одни и те же либы

    Вообще говоря композер умеет в кэш и одни и те же версии либ тянутся с кэша.

    В проекте могут быть заняты люди, которые не умеют (или не могут в данный момент) работать с консолью: верстальщики, технические писатели, ревьюер кода (безопасности), сюда же и вопрос оплаты специалиста, которые умеет всё

    Если нужно именно поднять окружение с проектом - настройте vagrant и пропишите в README как им пользоваться конкретно для вашего проекта.
    Что касается людей:
    * верстальщики - vagrant
    * технические писатели - я конечно не в курсе вашего проекта, но я бы доступ даже к репозиторию не дал, максимум - завел отдельный репозиторий для них.
    * ревьюер кода (безопасности) - ревьюер, который не может в composer / консоль?? Шутка не удачная.
    * сюда же и вопрос оплаты специалиста - лолшто? Это вообще не связано с окружением вашего проекта, ну вот ни капли.

    Нет возможности просто и быстро передать кому-то код, просто расшарив ссылку на гит

    Если у вас проект НЕ opensource - то такого делать в принципе нельзя. Доступ к репозиторию должны иметь специалисты, которые работают с кодом этого проекта и ни кто другой, а composer тут вот ни капли ни при чем!

    Вопрос в том, можно ли сохранять папку vendor в git

    НЕТ! Вы придумали НЕ существующую проблему и пытаетесь героически ее решить, только от этого решения будет еще хуже.

    насколько это противоречит принятому стилю

    на полностью

    какие могут быть проблемы с этим (сейчас самый жирный минус от такого подхода вижу в распухании репозитория) ?

    1. Вы становитесь вендором кода, который взяли где-то, как следствие вы следите за его обновлением, у изначального вендора и вы проводите аналогичные правки в своем проекте. Если так не делать - баги, найденные в этой зависимости сами себя не пофиксят и этот код будет быстро устаревать.
    2. В код зависимости появляется соблаз провести собственные наработки - это то, что делать нельзя, иначе процесс обновления будет сложнее на порядки.
    3. Ваш репозиторий разбухнет.
    4. Композер вашу зависимость придется явно прописать иначе автолоад может ее не подтянуть.

    Использует ли кто-нибудь такую практику в своих проектах ?

    Пару лет назад работал на крупном проекте, который начинался до появления композера. Когда зависимостей тьма и ты не знаешь, какие из них содержат артефакты собственных наработок, какие обновляются синхронно с официальными вендорами, а какие тянутся из вне приходится тратить кучу времени на выяснение. Это просранное время.
    Ответ написан
    1 комментарий
  • Как в Promise добавить отложенный обработчик ошибки?

    @sugadu
    а вот так?
    let bbb = Promise.resolve();
      
      var aaa = bbb.then(none => {
        throw "ошибк2";
      })
      
      aaa.catch(err => {
        console.log(err)
      });
    Ответ написан
  • Где скачать базу данных регионов и населенных пунктов России?

    @IceJOKER
    Web/Android developer
    https://vk.com/dev/database.getCountries
    там же и остальные данные
    Ответ написан
    Комментировать
  • Как правильно в Ubuntu подключить ssh ключ для GitLab?

    @exenza
    Вам нужно изменить параметр url в .git/config проекта, на тот url, который в гитлабе для ssh, вида git@gitlab.com:username/projectname.git;
    или склонировать проект целиком из репозитория еще раз используя ssh: git clone git@gitlab.com..
    Ответ написан
    Комментировать
  • Как называется этот стиль рисования?

    @Skrolea
    Я не художник (от слова "совсем"), но мне кажется, что это называется "Сделайте ручки, ножки просто линиями, лицо сделайте светлей, глаза точками, нос двумя точками" ))
    Ответ написан
    4 комментария
  • Один сайт на нескольких хостингах?

    @wukibuh
    Это или криво или не тривиально.

    На Хабре есть группа статей фирмы ivi.ru.
    Там про это очень хорошо разжевано - про самые разные методы, про плюсы и минусы.

    В частности:
    https://habrahabr.ru/company/ivi/blog/237349/

    Все советы про CDN и DNS, которые вам тут дали Lindon_cano и Дмитрий
    - большая глупость.

    DNS не работает - потому что он тупо кэшируется.
    CDN - поможет только немного, только с картинками. А для сайта магазина основная нагрузка - это движок, а вовсе не картинки.

    Идея с проксированием вообще крайняя тупость в совете - тройная задержка получается.

    Сделать несколько реплик сайта и позволять пользователям выбирать самим сайт. По geoIP подсказывая.
    Ответ написан
    3 комментария
  • Почему DNS выбирает не тот IP?

    Коллеги, курите мануалы про DNS Round Robin и Netmask Ordering
    Ответ написан
    2 комментария
  • Как округлить число до кратного 10, например 6 до 10, 23 до 30?

    Школьный же вопрос, дели на 10, округляй а потом умножай на 10.
    Ответ написан
    6 комментариев