• Как сделать простой php маршрутизатор (роутер)?

    devg
    @devg
    I am Yenior software developer
    Очень простой роутер, не без недостатков, но довольно быстрый и легко использовать, дописывать под себя.

    <?php
    /**
     * Простой роутер
     * @devg
     */
    final class RouterLite {
    
      public static $routes = array();
      private static $params = array();
      public static $requestedUrl = '';
    
      /**
       * Добавить маршрут
       */
      public static function addRoute($route, $destination=null) {
        if ($destination != null && !is_array($route)) {
          $route = array($route => $destination);
        }
        self::$routes = array_merge(self::$routes, $route);
      }
    
      /**
       * Разделить переданный URL на компоненты
       */
      public static function splitUrl($url) {
        return preg_split('/\//', $url, -1, PREG_SPLIT_NO_EMPTY);
      }
      
      /**
       * Текущий обработанный URL
       */    
      public static function getCurrentUrl() {
        return (self::$requestedUrl?:'/');
      }
    
      /**
       * Обработка переданного URL
       */
      public static function dispatch($requestedUrl = null) {
    
          // Если URL не передан, берем его из REQUEST_URI
          if ($requestedUrl === null) {
            $uri = reset(explode('?', $_SERVER["REQUEST_URI"]));
            $requestedUrl = urldecode(rtrim($uri, '/'));
          }
    
          self::$requestedUrl = $requestedUrl;
    
          // если URL и маршрут полностью совпадают
          if (isset(self::$routes[$requestedUrl])) {
            self::$params = self::splitUrl(self::$routes[$requestedUrl]);
            return self::executeAction();
          }
    
          foreach (self::$routes as $route => $uri) {
            // Заменяем wildcards на рег. выражения
            if (strpos($route, ':') !== false) {
              $route = str_replace(':any', '(.+)', str_replace(':num', '([0-9]+)', $route));
            }
    
            if (preg_match('#^'.$route.'$#', $requestedUrl)) {
              if (strpos($uri, '$') !== false && strpos($route, '(') !== false) {
                $uri = preg_replace('#^'.$route.'$#', $uri, $requestedUrl);
              }
              self::$params = self::splitUrl($uri);
                
              break; // URL обработан!
            }
          } 
          return self::executeAction();
      } 
    
     /**
       * Запуск соответствующего действия/экшена/метода контроллера
       */
      public static function executeAction() {
        $controller = isset(self::$params[0]) ? self::$params[0]: 'DefaultController';
        $action = isset(self::$params[1]) ? self::$params[1]: 'default_method';
        $params = array_slice(self::$params, 2);
    
        return call_user_func_array(array($controller, $action), $params);
      }
    
    }
    ?>


    Пример использования:
    <?php
    // маршруты (можно хранить в конфиге приложения)
    // можно использовать wildcards (подстановки):
    // :any - любое цифробуквенное сочетание
    // :num - только цифры
    // в результирующее выражение записываются как $1, $2 и т.д. по порядку
    
    $routes = array(
      // 'url' => 'контроллер/действие/параметр1/параметр2/параметр3'
      '/' => 'MainController/index', // главная страница
      '/contacts' => 'MainController/contacts', // страница контактов
      '/blog' => 'BlogController/index', // список постов блога
      '/blog/:num' => 'BlogController/viewPost/$1' // просмотр отдельного поста, например, /blog/123
      '/blog/:any/:num' => 'BlogController/$1/$2' // действия над постом, например, /blog/edit/123 или /blog/dеlete/123
      '/:any' => 'MainController/anyAction' // все остальные запросы обрабатываются здесь
    ));
    
    // добавляем все маршруты за раз
    RouterLite::addRoute($routes);
    
    // а можно добавлять по одному
    RouterLite::addRoute('/about', 'MainController/about');
    
    // непосредственно запуск обработки
    RouterLite::dispatch();
    ?>


    UPDATE (07.08.2017):
    Дальнейшее развитие данного роутера см. в проекте Litero (https://github.com/bit55/litero)
    Ответ написан
    1 комментарий
  • Как правильно хранить сессии для авторизации?

    @iSensetivity
    бухгалтер, програміст-самоук
    cookie?
    Автор. на сайте -> ставим куку -> ставим сессию = дальше работаем с сессией.
    Вход на сайт -> проверяем сесию, нет? -> проверяем куку, есть? -> сравниваем хешьі с хешами с БД, совпадаеют? -> обновляем куки -> ставим сессию = дальше работаем с сессией.
    Ответ написан
    Комментировать
  • В чем разница между --save-dev и --save?

    keksmen
    @keksmen
    Just a programmer
    Как верно подметил ruddy22 в production версию продукта попадают не все модули, использующиеся при разработке. К примеру, если вы хотите минифицировать модуль, то, скорее всего будете использовать уже готовые продукты, которые в его использовании не пригодятся.

    Если совсем коротко, то модули из devDependencies не будут установлены в production. Вот и всё.
    Ответ написан
    2 комментария
  • Как правильно авторизоваться через API?

    DmitriyEntelis
    @DmitriyEntelis
    Думаю за деньги
    Вполне нормальная.
    Ответ написан
    Комментировать
  • Чем куки отличаются от сессии в PHP?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Нууу давайте разбираться.

    Для начала почитайте про HTTP на той же вики. Досканально знать не нужно, но стоит минимально понимать структуру запросов/ответов, понимать что у запроса и ответа есть заголовки и тело (тела может и не быть, зависит от типа запроса/ответа).

    Так вот. Куки. Куки живут на стороне браузера. Они передаются HTTP заголовком на каждый запрос на сервер (даже если вы за картинками полезли). Есть просто куки, есть http-only куки. Куки могут быть разграничены по хосту и пути. Все это дает нам гибкость и помогает с секьюрностью. В PHP содержимое $_COOKIE предоставляет нам SAPI. Когда PHP получает на обработку запрос, SAPI используемое (php-fpm, cgi, mod_php имеют свои реализации SAPI) в данный момент берет заголовки и тело запроса, парсит их и заполняет все эти суперглобальные массивы типа $_SERVER, $_GET и в том числе и $_COOKIE. Все что прислал нам клиент (что-то что делает запросы это клиент, что-то что их обрабатывает - сервер), а куки шлет нам браузер только те что можно исходя из того куда шлется запрос. Устанавливаются куки заголовком Set-Cookie в ответе, то есть тут больше нужно читать в принципе про HTTP а не про PHP. PHP просто позволяет вам работать с этим добром. Вы можете сэтить куки напрямую работая с заголовками ответа при помощи функции header. Более того, если выставить время жизни куки в 0, то как раз таки они а не сессия будет сбрасываться при закрытии браузера так как тот будет забывать все такие куки.

    Вот... сессии... В PHP сессия обычно это файл. Просто какой-то файл с рандомным именем. Если скажем в php.ini указано session.autostart или делается вызов session_start то создается файл под сессию пользователя (можно переместить в рэдис или мемкэш, свое хранилище и т.д в зависимости от нужд. Так же данные можно шифровать, что по умолчанию и происходит). Этот файл имеет ID, просто какая-то рандомная строка. И если при обработке запроса не нашлась сессия с предыдущего запроса - создается новая.

    И вот мы подошли к самому интересному - как PHP связывает сессию с предыдущего запроса с текущей. И тут все довольно просто - куки. Когда пользователю присваивается сессия, автоматически сэтится http-only (что бы нехорошие люди не могли из js увести нашу сессию) кука, в которую записан идентификатор сессии. В дебагере браузера можете посмотреть есть ли у вас кука PHPSESSID (название можно менять в настройках, да и вообще сессии можно не только через куки связывать, но это уже загоны по секьюрности) когда будете эксперементировать с сессиями.

    Когда запрос обрабатывается SAPI, при наличии session.autostart, перед тем как начинать создавать новую сессию, пых все же смотрит а есть ли у нас кука с идентификатором сессии, проверяет есть ли у него такая, и если есть успокаивается и не создает новую. Поскольку сессия привязывается через куки, то можно выставить время жизни этой самой куки (в php.ini) и таким образом регулировать время жизни сессии.

    Вот... когда использовать куки а когда сессии? Желательно понимать, что чем больше данных в куках (а у них есть лимит к слову) - тем больше данных мы передаем на каждый запрос. То есть это не круто когда что бы получить 1 килобайт данных мы должны в заголовках передать пару килобайт кук. Люди, повернутые на оптимизации, даже картинки хранят на отдельных cookie-less доменах что бы уменьшить количество трафика и пакетов (обычно простенький HTTP запрос влазит в размеры одного TCP пакета). Если вам нужно работать с этими данными из JS на любой странице, например локаль выбранноую пользователем для того что бы применять переводы еще и в JS, то стоит использовать куки. Для всео остального лучше конечно же использовать сессии. Во всяком случае на начальных этапах когда что-то сильно сложное вам делать не придется.
    Ответ написан
    2 комментария
  • Существует ли какие-либо стандарты ответов в restful?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Есть вполне стандартные статус коды:
    401 - нужно авторизоваться. В этом случае на клиенте мы должны попросить чувака ввести логин и пароль
    403 - у вас нет прав на это действие. Например юзер пытался удалить что-то или сделать что-то на что у него нет прав.
    422 - не могу обработать сущность. То есть если у нас не валидны данные в запросе, пароль там или имейл не ввели и все такое.
    404 - пользователя с таким именем пользователя и паролем не существует.

    Добавлять ли в тело ответа месседж с пояснением проблемы - решать вам. По хорошему стоит добавлять ибо тогда мы можем рулить сообщениями об ошибках с сервера. Ну или предоставлять клиенту оные. Но в любом случае разруливать ошибки нужно при помощи статус кодов.

    restpatterns.org/HTTP_Status_Codes
    Ответ написан
    2 комментария
  • Как избавиться от мерцания/ряби внешнего монитора?

    @Ivan85
    Достало меня это мерцание!

    Подошёл к решению проблемы комплексно, собрав всё, что нужно в Интернете. Мерцание уменьшилось до минимально приемлемого уровня. Решение проблемы кривое, даже если выполнить все пункты.

    1) Максимально разносим все провода и устройства в пространстве (чем дальше друг от друга тем лучше). Но не менее чем на 1,5-2 метра.

    2) Подключаем ноутбук и монитор в разные розетки.

    3) Монитор ставим через UPS, ноутбук без UPS или наоборот (если имеется в наличии UPS).

    4) Обмативаем фольгой все провода и блок питания для экранирования наводок.

    5) Выставляем в настройках экрана разрешение не 60 Гц (можно 75).

    6) Если на конкретном мониторе всё равно мерцает, пробуем другой монитор — в моём случае помогло ещё дополнительно уменьшить мерцание. Если покупать новый, то лучше сразу с HDMI и DVI выходами — при наличии соответствующих портов в ноутбуке можно отменить все перечисленные извращения (фольга, ИБП и т. д.)

    7) Эксперименетируем с разрешениями экрана — возможно, на некоторых разрешениях мерцание менее заметно.

    8) Настраиваем цвета на мониторе — при некотором сочетании цветов мерцание менее заметно.

    9) Обязательно проводим автонастойку монитора (обычно есть такая кнопка на мониторе).

    10) Если возможно, удлиняем провод для ноутбука, причём ту его часть, которая идёт от ИБП — желательно до пяти метров и максимально далеко уносим блок питания. Можно попробовать купить несколько блоков питания и экспериментальным путём подобрать наиболее оптимальный.

    11) Говорят, лучше использовать короткий провод VGA с ферритовыми кольцами (можно ещё дополнительно обмотать фольгой) — но в моём случае это не помогло. Лучше когда имеется несколько различных VGA-проводов — экспериментальным путём подбираем оптимальный.

    12) Как самый дебильный вариант, можно поменять ноутбук — но его рассматривать не буду — у меня самый удобный в мире ноутбук, хоть и без DVI разъема.

    Проблема с мерцанием монитора при подключении к ноутбуку серьёзная и решать её надо комплексно, используя все возможные ресурсы. За уменьшение мерцания на каждый провент стоит бороться!

    Чтобы не работать от батареи ноутбука и соответственно, её не изнашивать — как вариант, можно купить ИБП, отключить в настройках пищание, работать только от UPS, когда уходим на перекур, включать шнур бесперебойника в розетку. Хотя, наверное, проще купить монитор с нужными разъемами (HDMI и т. д.)
    Ответ написан
    1 комментарий
  • Как правильно работать на oDesk?

    Ubran_Hera
    @Ubran_Hera
    Начинал ~2 года назад (август/сентябрь) на oDesk (это была не первая моя попытка), выставил 14..15 баксов, без портфолио и истории. Первый заказ был получасовой, на 7 баксов, практически случайный (от новичка) — немного напортачил, но всё исправил, потратил времени в разы больше, но добился положительного отзыва.
    Общение сразу пошло через Skype и электронную почту, оплата — через PayPal. Это против правил, но так предложил заказчик.

    Затем оказалось, что работы у него непочатый край. До Нового Года переделывал маленькие сайтики (бизнес-проекты одного и того же человека). Взял меньшую плату, но повысил себе статистическую «среднюю ставку».

    Самое сложное было в графике и работе из дома — жена (девушка) не подходила ко мне когда я говорил по Skype/SIP, но в остальные моменты очень мешала и сбивала с толку. Ещё обижалась, что я ничего не делаю по дому и ложусь спать/встаю с разницей 3..4 часа по отношению к ней — одна комната, горящий монитор, гудящий вентилятор и т.д. Очень сложно было когда мы оба заболели (простуда).

    В итоге я понял, что никак не могу в таком режиме работать дольше 2 недель (у меня ещё есть постоянная работа в телекоме по сменному и практически ненормированному графику), а потом требуется месяц (!) отдыха. С девушкой пришлось расстаться, меня постигло разочарование во фрилансе на следующий год, когда я за месяц заработал сумму порядка $2000, но ни разу не покатался на велике (это был июль) и не побывал на природе/на пляже.

    Шашлык и вино действительно хоть каждый день и стойкое желание переехать куда-нибудь в англоязычную Канаду (тем более, что часто звали). Ставка на почасовые заказы сейчас 20..35.
    Иногда чувствую себя зомби (3 часа сна два дня подряд, потом 12 часов и всё равно не выспался, 6 часов, опять 2 дня по 3 часа, потом 14..15 на выходных).

    Жизнь повернулась так, что сейчас вынужден буду выплачивать пару кредитов, включая ипотечный.
    Выбор очевиден — уволюсь рано или поздно с основной работы (уже была попытка, в целом удачная) и стану совожаворонком (рано вставать и поздно ложиться).

    Success story неполная — не даю ссылки на профиль (у меня их несколько, в т.ч. приходилось заказывать самому у себя, но это оказалось ненужной глупостью). Так что не просите — за треть проектов, особенно первых ужасно стыдно, при том, что посмотрев на некоторые из них клиенты просят «и мне так же сделай», причём никогда не угадаешь заранее что может понравиться.

    Единственное, что радует — UK, CA, NZ, US AU — WeekEnd для них — это святое. На душе легко и спокойно с 3 утра субботы до 15:00 понедельника.
    Но бывает, что заказчик шлёт мне в полседьмого утра письмо с вопросом «Как продвигается наш проект» в 6:30 утра по его часовому поясу.

    С точки зрения разработки хорошо, что разделение testing/development/working environment очень чёткое и всегда есть время откатиться — начинаю обычно в час ночи и заканчиваю полпятого утра по их TimeZone, на живом, боевом сервере никогда не экспериментирую.

    Ну и по поводу каналов в Интернет — у меня 2 FTTx и 3 «свистка» — иногда так медленно заливается на хостинг, что приходится вспоминать командную строку и перепробовать их все.

    Зато индусы иногда вымораживают своим менталитетом, даже при хороших ставках.

    Ну и естественно, я стал замечать за собой НЕНАВИСТЬ к нашим местным наебизнесменам-работадателям, которые предлагают оклады 15..22 тыс. руб./мес. работникам с образованием и опытом, особенно после того, как устроившись в одну из местных фирм-конкурентов «тайным покупателем», вернее разработчиком (чтобы посмотреть workflow, т.к. это довольно успешный бизнес-проект с большой клиентской базой) увидел тот же Job Offer с oDesk, но очень плохо, безграмотно переведённый топ-менеджером компании в редких перерывах между поездками на дайвинги.

    В «малый бизнес» я тоже пытался уйти — очень сильная конкуренция, ценовая со школотой. Потом оказалось, что это ещё не главная проблема — рынок заказчиков всё равно растёт быстрее рынка исполнителей. Главная проблема — это чудовищная пропасть между опытом заказчика — НЕ ЗНАЮТ ЗАЧЕМ ИМ ИНТЕРНЕТ И НЕ ЗНАЮТ ЧЕГО ХОТЯТ и… ПОЛНЫМ ОТСУТСТВИЕМ ЖЕЛАНИЯ ПЛАТИТЬ профессионалам.

    Ещё поразило соотношение между уровнем разработчиков и наглостью в сочетаниями с понтами у менеджеров компаний-конкурентов. Не знаю кого винить — Фурсенко, или сразу Вашингтонский кагал, но пока встречался с потенциальными заказчиками (сейчас только телефон, а лучше -электронная почта) по три раза на дню бывал в ситуации, когда выплеснув на меня ушат откровенной технической ахинеи дядя-Вася-на-джипе на вопрос «Где вы нашли эту чушь?» начинал быковать в духе «Это мне сказали девушки в конторе ИП XYZ, А У НИХ ВСЁ ЧЁТКО, ВЕДЬ У НИХ САМ ИВАН МОИСЕИЧ ЗАКАЗЫВАЕТ САЙТЫ!»

    Короче oDesk — единственный шанс для заМКАДья, кроме восстания конечно.
    Ответ написан
    8 комментариев
  • MVC в PHP??????

    @egorinsk
    Что значит аналоги MVC? Есть модификации MVC типа MVVM или MVP (по сути, примерно то же), есть 3-tier архитектура (но вряд ли вы захотите ее делать на PHP).

    Я осваивал MVC на примере CakePHP (хотя сам фреймворк мне не нравится, он тупой, но как учебный пример годится). Просто прочтите прилагаемый к нему мануал, где приведен пример, как сделать блог с использованием подхода MVC.

    Паттерны вам пока не нужны. Все паттерны описаны в какой-то книге Мартина Фаулера (вот список: martinfowler.com/eaaCatalog/, там есть перевод на русский, но он плохой ), но, чтобы их понять, надо сначала иметь определенный опыт написания кода и разбора чужого кода. Если его у вас нет, для вас эти паттерны будут чем-то чужеродным и непонятным (много умных слов, а зачем это нужно, если можно по-простому написать).

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

    — DRY (не повторяйся) — не должно быть повторяющихся кусков в коде длинее нескольких строк, не должно быть генерации кода путем копипасты и правки, какие-то данные (к примеру, список стран) должны храниться только в 1 месте, а не в нескольких. Следование этому принципу улучшает архитектуру кода, упрощает поддержку.

    — KISS (делай как можно проще) — выбирай самый простой способ реализации, если есть несколько вариантов, и если это не грозит проблемами в будущем.

    — не ориентируйся и не используй фичи из PHP4. Он умер.

    — не полагайся только на HTML5/CSS3. Еще не у всех есть айпады с маками, и живы ИЕ8, ИЕ7 и ИЕ6.

    — пиши свой код, так, как будто после тебя его будет поддерживать псих-маньяк, который знает, где ты живешь. То есть, не пиши такие вещи, которые трудно/невозможно понять другому человеку. Думай о том, кто будет читать твой код. Изредка в сложных местах ставь комментарии. Не раскидывай логику выполнения действия по 10 файлам. Не делай файлы больше 500-1000 строк.

    — давай правильные названия классам, функциям, константам и переменным. Не используй транслит ($chisloPokupatelei). Не знаешь английский — вооружись Яндекс.Словарями/Гуглотранслейтом. Выбери и следуй стандарту кодирования (рекомендую Zend Coding Standard).

    — код на функциях можно легко превратить в ООП-код путем превращения функций в статические методы и объединения в классы.
    Ответ написан
    6 комментариев
  • Функционал vs Функциональность?

    Shultc
    @Shultc
    RnD Developer
    Что-то я подозреваю, что у вашего начальника какие-то проблеммы именно со вторым значением этого слова…
    Ответ написан
    1 комментарий
  • Куда жаловаться о СМС-спаме?

    спам-смс идут, как правило, через организации-партнёры опсоса, предлагающие такие услуги на рынке. У них есть бд номеров с признаками интересов и они торгуют рассылкой по этой бд. Соответственно, можно прийти в офис опсоса и тщательно проинструктировать их о том что не хочешь получать смс, рассылаемые подобными сервисами.

    Меня одно время внезапно начали спамить новинками ночной жизни дефолт-сити (хотя я не представляю, как мой номер попал в эту базу, т.к. моя ночная жизнь проходит или в кровати, или в серверной). Я зашёл в мегафоновский офис, десять минут убеждал младшего помощника старшего дворника, потом разозлился, дошёл до старшого и внятно объяснил, что у них варианты или оставить всё как есть, а я буду искать способы испортить хотя бы имидж мегафону, или напрячь булки и сделать так, чтобы в 00:02 мне не валились смс о том что дима иблан где-то выступает. Старшой согласился сделать всё что в его силах.

    Больше спама нет.
    Ответ написан
    Комментировать