• Где рациональнее соединяться с БД?

    @dmitryKovalskiy
    программист средней руки
    Если говорить про ASP.NET, который вы упомянули в комментариях -в своей практике наиболее часто встречал создание соединения непосредственно в методе, где исполняется запрос, с использованием синтаксического сахара using. Т.е. создали соединение,выполнили запрос, разорвали соединение. По PHP не скажу, но все же думаю вам надо для начала определится где вы будете писать ваш проект. Лично мне идея инициализации в конструкторе не нравится тем что есть ненулевая вероятность что соединение вы установите, возможно не используете никак, а когда оно будет закрыто не совсем понятно.
    Ответ написан
    6 комментариев
  • Считается ли плохим тоном, наследование PDO в класс вспомогательной обертки?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Вообще говоря \PDO - это чужой вендроский код, вам на прямую неподвластный (разве что сырцы пыхи пилить будете), так что лучше все таки обертку, так как она будет гарантировать вам постоянство интерфейса работы с БД.
    С другой стороны, если выделаете что-то не большое - выбирайте по удобству, если удобнее и быстрее наследование - пусть будет так, если обертка - тогда обертка. Руководствуйтесь здравым смыслом.
    Посмотрите Doctrine на досуге
    Ответ написан
    Комментировать
  • Стоит ли ip пользователя в таблице сессий хранить в хеше?

    sanchezzzhak
    @sanchezzzhak
    Ля ля ля...
    ip нужно хранить в числе если у вас будут выборки по диапазоном
    тип поля int + запретить отрицательные числа у колонки.

    Сохранять рекомендуют через INET_ATON но можно и через ip2long
    Ответ написан
    1 комментарий
  • Какими путями можно пройти в целях доработке системы авторизации?

    Пожалуйста, не используйте rand для генерации соли, guid, id сессий,... - не секурно.
    Ответ написан
    2 комментария
  • Как написать правильный preg_replace паттерн?

    alsopub
    @alsopub
    preg_replace('/[^A-Za-z]/', '', $s) -> WeathertodayC
    Ответ написан
    Комментировать
  • В чем проблема циклической перезагрузки MIUI 7?

    Chvalov
    @Chvalov
    Посмотрите DMESG, когда то мне помог при портировании прошивки.
    Вроде софт live dmesg, но не уверен.

    В вашем случае придется немного постараться чтобы dmesg вывести.
    Ответ написан
    Комментировать
  • Как сделать простой 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 комментарий
  • Чем куки отличаются от сессии в 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 комментария
  • Защищает ли PDO от SQL-инъекции?

    @ruslite
    Когда данные обработаны в PDO, они напрямую передаются драйверу базы данных, либо запрос строиться безопасным образом внутри данного расширения. Как можно заметить, это простой путь решения проблемы с SQL инъекциями.
    Однако при использовании предопределенных выражений совместно с PDO необходимо знать некоторые нюансы, чтобы избежать неприятных ситуаций. Например, в MySQL клиенте некоторые запросы, составленные посредством предопределенных выражений, не могут быть выполнены, а так же они не используют кэш, что может замедлить работу вашего web-приложения.
    Гарантированная безопасность при использовании предопределенных выражений звучит успокаивающе, но разработчики не должны принимать PDO и другие слои абстракции\предопределенные выражения за абсолютную защиту от взлома. Любые входящие данные должны проверяться, PDO – дополнительная линия обороны. Это расширение не закрывает все множество уязвимостей, посредством которых может быть нанесен вред вашей информации, но в то же время, PDO неплохо справляется с вопросом предотвращения SQL инъекций.

    Источник
    Ответ написан
    1 комментарий
  • Защищает ли PDO от SQL-инъекции?

    svd71
    @svd71
    Защищенность PDO от инъекций строится на использованании не динамически создаваемых запросов, но запросов с параметрами. Любой момент изменения запроса в коде под какие-то (часто необдуманные) нужды приводит к возможности инъекции.

    пример вам уже привели, повторю его:
    $qry = 'select * from users where user_id='".$usrname.'" and passwd='".md5($passwd.'$salt).'"';


    запрос подвержет инъекции: достаточно подсунуть имя с двойной кавычкой и далее через точкузапятую свой запрос. Остаток с паролем комментируется символами:

    $usrname = '"; update users set passwd="12345" where id="admin"; -- ';

    приведет фактически к такому запросу
    select * from users where id=""; update users set passwd="12345" where id="admin"; -- passwd=''


    совсем другое дело PDO. Он не допускает мультикомандные запросу как факт (то есть после первого select обработка не пойдет). А во вторых указанные инъекции просто запицется в параметры запроса, что будет обработанно корректно.
    Ответ написан
    1 комментарий
  • Где можно прочесть статью об алгоритме авторизаций с привязкой по IP?

    KOLANICH
    @KOLANICH
    Знаю JS, PHP, C++, C#
    просто сохраните айпи в поле массива $SESSION и проверяйте на каждой странице, если не совпадает - разлогинивайте (session_destroy).
    Если сервер - апач, используйте для этого опцию .htaccess php_value auto_prepend_file .
    Ответ написан
    Комментировать
  • Как решить проблему с методом jquery .before()?

    GeneMoss
    @GeneMoss
    void
    Используйте insertBefore вместо before. Параметром для before является контент, который вставлять, а не цель, куда вставлять.
    Ответ написан
    1 комментарий
  • Что означает конструкция (function($){$(function(){ })})($)?

    GeneMoss
    @GeneMoss
    void
    $(function(){}) — это мы запускаем действие в момент загрузки страницы. А оборачиваем в анонимную функцию (function($){ })($);, чтобы избежать конфликта имен с $.

    Автор плагина предусмотрел случай, когда доллар занят под другую библиотеку/функцию/переменную. Чтобы избежать конфликта имен, достаточно будет заменить доллар на jQuery, вот так (хотя сразу так и нужно было писать):
    (function($){$(function(){
        $('select').styleThis();
    })})(jQuery);


    Т.е. передав один раз нужный параметр, нам нет нужды переписывать весь плагин.
    Ответ написан
    1 комментарий
  • Что означает конструкция (function($){$(function(){ })})($)?

    Вызов функции $() с аргумментом в виде анонимной функции, внутри замыкания (closure) в которое передаётся $. Весь этот изврат нужен для того что бы не было проблем со сборкой мусора... на практике в JQuery это просто выполнение функции по событию onDocumentReady.
    Ответ написан
    Комментировать
  • Как вставить html в методами js, храня этот html в отдельном файле templates?

    ruFelix
    @ruFelix
    Предсказание будущего по руке, таро, кофе.
    Вы же сами фактически написали решение
    так и сделайте

    создайте js файл вида:
    var headline1 = '<div>...</div>'
    var headline2 = '<div>...</div>'
    var headline3 = '<div>...</div>'


    подключите его к ващей страниц:
    <script src="template.js"></script>

    И используйте:
    $("#box").append(headline1);
    Ответ написан
    Комментировать
  • Как вставить html в методами js, храня этот html в отдельном файле templates?

    Вот так:
    $( "#box" ).load( "ajax/test.html" );

    Опции: api.jquery.com/load/
    Ответ написан
    Комментировать
  • Понять взаимодействие - google public dns и jquery CDN - заговор? :)?

    romik
    @romik
    На официальном сайте: Dont getting stylesheets for jQuery website
    Ответ написан
    Комментировать