Что нового в PHP 5.4

Всем привет! Судя по слухам, 19 января, в свет должен был выйти очередной RC PHP 5.4. Возможно даже, что он будет финальным. А это значит, что нужно скорее заняться изучением новых возможностей.

Я несколько лет профессионально занимаюсь веб-разработкой и в качестве основного серверного языка использую PHP. Так что узнав о выходе столь крупного обновления, я отправился собирать информацию. Под катом shortlist самых значимых нововведений.



Примеси


Ключевая новинка 5.4 — примеси. Они послужат в PHP заменой мультинаследования. Каждая примесь задается отдельным «классом» через ключевое слово trait. Внутри примеси могут быть определены методы, которые станут доступны в классе, к которому будут подключены примеси. Подключение примесей происходит с помощью языковой конструкции use. Имена примесей задаются через запятую и все их методы становятся доступны внутри класса.

Если имена методов класса и примесей совпадают, то приоритетным методом станет метод класса. К сожалению, в этом случае мы не получим даже Notice.

Примесь всегда имеет доступ к классу, к которому она подключена, через конструкцию parent.

class A {
  public function foo() {
    return 'foo';
  }
}

trait B {
  public function bar() {
    return parent::foo() . ' bar';
  }
}

class C extends A {
  use B;
}

$c = new C();
echo $c->foo(); // foo
echo $c->bar(); // foo bar


Нативная поддержка Юникода


Да-да. Больше не придется использовать расширения, вроде multibyte и ему подобных. Все строковые функции отлично понимают юникод.

Array dereferencing support


Данная возможность — краеугольный камень для многих PHP разработчиков. Как часто нам нужно дернуть нулевой индекс у метода, который возвращает массив? Насколько сильно бесит то, что эту вроде бы простую операцию приходится записывать в две строки, да еще и переменную создавать? Теперь страдать больше не придется:

function foo() {
  return array(1, 2, 3);
}

echo foo()[0]; // 1


Short syntax for arrays


В PHP 5.4 теперь доступна короткая запись массива, без ключевого слова array.

// Раньше приходилось писать так:
$array = array(1, 2, 3);

// Теперь можно так:
$array = [1, 2, 3];

// И даже так:
$array = ['first' => 1, 'second' => 2];


Встроенный веб-сервер


Отныне, вместе с дистрибутивом PHP будет поставляться встроенный веб-сервер, предназначенный исключительно для разработки. Его можно будет запустить из консоли и повесить на какой-нибудь порт:
php -S localhost:8000

Upload progress


Несмотря на то, что в HTML 5 File API реализован механизм отслеживания процесса загрузки файла на сервер (размер загруженной части отдает сам браузер), в PHP 5.4 появится дополнительный источник мониторинга состояния загрузки. Он будет храниться в сессии пользователя в ключе, например, upload_progress_myform и мы в любой момент сможем дернуть его Ajax'ом для захвата мира отрисовки прогресс-бара.

Вызов метода или свойства класса выражением


Еще одно приятное нововведение, которое поможет нам сэкономить строчку кода. Для того, чтобы вызвать свойство или метод класса, не нужно будет больше запоминать его в отдельную переменную.

class A {
  public static function foo_bar() {
    return '123';
  }
}

$foo = 'foo';
$bar = 'bar';

echo A::{$foo . '_' . $bar}(); // 123


Scalar type hints


PHP явно идет в сторону строгой типизации. Раньше для автоматической проверки типа в аргументах метода можно было указывать только массивы и имена классов. Теперь такая возможность распространяется на некоторые другие типы: int, float и boolean.

function foo(int $a, bool $b) {
  return true;
}


Улучшена производительность @


Оператор @ служит в PHP для отключения вывода ошибок на текущей строке кода. Раньше в высоко нагруженных приложениях использовать @ было невозможно из-за довольно ощутимых тормозов. Поэтому лично я ее больше не использую нигде.

В конце-концов приглушать ошибки — это странно. Ошибки нужно исправлять или ловить Exceptions.

Deleted


Кроме того из PHP наконец-то выпилены register_globals, long_arrays и прочие директивы, заждавшиеся удаления.

Использованная литература




Update: Исправил trail на trait, приношу свои извинения, спасибо DoctorChaos за наводку.
Update 2: Scalar type hints в PHP 5.4 не будет. Не смотря на это заявление, в SVN тэге 5.4 scalar type hints нет :( Спасибо Irker и sectus.

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 340

    +4
    Указание типа для аргументов и trails радуют.
      +2
      В тайп-хинтинге не будет неявного приведения типов. Т.е. '42' в int $a не передастся.

      А если учесть, что у нас все данные снаружи приходят в строках — то весь код превратится в бесконечное явное приведение типов.

      Итого — язык превратился из языка со слабой динамической типизацией в непонятно что.
        0
        Функции снаружи не вызываются. К тому же никто не заставляет использовать хинтинг.
          0
          Функции вызываются вашим кодом, а данные приходят именно снаружи

          foobar($_POST['int']); — и вам придётся использовать (int) для приведения к целому.

          Никто не заставляет, да, но почему было не сделать неявное приведение, как это сделано везде в пхп, а конкретно здесь идти по особому пути — лично мне непонятно
            +2
            Думаю, что тогда и в таких конструкциях нужно будет задействовать преобразование:
            public function test(Itest $test){}

            Но я с вами согласен. Без приведения и правда становится грустнее.
              –3
              возможно потому, что хотят сделать как в си, но утверждать точно не буду.
              class bar {
              function foo(int $a) {
              }

              function foo(array $a) {
              }
              }


              но все же, иногда, строгая типизация бывает очень даже полезна.
                +1
                С языках со статической типизацией — да, полезна. А делать из динамического языка — статический, только людей смешить. Как раз по тем причинам, что вместо программирования вы теперь будете сидеть и жонглировать явными приведениями
                  0
                  но ведь никто не заставляет это использовать повсеместно.
                  При этом для какого-нибудь Factory записи станут проще
                    0
                    Повсеместно — нет, но теперь как только вы захотите использовать какую-нибудь стороннюю библиотеку, которую писал вот такой «умник» — то привет

                    foobar((int) $a, (float) $b)
                +2
                Раньше я писал
                function foobar($id) {
                $param = (int) $id;

                }
                foobar($_POST['id']);

                теперь буду

                function foobar(int $id) {

                }
                foobar((int)$_POST['id']);

                Второй вариант, по-моему, более читаемый, что при объявлении функции, что при вызове. При объявлении не нужно приведения, и в обоих случаях сразу видно, что foobar ждёт число.
                  +4
                  Раньше вы написали (int) раз и навсегда, а теперь все клиенты вашего метода обязаны его писать также.

                  Отлично просто стало.

                  Что foobar ожидает должно быть понятно из документации и подсказок IDE во время написания кода, и из имен переменных во время чтения.
                    +2
                    class MyClass
                    {
                        public function __construct()
                       {
                            $query = $this->registry
                                                   ->get_service('InputQueryBuilder')
                                                   ->get_query_object();
                    
                            $this->some_method($query->get('id', 'int')); // первый параметр - ключ, второй - ожидаемый тип
                        }
                    
                        protected function some_method(int $id)
                        {
                            // тело метода
                        }
                    }


                    Используйте инкапсуляцию запроса в объекте и будет вам счастье.
                      +2
                      Я приницпиально не понимаю чем

                      $query->get('id', 'int')

                      лучше

                      (int)$query->get('id')

                      И ещё больше я не понимаю как ваш ответ решает необходимость указания типа везде вместо одного места раньше
                        0
                        $query->get('id', 'int') лучше, чем (int)$_POST['id']. Если вы не хотите везде указывать тип, то можно реализовать метод set_type($key, $type), который будет приводить значение ключа к типу и хранить его с этим типом в объекте запроса в дальнейшем. Тогда приведение нужно будет сделать только один раз, а если это не было сделано, то об этом подскажут сообщения о несоответствии типов.
                          +1
                          >> $query->get('id', 'int') лучше, чем (int)$_POST['id'].

                          Чем? Вторая запись гарантирует итоговый тип аргумента, а первая — без просмотра реализации вообще непонятно что делает.

                          Перечитайте, пожалуйста, мой комментарий снова. Моя мысль была о том, что теперь вы в клиентском коде обязаны будете везде таскать нужные типы. А в случае изменения сигнатуры, опять же, по всей тонне клиентского кода бегать и менять вызовы.
                            +1
                            Если вы имеете в виду ТОЛЬКО приведение к типу — то использование (int) безусловно нагляднее. Я же говорю о комплексной работе с запросом, раз уж ветка началась с идеи «все входящие параметры — строки, что делать дальше». Продолжим дальше на примере с id, полученным из браузера пользователя вместе с запросом:
                            use /Project/Validator/ValidatorI as V,
                                  /Project/Validator/Exceptions/ValidatorException;
                            
                            // класс обладает знаниями о том, как выполняется определенное действие,
                            // запрошенное пользователем, и о том, какие типы и граничные значения
                            // имеют входящие параметры
                            class SomeActionController
                            {
                                protected function validate_query(array $params)
                                {
                                    try
                                    {
                                        // $params['id'] передается по ссылке 
                                        // и после валидации имеет заданный тип
                                        $this->validator->validate($params['id'], V::INT|V::UNSIGNED|V::NOT_NULL); 
                                    }
                                    catch (ValidatorException $e)
                                    {
                                        // обработка ошибки
                                    }
                            
                                    $this->some_method($params['id']);
                                }
                            }

                            В этом примере я пытаюсь показать, что если вы работаете в рамках фреймворка / CMS, то есть следующие особенности архитектуры:
                            1. Встроенный механизм комплексной проверки значений, с возможностью приведения к типу
                            2. Проверка значения и, соответственно, его типа происходит в одной точке и если проверка провалилась, то код сообщает об ошибке и прерывает исполнение. Далее используется уже проверенное и приведенное к типу значение, а не сырое значение из запроса
                            3. В модуле, который использует данные, имеются необходимые для проверки типа / границ допустимых значений знания
                            4. Переменная меняет свой тип в результате изменения логики работы модуля, а не наоборот
                            5. Соответственно, указание типа в сигнатуре должно применяться именно в тех случаях, когда от него зависит работоспособность кода, что хорошо демонстрирует пример с id, который всегда имеет тип integer, не может быть отрицательным, и обычно больше нуля
                              0
                              По всем пунктам согласен.

                              Однако используемый подход вы могли использовать и без тайп-хинтинга скалярных типов :-)

                              Итого: если вы пользовались тем, что вы описали — то для вас с появлением хинтов ничего не меняется. А если вы не пользовались этим всем — то введение хинтов на скаляры добавит головной боли.

                              Нет?
                                +2
                                Безусловно да :) Но поскольку я считаю, что дисциплинировать программиста можно только тогда, когда код максимально строг, и за ошибки бьет по рукам, то хинтинг типов будет одним из способов заставить программистов, использующих мой код, пользоваться встроенными средствами валидации, а не бездумно пихать непроверенные данные в нижележащее ядро фреймворка. Вариация технофашизма, я бы сказал.
                                  0
                                  Может тогда на c# начать писать? :-)
                                  Там о подобных ошибках вы бы узнавали ещё на этапе сборки проекта :-)

                                  Ладно, не буду оффтопить, мы сошлись во мнении и это главное :-)
                      0
                      Никого не заставляю пользоваться своими методами :)

                      Нет документации и IDE ничего не подсказывает, она-то откуда знает число или строку я ожидаю в качестве id, если я не напишу function foobat(int $id). Есть, конечно, phpdoc, но меня его писать не заставляют. А насчёт имён — вводим венгерскую нотацию? nId вместо Id?
                        –1
                        Не, не вводим. Имени должно быть достаточно ;-)

                        Но так или иначе — ваш «вариант 2» приводит к раздутому коду (для того, чтобы написать то же самое — клавиш нажать придётся больше)
                          0
                          Ну вот как может быть достаточно имени Id? Идентификатор может быть любого типа.

                          Очень многие способы «раздутия кода» улучшают читаемость и уменьшают количество возможных ошибок.
                            0
                            Уменьшают количество ошибок, совершенно верно.

                            Вы изменили сигнатуру метода в связи с переездом int $id на string $id.

                            Раньше для вас потребовалось бы изменить лишь тело метода (изменить принудительное кастование).

                            Теперь вам придётся по всем 100мб кода бегать и делать поиск-замену. Вероятность ошибки >> 0.
                              0
                              Сишники и явисты как-то же справляются, ещё и утверждают, что из-за статической типизации код у них надежнеё.
                                +2
                                Потому что у них язык строго типизированный со статической типизацией. А пхп у нас слабо типизированный с динамической. И появление ущербной реалазиации тайп-хинтинга никак положение дел не изменит.

                                Равно как и не позволит появиться волшебным инструментам для рефакторинга и статического анализа, потому что язык по факту тот же самый, но с орешками.
                              • UFO just landed and posted this here
                                  0
                                  Т.е. вы предлагаете делать класс-обёртку (см. костыль) только для того, чтобы потенциальный недостаток языка нивелировать. Правильно?

                                  А веское основание — мы ушли от секвенций и решили использовать UUID.
                                  • UFO just landed and posted this here
                                      –1
                                      >> В один прекрасный день мы обновляем бинарную библиотеку, и она начинает требовать других типов входящих параметров. Теперь вопрос: как заставить весь проект работать с новой библиотекой?

                                      В том-то и дело: пхп язык с динамической слабой типизацией. В случае с пхп «раньше» — ничего страшного не произошло бы.

                                      Не скатывайте дискуссию в кривую архитектуру, это всё софистика.

                                      Ошибка разработчика — только теперь уже языка, а не приложения, в том, что сейчас в некоторых частях пхп неявное приведение будет, а в некоторых нет.
                                      Это подарок в копилку несогласованных именований функций и порядка следования аргументов.
                                        0
                                        Неявное приведение было реализовано и так. Пишем $node_id=$id % $nodes_count и не обращаем внимание, что $id строка. И теперь мы можем его реализовать, просто не используй хинтинг. А вот если нам нужно явное приведение, мы его используем. Повторюсь, никто не заставляет вас использовать все возможности языка. Как никто не заставляет использовать библиотеки их использующие. В конце-концов, если библиотека свободная, то форкните её и удалите int в сигнатурах. Заодно сравните, какая большей популярностью будет пользоваться.
                                          0
                                          Популярностью всегда будет больше пользоваться библиотека от известного (см. оригинального) автора :-) Часто — вне зависимости от качества кода.

                                          Т.е. ваша позиция: всё равно, что у языка часть вещей делается неявно, а часть явно?
                                            0
                                            Не всё равно, а хорошо. Там где я хочу чтоб делалось явно, я это декларирую, где не хочу полагаюсь на неявное.
                                        • UFO just landed and posted this here
                                    –1
                                    Никто никого не заставляет, дело же добровольное! :)
                                    И даже по всем 100Мб кода бегать никто не заставляет — есть шикарные функции рефакторинга в любой нормальной IDE и делается это на 30 секунд дольше чем «изменить лишь тело метода».
                                    Плюсы вам привели — валидация значения внутри, а не извне.
                                    Разработчики IDE могут применять более продвинутые алгоритмы code-completion.
                                      0
                                      Не сможете вы отрефакторить с гарантий безошибочности изменение типа в сигнатуре, потому что неизвестно когда приведение к этому типу осуществляется в клиентском коде.
                                        0
                                        Насчёт рефакторинга вы не совсем правы. Если используется «магия» типа $object->$method($id); то проблемы могут возникнуть, и IDE мало поможет, только тесты.
                                  +3
                                  Почитайте Спольски, венгерская нотация должна использоваться не для указания типа переменной, а для указания какого-либо аспекта хранящихся в ней данных.
                              0
                              Я бы не стал так бесцеремонно передавать внешние данные напрямую в функцию, которая должна с ними работать. Скорее уж foobar( $request->get('int') ) или вообще foobar( $request ).
                                0
                                > но почему было не сделать неявное приведение

                                Ну, потому что это НЕ будет уже типизацией, а будет приведением типов, не более того… а это совсем другое.
                              0
                              Птому что явное приведение типов в неочевидных случаях — это правильно.
                                0
                                1. $object + 42
                                2. '42' + 42

                                В обоих случаях будет произведена попытка привести объект и строку соответственно в число. Это для вас очевидно?

                                А чем для вас приведение '42' как аргумента, объявленного как int — неочевидно?

                                Как раз в случае сигнатуры метода тип определён статически, а в арифметике — тип вообще в явном виде НИКАК не фигурирует.
                                  –2
                                  Первый пример — должен падать с ошибкой.
                                  Второй должен выполнять единственное очевидное действие, и преобразовывать 42 в строку, тем самым образуя '4242', хотя и это тоже можно поставить под сомнение, будучи особым пуристом.

                                  Приведение '42' к инту для меня неочевидно потому, что если я так написал, значит я ошибся, и я хочу получить на это ошибку. Если я хочу преобразовать строку к числу, я буду использовать прямой метод преобразования, потому как можно выполнить такой преобразование десятком спобосов. Навскидку: '0x10' — ошибка или 16, '3000000000' — ошибка или unsigned, или bignum, или на флоат подменить, '1.0' — ошибка или 1, '01' — ошибка или 1, '-0' — ошибка или 0,.
                                    0
                                    Проблема в том, что второй пример сейчас в пхп работает. И ваше предложение превратить пхп в язык со строгой типизацией приводит к тому, что в некоторых местах пхп осуществляет неявное определение, а в некоторых — нет. Таким образом ведёт себя неконсистентно.

                                    И наряду с разным стилем именования функций, разными порядками аргументов в схожих функциях у нас появляется ещё одна особенность, о которой нужно знать и постоянно помнить
                                      0
                                      Я не предлагаю ничего для ПХП. Вообще ничего. Для меня ПХП — богом забытый язык, на котором я, конечно, могу писать при сильной необходимости, но врядли выберу как язык решения какой-либо задачи, если не возникнет внешних ограничений(Стоит понимать, что «у меня тут апач с пхп, и мне надо хапустить прототип через час» — вполне себе ограничение, хотя в таком случае я все равно скорее всего выберу haXe.).
                                +6
                                Вы не правильно понимаете назначение type hinting. Его нужно использовать ТОЛЬКО ТОГДА когда я ожидаю конкретный тип данных на входе, чтоб не писать лишних if. Потому и не происходит неявное приведение, потому что оно там быть НЕ ДОЛЖНО.
                                  +1
                                  В ПХП данные из всех внешних источников приходят в строках.

                                  Если вы работаете с внешними данными и у вас не строка — значит кто-то до вас это явное приведение всё таки сделал.
                                    0
                                    Т.е. взаимодействие слоев кода между собой вы не рассматриваете в принципе?
                                      0
                                      В слоях кода данные тоже появляются откуда-то.

                                      Вы предлагаете только в части проекта использовать тайп-хинтинг?

                                      Как вы тогда формализуете необходимость его использования в code conventions проекта? «Тогда когда нужно» — не является формальным определением.
                                        +1
                                        В слоях кода данные появляются из внешнего кода, а во внешнем коде данные могут быть в любом виде.
                                        Насчет формализации: а вы каждую фичу языка описываете в code conventions?
                                        Type hinting подходит для библиотек или модулей напрямую не взаимодействующих с пользователем. Хотите — можете так и записать :)
                                          0
                                          Не каждую фичу, но для каждой специфичной конструкции языка должна быть описана применимость и способ записи. Иначе это не CC.

                                          База — не пользователь, данные в строках.

                                          Тогда может «напрямую не взаимодействующий с любым внешним источником»

                                          Так или иначе — я вас понял. Через годик посмотрим, во что превратится код
                                            0
                                            Нормальные ORM преобразуют строки от PDO в PHP типы в соответствии с маппингом. Даже в объекты преобразуют, не то что в int или bool.

                                            А вообще не нашёл я в ченжлогах scalar type-hinting. Только callable нововведение вижу.
                                              0
                                              Нормальные ORM и тапочки могут приносить.

                                              В случае с «нормальными ORM» нам тайпхинтинг не нужен был и не нужен будет, потому что у нас данные и так гарантированно с нужным типом.
                                                0
                                                Вызов функции/метода может быть как с параметром от ORM, так и с другим. Мне проще писать функцию, где мне гарантированно приходит параметр с нужным типом, а не думать о том, стоит ли NULL приводить к 0 или выбрасывать исключение.
                                      0
                                      Справедливости ради нужно заметить, что не из всех. В качестве контрпримеров — данные из bound variables в PDO, данные из prepared statements в mysqli, данные из pecl/mongo, данные из DOMXPath::evaluate, результаты yaml_parse_url и т.п.
                                        –1
                                        Они так же приходят в строках, а потом кастуются. Автоматически, но это ничего не меняет
                                    0
                                    Данные снаружи сначала нужно фильтровать. Поэтому приведение данных полученных извне к ожидаемым типам данных вполне нормальная практика имхо. Если мы ждем от пользователя целое число, а он нам передает и мы сразу же передаем это в функцию — это как бы не хорошо.
                                      0
                                      Я согласен с вами, что данные нужно валидировать, но не согласен с тем, что валидация как-то связана с приведением типов.

                                      Если мы ждём от пользователя целое число — то мы можем применить ctype_digit() и не кастовать данные
                                  +14
                                  Радуют все изменения. Особенно полная поддержка юникода.
                                    –5
                                    Где вы увидели полную поддержку юникода? Её пока не сделали.
                                      0
                                      Одним из подтверждений будет, например, новая настройка в php.ini (http://cn2.php.net/ini.core.php) — zend.multibyte, которая по умолчанию установлена в false.

                                      Кроме того можно посмотреть список багофиксов, в которых очень много изменений связано с юникодом и введением его поддержки. И хотя в официальном чендж листе нет фразы «Мы добавили юникод», можно с уверенностью сказать, что в 5.4 о в том или ином виде будет.
                                        +1
                                        Под полной поддержкой юникода я бы ожидал увидеть его поддержку на уровне кода, а не только на уровне строковых литералов. Поддержка юникодных строк без его полной поддержки вероятнее всего даст просадку производительности.
                                          0
                                          Вот именно «в том или ином виде будет», а полной поддержки не будет.
                                      +6
                                      наконец выпилили register_globals
                                        +8
                                        Весьма интересно.
                                        С массивами — казалось бы мелочь, но ведь так не хватало…
                                          –5
                                          Честное слово, примеси в пхп — это какое-то недоразумение
                                            +2
                                            Захотелось спросить на каком языке вы программируете :)
                                            Отличный вброс, покормлю пожалуй.
                                              0
                                              я больше 5 лет программил на пхп
                                              последние 2 года на питоне, немного руби, немного эрланг и жс на ноде
                                              –1
                                              Да ладно, недавно делал систему поиска недвижимости, была куча типов недвижимости — строение, офис, квартира, участок и т.п., у каждого типа свой набор свойств, большинство из которых повторяется в большинстве объектов, но есть много уникальных. Чем хардкодить кучу подклассов или читать конфиги классов из файлов и динамически создавать в них свойства/методы — в разы легче, проще, удобнее, быстрее было бы сделать это с трейтами.
                                                0
                                                Я тоже недавно делал такую систему. Не вижу принципиальной разницы между наследованием и трейтами. use Common или extends Common… Другое дело, когда наследование нежелательно или невозможно, например все классы модели/контроллера уже наследуются от ActiveRecord или Controller или вообще не имеют общего в терминах предметной области, но вот чисто по коду имеют много общего, например реализация стандартных интерфейсов типа Iterator или ArrayAccess.
                                              +12
                                              Порадовала короткая запись массивов.
                                              Теперь удобнее будет передавать их в качестве аргументов в функции:
                                              $obj->method([
                                              'foo'=>'bar',
                                              'bar'=>'foo'
                                              ]);

                                              теперь это напоминает JavaScript ;)
                                                +1
                                                Ага. Вроде мелочь, но выглядит значительно лучше.
                                                  –12
                                                  Зачем? не лучше объявить

                                                  /**
                                                  @var int $foo
                                                  @var string $bar
                                                  **/
                                                  function method($foo, $bar)?
                                                    0
                                                    Ну, например, затем, чтобы делать внутри функции аналог джаваскриптовых пополнений объекта умолчаниями — таких, как $.extend(), _.extend(), _.defaults().
                                                  +3
                                                  > в PHP 5.4 появится дополнительный источник мониторинга состояния загрузки.
                                                  > Он будет храниться в сессии пользователя в ключе, например, upload_progress_myform
                                                  Может ктонибудь пояснить как оно будет работать? У меня, например сессии в базе. Upload делается перед запуском скрипта, поэтому поставить свои обработчики сессии в скрипте, который принимает закачку, нельзя. Как же php сам сможет записать в сессию нужное значение?

                                                  И еще, раз сессия будет перезаписываться десятки раз во время закачки, значит здравствуй здоровенный io?
                                                    –11
                                                    Встречный вопрос: для чего вы храните сессии в базе?

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

                                                    По умолчанию в пхп сессии хранятся на диске, т.е если бы мне хотелось ускорить что-то в этом и так быстром месте, то логичнее переместить сессии в memcache, но уж никак не в базу. Значит причина не в скорости.

                                                    Т.е у вас была причина пожертвовать скоростью ради… чего?
                                                      +17
                                                      Звездец. Я разве об этом спросил?
                                                        –1
                                                        А я и не отвечал на ваш вопрос, просто стало интересно зачем это может понадобится.
                                                          +2
                                                          «например»
                                                            0
                                                            Например просто получить «сейчас на сайте хх человек»
                                                              0
                                                              Ну так для этого не обязательно хранить сессии в базе.
                                                                0
                                                                Ну хорошо если этот пример не нравится, то еще появляется возможность просто поправить данные одной сессии из другой.
                                                                  0
                                                                  И для этого база тоже не обязательна.
                                                                    +2
                                                                    Тогда база и для хранения данных не обязательна, ведь можно использовать ФС вместо неё. А база не обязательно хранится на диске, можно дать таблице сессий тип memory, и иметь все преимущества скорости доступа к оперативной памяти и базы даннях храня сессии в базе.
                                                                      +2
                                                                      Ну конкретно с memory могут быть проблемы — потому что там поле типа text создавать нельзя, а в сессии, бывает, СТОЛЬКО данных понапихают )))
                                                                        +1
                                                                        Для плоских данных типа сессий — да. База не нужна. Поэтому и используют мемкеш или apc. Получается не база а key-value хранилище.

                                                                        В случае если мы используем тип таблиц memory все ок, но все еще не видно очевидного профита.
                                                                        Т.е программист написал хендлеры для базы, сделал таблицы особенного типа. Т.е потратил на это время. Он очевидно должен был получить какой-то очень полезный бонус в замен. Вот я спрашиваю — что это за бонус?
                                                                          0
                                                                          Доступ к сессиям извне, простое изменение данных всех сессий из php.
                                                                            +3
                                                                            load balancing + REST. Пнрвый запрос пришел на один сервер, второй — на другой. Как восстанавливать контекст пользователя?
                                                                              –2
                                                                              биндить юзера (сессию) к одной ноде например :)
                                                                                0
                                                                                Все равно поиск в базе будет происходить. И что будем делать, когда у нас пришли все юзеры именно этой ноды? ;)
                                                                                  –1
                                                                                  а что мы будем в базе искать, то? Пришли и пришли, что с того?
                                                                                    0
                                                                                    > а что мы будем в базе искать, то?

                                                                                    Каким образом будет происходить следующее:
                                                                                    биндить юзера (сессию) к одной ноде например :)

                                                                                    ?

                                                                                    Маленькими гномиками и магией?

                                                                                    > Пришли и пришли, что с того?

                                                                                    Клиентов всегда больше, чем серверов. Обычно намного больше. Если ты жестко привязываешь пользователя к ровно одному узлу — добро пожаловать в DoS в случае, если на эту ноду внезапно придут большинство пользователей, привязанных к этой ноде.
                                                                                      0
                                                                                      Жестко пользователей привязывать это перебор, конечно, но вот открываемую сессию к наименее нагруженной ноде (реальной нагрузке или по числу обслуживаемых сессий), по-моему, в большинстве случаев должно хватить без необходимости расшаривать данные сессии между нодами
                                                                  +1
                                                                  ИМХО, кросдоменная авторизация… Работал давненько в одной конторе, где была куча проектов на поддоменах и для того чтобы сеесия оставалась неизменной с ней работали через БД.
                                                                  З.Ы. Придумывал такой вариант не я, я только привел пример!
                                                                +2
                                                                Ну например, стоит использовать базу данных для хранения сессий в том случае, если у вас количество серверов, которые обрабатывают запросы пользователей, больше одного. В этом случае вам файловая система и тем более APC не подходят. Memcached же не подходит по той причине, что данные сессий старых пользователей могут быть вытеснены новыми данными. Вам же, например, не очень приятно, когда вы заходите на какой-нибудь сайт каждый день, а он постоянно просит вводить у вас логин и пароль и не запоминает авторизацию. Это же плохой user-experience.
                                                                Именно поэтому имеет смысл сохранять данные сессии в персистентное внешнее хранилище данные, которое может быть и MySQL-ем, и Redis-ом или вообще каким-нибудь Membase-ом.
                                                                  +1
                                                                  > Вам же, например, не очень приятно, когда вы заходите на какой-нибудь сайт каждый день, а он постоянно просит вводить у вас логин и пароль и не запоминает авторизацию.

                                                                  Это уже куки, а не сессия.
                                                                    +3
                                                                    На всякий случай расскажу как работают сессии в PHP:
                                                                    Когда вы начинаете работать с сессионными данными для подключения, php задает куку с именем, который вы указываете в конфиге (по умолчанию PHPSESSIOID вроде) и уникальным значением, которое хранит в себе ID сессии пользователя. При каждом запросе к скрипту идет выборка этой куки и поиска сессионных данных, что соответствуют этой куке. Если сессионных данных не будет найдено, например, по причине того, что они хранились в APC, а вы перезапускали свой апач, то соответсвенно и слетит авторизация.
                                                                      +4
                                                                      Тогда и я на всякий случай напомню Вам как работают сессии в PHP.

                                                                      Как вы правильно заметили, php создаёт куку для сессии, но не заметили одно, что эта кука собственно живёт до конца сессии (пока не закрыли браузер, не беря в расчёт, что сейчас многие браузеру восстанавливают сессии, но я этим не пользуюсь, но многие сайты всё равно помнят мой пароль).

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

                                                                      Конечно, плохо, если сессия «поломается» при простом сёрфинге по сайту, но надо так рассчитывать нагрузку и объём, который будет в сессии храниться.
                                                                        +2
                                                                        Да, вы правы. Приношу извинения, не стоило мне отвечать в таком тоне. :-)
                                                                          +3
                                                                          www.php.net/manual/ru/function.session-set-cookie-params.php — тут уж как настроишь))) Описывваемое вами поведение это поведение по-умолчанию.
                                                                            0
                                                                            Действительно, спасибо, будем знать.
                                                                      0
                                                                      Про ввод паролей вы плохой пример привели — никто не реализовывает вечноживущие сессии для этого, а просто поднимают новую с уже известным user_id. По остальным доводам — да, +1
                                                                        0
                                                                        Не совсем понял механизм, что вы предлагаете для вечноживущих сессий.
                                                                        В любом случае, нужно хранить куку в какой-то базе данных, которая связана с профилем пользователя, по которой и проводится аутентификация.
                                                                          0
                                                                          Я как раз предлагаю никогда не использовать вечноживущие сессии вообще.
                                                                          А в куке просто лежит рандомный идентификатор который где-то в хранилище однозначно связывает нас с user_id.

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

                                                                          Повторю: это не вечноживущие сессии, сессии в этом случае живут сколько и должны жить :-)
                                                                            0
                                                                            Ага, понял вас. По всей видимости мы немного по разному интерпретировали понятие сессии. Я имел ввиду не те данные, что хранятся в $_SESSION, а немного более широкое понятие.
                                                                            А так да, конечно, стоит разделять данные, которые должны храниться для пользователя максимальное количество времени и данные, которые необходимо знать только в рамках текущей сессии (простите за тавтологию :-) ). К этим данным разные требования и, соответственно, разный механизм работы с ними.
                                                                          0
                                                                          Мммм, а откуда user_id становится заранее известным?
                                                                            0
                                                                            Из отдельной куки, являющейся ключом к таблице (или ещё какого хранилища), где есть user_id
                                                                              0
                                                                              То есть предлагаете городить огород вместе вечноживущих сессий? А зачем?
                                                                                +2
                                                                                А зачем вам вечноживущие сессии? Не стреляйте из пушки по воробьям.

                                                                                Задача: уметь производить аутентификацию пользователя через неделю.

                                                                                Решение с отдельным хранилищем: узкоспециализированное, решает конкретно эту задачу.

                                                                                Решение с вечноживущими сессиями: вместе с необходимыми данными также сохранит кучу потенциально ненужного мусора.
                                                                                  +1
                                                                                  Тут вас поддержу :)
                                                                                    +3
                                                                                    Мне надоело спорить уже, кстати. Сдаюсь везде, где не был прав на 100% ))
                                                                                    0
                                                                                    Я только хотел узнать: какого мусора?
                                                                                      0
                                                                                      В сессиях часто хранятся значения, которые имеют смысл только «здесь и сейчас». Это и есть мусор
                                                                                        –1
                                                                                        Задам, возможно, крамольный вопрос: что мешает удалять значения из сессии, когда здесь и сейчас закончилось?
                                                                                          +1
                                                                                          А откуда мы знаем, когда оно закончилось? К примеру — время жизни неких данных == пользовательский сеанс работы (равный времени среднестатистической сессии).

                                                                                          Пример данных: кэш каких-то не очень важных данных.

                                                                                          Как мы узнаем, когда удалять их? Положили в сессию, сессия протухла, PROFIT
                                                                                            0
                                                                                            Стоп. Вы не обижайтесь, но кэш, хранящийся в сессии, пахнет сливами.
                                                                                              0
                                                                                              Окей, это не кэш, это список посещённых в этой сессии страниц
                                                                                                –1
                                                                                                Не вижу абсолютно никаких проблем в вечно хранящемся списке посещенных страниц (еще желательно с таймстампами и прочими полезными данными). Думаю, разработчики поисковых гигантов и рекламных систем меня поддержат.
                                                                                                  0
                                                                                                  В вечно хранящемся списке где? В вечно живущей сессии?
                                                                                                  Или в базе?

                                                                                                  Следующий кандидат — csrf токен. Слишком долго живущим делать нельзя, сессионный ttl — как раз окей.
                                                                                                  0
                                                                                                  Но для этого (как и для кэша) должно быть реализовано отдельное специализированное хранилище.

                                                                                                  В сессии хранятся (должны хранится) как раз те данные, которые не потеряют актуальность, даже если пользователь впал в кому или на телефоне закончились деньги. Например, адрес, который пользователь ввел в форму заказа, а потом решил нажать назад, чтобы посмотреть что-нибудь еще. Или идентификатор самого пользователя. Или личные предпочтения (но вообще для них тоже должно быть создано более идеальное хранилище).
                                                                                                    0
                                                                                                    Кому «должны»? В сессии могут храниться любые данные, которые мы хотим.

                                                                                                    Первые шаги длинной формы, в начале которой пользователь вводил данные от сторонних ресурсов и которые устаревают через некоторое время.

                                                                                                    Зачем сохранять их перманентно? Не нужны они нам перманентно
                                                                                                      0
                                                                                                      Кому «нам»?
                                                                                                        0
                                                                                                        Никому они не нужны. У вас по обсуждаемой теме есть что ещё сказать, или вы перешли на стратегию «и чо?»?
                                                                                                          0
                                                                                                          Ох. Я вам говорю — каждому-свое, и в сессии не должно быть кэша, а вы мне отвечаете: ну, «нам» нужно обязательно запихнуть в сессию «данные, которые могут протухнуть» (хотя это и есть вольное определение слова «кэш») и гнете таким образом свою линию. Ок, продолжайте.
                                                                                                            0
                                                                                                            Ок, расскажите, зачем нам нужны сессии длиной в год.

                                                                                                            Вы же предпочитаете специализированные хранилища для каждой задачи, как вы выше сказали — давайте тогда от этого и отталкиваться.
                                                                                                              0
                                                                                                              Не в год, а в вечность, хе-хе:)
                                                                                                              Ну поймите же, у сессии в идеале вообще не должно быть экспайра. Экспайр может быть у кэша (хотя и там он совсем не обязателен, по крайней мере в идеале для кэша лайфтайм должен быть по умолчанию тоже вечностью, если явно не указано другое), но поскольку у нас нет квантовых хранилищ информации, нужно как то стирать случайных посетителей. В то же время, если человек выбирает «ЗАПОМНИТЬ меня», приборчик обязан его, черт побери, запоминать! В самом деле, вы же за забудете человека, если один раз запомните его? А веб-сайты это постоянно делают, сплошная ложь кругом.
                                                                                                                0
                                                                                                                Вы всё таки не ответили — зачем бесконечные сессии?

                                                                                                                «В идеале» — не аргумент.

                                                                                                                >> в идеале для кэша лайфтайм должен быть по умолчанию тоже вечностью
                                                                                                                Тогда ресурсы будут тратиться на инвалидацию.

                                                                                                                >> В то же время, если человек выбирает «ЗАПОМНИТЬ меня», приборчик обязан его, черт побери, запоминать!
                                                                                                                Должен. Посмотрите выше — вы за «специализированные» персистентные хранилища под каждую задачу. Сессия — не специализированное и не персистентное. Если человек потеряет сессионную куку (или пересядет за другой браузер) — тогда данные потеряются.
                                                                                                                  0
                                                                                                                  Я отвечу еще раз не зачем, а почему. Потому что в хранящихся ограниченное время сессиях есть небольшая проблема. Дело в том, что разные данные имеют тенденцию протухать с разной скоростью, так что например приведенный вами пример длинной формы может храниться несколько дней, а упомянутый опять же вами токен csrf может испортиться и через несколько секунд. Приводить весь этот огород к одному универсальному числу не имеет никакого смысла.

                                                                                                                  К тому же, в вечных сессиях очень прикольно хранить такие штуки, как все ай пи адреса, с которых заходил пользователь, или еще какие-то данные, которые должны быть спрятаны от всех, включая разработчиков, и доступны только для какого-либо анализа.
                                                                                                                    0
                                                                                                                    >> К тому же, в вечных сессиях очень прикольно хранить такие штуки, как все ай пи адреса, с которых заходил пользователь
                                                                                                                    Создайте «специализированное хранилище» и храните это там. Какой смысл хранить данные в месте, где их аналитика затруднена?

                                                                                                                    user_id | ip | date — вот вам таблица, кладите туда и будет вам счастье. И будет вам вся мощь sql доступна, безо всяких трюков.

                                                                                                                    Т.е. вы так и не привели доводов «за» долгую сессию :-)
                                                                                                                      0
                                                                                                                      >> которые должны быть спрятаны от всех, включая разработчиков
                                                                                                                      Вопросы безопасности и доступа вообще сессиями никак не решаются. Если разработчик имеет доступ к базе, то и к сессиям он получить доступ сможет.

                                                                                                                      Более того, если сессии у вас хранятся в чём-то экзотическом — то забудьте о всяких прикольных штуках и анализе.
                                                                                                                      0
                                                                                                                      Бывают такие куки, которые сложно потерять. Да и синхронизация не такая большая проблема в вероятном будущем. Касаемо ресурсов, то это проблему можно решить отдельным камнем на ssd-диске, которые будет заниматься только инвалидацией. Ну, знаете там, хранить карту, следить за atime и size, вот это все.
                                                                                                                        0
                                                                                                                        >> которые будет заниматься только инвалидацией.
                                                                                                                        Инвалидация это ещё и логика, хранение дерева зависимостей и прочее. Зачем — если вариант с ttl 15 минут решает проблему?

                                                                                                                        Куки по определению потереть легко, любые.

                                                                                                                        >> Ну, знаете там, хранить карту, следить за atime и size, вот это все.
                                                                                                                        зачем писать отдельную логику, если всё уже придумано и реализовано?
                                                                                                                        0
                                                                                                                        Пока отдельного камня нет, я за кэш прямо сейчас скажу вот что: если его просто дропать в нужные моменты, и хранить с ассоциативным графом при этом, и не хранить в кэше вечно то, что может засорить в будущем диск — с современными объемами хардов проблема не такая уж и большая. Я, во всяком случае, пока отлично обхожусь без инвалидации.
                                                                                                                          0
                                                                                                                          >> если его просто дропать в нужные моменты
                                                                                                                          Этот процесс и называется «инвалидация». Просто вы, судя по всему, инвалидируете весь кэш (o_O), а не конкретные элементы.

                                                                                                                          Да и кэш на харде, медленном ресурсе… :-S
                                                                                                                            0
                                                                                                                            Насколько медленном? У вас скорость интернета внезапно превысила 6 гигабит/сек?
                                                                                                                              0
                                                                                                                              Вы издеваетесь? Время случайного доступа у памяти и HDD сравните, угу?
                                                                                                                                0
                                                                                                                                Э. Вообще-то у SSD дисков (во всяком случае, мне такой экземпляр наверное попался) время случайного и последовательного доступа никак друг от друга не отличаются. RAID контролеры тоже частично снимают эту проблему. Допускаю, что в целом время доступа к памяти и к контролеру SATA могут отличаться в пользу памяти, но не думаю, что разница настолько огромная, чтобы на нее так дрочить. Ну и эцсамое, жрите поменьше, кэш магазина на 1000 товаров занимает… ну, гигабайта два наверное.

                                                                                                                                Кстати, такая инвалидация происходит ведь при изменении данных, это случается в десятки раз реже, чем просмотр. Что касается о_О, то вы пропустили мой пассаж про ассоциативное дерево, а теперь чему-то удивляетесь.
                                                                                                                                  0
                                                                                                                                  Да, я удивляюсь, что вместо автоматической инвалидации по TTL вы поддерживаете деревья связей и реализуете это вручную.

                                                                                                                                  По-прежнему, это никак к вечно живущим сессиям не относится
                                                                                                                                0
                                                                                                                                Ну и заодно — модели HDD, которые умеют 6гбит
                                                                                                                              0
                                                                                                                              Смею также заметить, что вы до сих пор ни одного довода за бесконечные сессии не привели.
                                                                                                                                0
                                                                                                                                Да это потому что я комментировать только раз в пять минут умею.

                                                                                                                                Суть токова.

                                                                                                                                Чтобы закончить с инвалидацией — зря удивляетесь, потому что это не инвалидация на самом деле (как считаете вы) а именно дропание. Инвалидация, это когда на место дропнутого кэша генерируется новый, а на этот случай дерево блоков как раз и позволяет сэкономить ресурсы и не генерировать новые блоки того, что не изменилось. А вручную, это как-то так: cache::drop('catalog') или cache::drop_by_tag('product_1').

                                                                                                                                Насчет вечноживущих сессий я честно не знаю, чего вы добиваетесь, ведь я же уже несколько раз сказал: данные, которые нельзя светить в бд/где угодно, где их можно легко найти, но нужно хранить и использовать. Пример, кстати, вы привели сами в самом начале: идентификатор текущего пользователя. Аргумент: пользователь, кем бы он ни был, не должен знать своего идентификатора. Тем более иметь возможность подменить его в куке.
                                                                                                                                  0
                                                                                                                                  >> данные, которые нельзя светить в бд/где угодно, где их можно легко найти, но нужно хранить и использовать.
                                                                                                                                  Эм, сессии — не способ обеспечить безопасность и сохранность данных вашего приложения. «где угодно» — это хранилище для сессий.
                                                                                                                                  Мимо кассы.

                                                                                                                                  >> Аргумент: пользователь, кем бы он ни был, не должен знать своего идентификатора. Тем более иметь возможность подменить его в куке.
                                                                                                                                  Я и не говорил, что в куках будет id пользователя.
                                                                                                                                    0
                                                                                                                                    Как раз сессии идеальное место, если они хранятся внутри криптоконтейнера. Вечно.

                                                                                                                                    > Я и не говорил, что в куках будет id пользователя.
                                                                                                                                    Бритва?
                                                                                                                                      +1
                                                                                                                                      Если они хранятся в контейнере и их может расшифровать вебсервер — то их может прочитать любой, у кого есть доступ к вебсерверу. Равно как и из базы может прочитать тот, у кого ест ьдоступ к базе.

                                                                                                                                      Про бритву не понял

                                                                                                                                      habrahabr.ru/blogs/php/136800/#comment_4553759
                                                                                                                                        0
                                                                                                                                        Ну вы советуете завести под id пользователя видимо какое-то отдельное хранилище. Я говорю, что это Бритва Оккама, и давайте же в это хранилище и остальные данные пихать, и назовем его сессия, и не будем его экспайрить.
                                                                                                                                          0
                                                                                                                                          Мне из этого отдельного хранилища нужно только одно значение, user_id

                                                                                                                                          Ради одного значения менять хранилище — смысл?
                                                                                                                                            0
                                                                                                                                            Не, не так, это вам нужно хранилище только для одного значения. Вот я и спрашиваю, какой смысл создавать такое хранилище?
                                                                                                                                              0
                                                                                                                                              Погодите — это же ваша мысль, что нужно каждую задачу решать конкретным хранилищем. Например — это вы предложили принципиально кэш всегда храниться в кэше, просто потому что он кэш.
                                                                                                                                              Вот и здесь та же петрушка — конкретная задача, конкретное решение.

                                                                                                                                              Или вы посередине дискуссии меняете свою позицию?

                                                                                                                                              Если будете продолжать настаивать на «всё в кучу» — тогда я предлагаю довести до крайности и в принципе создать в базе одну таблицу и хранить в ней всё, денормализованно.
                                                                                                                                                +1
                                                                                                                                                Не каждую, не думайте за меня плиз. Кроме того, я считаю, что сессия и есть идеальное хранилище для идентификатора пользователя.

                                                                                                                                                2VolCh: Пользователь не должен знать ничего о том, как он представлен внутри системы управления сайтом, в том числе не должен знать свой айди. Для меня это настолько очевидно, что я даже не знаю, как это понятно аргументировать. Ну, например, это уже осложняет некоторые SQL-инъекции как минимум.
                                                                                                                                                  0
                                                                                                                                                  Сдаюсь :-)
                                                                                                                                                    0
                                                                                                                                                    Ну вот я знаю свой id на хабре (не суррогатный в виде PK в БД, а настоящий идентификатор). И вы знаете. Чем это плохо? Для меня совсем не очевидно.

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

                                                                                                                                                    А SQL инъекции я стараюсь полностью исключить, а не осложнять их — если злоумышленник смог выполнить выборку из БД, то знание моего настоящего id или суррогатного ему мало жизнь осложнит. Или вы рекомендуете, например, таблицу users называть afdsfhkuitdafvnltjhgiltuj (про возможность получить схему данных вообще молчу)?
                                                                                                                                                      0
                                                                                                                                                      >А SQL инъекции я стараюсь полностью исключить
                                                                                                                                                      Ну-ну. Читали Мюнхгаузена? «Броня, которую не может пробить ни один снаряд. Снаряд, который может пробить любую броню.» Так и живем.
                                                                                                                                                      0
                                                                                                                                                      >сессия и есть идеальное хранилище для идентификатора пользователя.

                                                                                                                                                      OMG. Я зайду с другого компа/оси/учётки/браузера или даже с той же их комбинации, но место для кук закончится (не проверял в современных браузерах, но для 3-го фокса, например, их общее количество ограничено несколькими тысячами) или случайно сотру куки и не смогу воспользоваться своим ид, зарегистрированным в другой «вечной» сессии? Может, всё-таки, вы храните ид пользователя в более надежном хранилище, а в сессии лишь кэшируете результат аутентификации? Иначе надеюсь, что вашими сайтами мне пользоваться не придётся.
                                                                                                                                        0
                                                                                                                                        >Аргумент: пользователь, кем бы он ни был, не должен знать своего идентификатора. Тем более иметь возможность подменить его в куке.

                                                                                                                                        Почему не должен? Он не должен иметь возможности представиться другим, а знать свой. Да даже если его другие знают… Чем это плохо?

                                                                                                                                        А по сути механизм сессий в PHP вовсе не предназначен для хранения секретных данных. Он предназначен для передачи данных между двумя запросами, чтобы не передавать их постоянно от сервера к клиенту и обратно в урле, полях форм или куках, а передавать лишь ключ в каком-то key-values хранилище. Более того в описании механизма сессий явно указывается, что он не предполагает и не гарантирует, что информация доступна только пользователю-владельцу сессии.
                                                                                                                                          0
                                                                                                                                          Смотрю, к разговору совсем наркоманы подключаются. Результат аутентификации и есть идентификатор пользователя, а вы занимаете совершенно бессмысленными с точки зрения информационной безопасности экстраполяциями.
                                                                                                                                            0
                                                                                                                                            Результатом аутентификации является булево значение, что предъявленный идентификатор (логин) и его характеристика (пароль) соответствует друг другу. Всё. Какие-то дальнейшие действия типа получения из БД и сохранения в сессии суррогатного ключа пользователя — это уже действия с аутентифицированным пользователем, после того как получен положительный результат аутентификации.

                                                                                                                                            Насчёт наркомана слова над не возьмёте?
                                                                                                                                              0
                                                                                                                                              Стало быть, в сессии все-таки?

                                                                                                                                              Что-что мне со словами сделать?;)
                                                                                                                                                0
                                                                                                                                                В сессии, может быть, хранится кэш запросов из БД — это оптимизация, не более. К безопасности никакого отношения это не имеет, если её не ослабляет вообще (за счёт лишнего звена). А сами идентификаторы пользователей хранятся в БД (или каком другом хранилище).

                                                                                                                                                *назад
                                                                                                                                                  0
                                                                                                                                                  Еще один. Дайте угадаю: у вас кэш хранится в сессии, а сессия хранится в кэше (например, в мемкэше)? Такое яйцо горыныча прямо.
                                                                                                                                                    0
                                                                                                                                                    Только не Горыныча, а Кащея.

                                                                                                                                                    А вы таким подходом не пользуетесь? Не храните одни и те же данные в кэшах L1/L2/L3 процессора, внутреннем кэше диска, в дисковом кэше ОС, кэше СУБД и кэше приложения? Насильно отключаете все кроме одного? Какого и как, не поделитесь? На уровне PHP конечно, а не ассемблера, прошивок и патчей ядра.

                                                                                                                                                    Это не говоря о том, что memcache называть кэшем несколько некорректно. Это инструмент для организации высокоуровневых разделяемых кэшей и, да, иногда я храню данные сессий в нём.

                                                                                                                                                    В общем сложилось впечатление, что вы используете best praсtices без понимания что именно вы делаете. Может нашли их в интернетах, может дошли методом проб и ошибок, выявив узкие места профайлингом или ещё чем, может интуиция или анализ задачи в целом подсказали, но понимания этапов решения задачи типа «пользователь не должен на каждой странице вводить логин и пароль, а приложение должно иметь возможность быстро получить связанные с ним данные» не видно.

                                                                                                                                                    Хотя, может, это я тупой и не могу представить себе задач для которых не нужно хранить идентификаторы пользователей в СУБД, файлах или ещё каком постоянном хранилище, чтобы пользователей мог получить к ним доступ с любого компа/ос/браузера/учётки, а достаточно только сессий. Или даже не достаточно, а необходимо, чтобы пользователь после переустановки ОС или очистки кук не мог получить доступа к своим данным. В таком случае не расширите ли мой кругозор, не подскажете пример такой задачи?
                                                                                                                                                      0
                                                                                                                                                      > Хотя, может, это я тупой и не могу представить себе задач для которых не нужно хранить идентификаторы пользователей в СУБД, файлах или ещё каком постоянном хранилище, чтобы пользователей мог получить к ним доступ с любого компа/ос/браузера/учётки, а достаточно только сессий.
                                                                                                                                                      Чувак, я ничего не понял, но ты достучался до моего похуй.

                                                                                                                                                      > В общем сложилось впечатление, что вы используете best praсtices без понимания что именно вы делаете.
                                                                                                                                                      Замечательно. У меня от вас именно такое же впечатление осталось, причем с самого начала разговора. По крайней мере вы свой вывод сделали только на основании того, что я, по вашему, слушком плохо веду демагогию, в отличие от.
                                                                                                                                                        0
                                                                                                                                                        >Чувак, я ничего не понял,

                                                                                                                                                        На пальцах — идентификаторы пользователей должны храниться в базе, хотя бы для того, чтобы пользователь мог залогиниться с любого компа и его суррогатный идентификатор мог быть скопирован из базы в новую сессию. Хранить идентификаторы в сессии, то есть заставлять пользователя регистрироваться заново при смене окружения и/или потери «вечной» сессионной куки — жестоко.

                                                                                                                                                        >По крайней мере вы свой вывод сделали только на основании того, что я, по вашему, слушком плохо веду демагогию

                                                                                                                                                        Нет, на основании фраз типа «Результат аутентификации и есть идентификатор пользователя», ведь идентификатор (логин) предъявляется пользователем вместе с другой характеристикой (паролем), результат проверки соответствия которых и будет результатом аутентификация. Соответствует пароль логину или нет, третьего не дано (если не считать ошибок выполнения) — результат булев — да, соответствует, или нет, не соответствует, пользователь тот, за кого пытается себя выдать или нет, true или false. Всё остальное (типа вытаскивания числового id из таблицы users по текстовым логину и паролю и сохранения его в сессии) — это оптимизации как UI (чтобы не заставлять пользователя при каждом запросе вводить логин и пароль), так и ресурсов (чтобы не дергать при каждом запросе базу, проверяя логин и пароль, и не связывать таблицу users с другими по текстовому логину) с безопасностью (чтоб не хранить пароль, пускай и хэшированный с солью, в куках или той же сессии). Вы же называете это всё одним процессом — аутентифкацией, хотя тут заключено ещё минимум 3 процесса оптимизации: UI и безопасности — пользователь передаёт логин и пароль только один раз, а дальше только идентификатор сессии посылает, ресурсов и безопасности — кэширование результатов запроса на соответствие логина и пароля (htcehcs), и, как следствие, ненужность хранения пароля в сессии (безопасность), и ещё раз ресурсов и безопасности — связь таблицы users осуществляется с другими по суррогатному числовому идентификатору, а не по натуральному текстовому (логину), связь по такому id быстрее (ресурсы) и отсутсвие необходимости хранить натуральный текстовый в сессии безопаснее немного. Плюс микрооптимизация в виде проверки результата аутентификации через isset($_SESSION['user_id']), а не $_SESSION['user_is_authenticated'].

                                                                                                                                                        Если и такое объяснение непонятно, то я умываю руки.
                                                                                                                                                          0
                                                                                                                                                          Дружище, у меня поле в таблице называется user_id, а не user_surrogate_id, думаю, у тебя так же, так о чем ты пытаешься спорить? Я обожаю эту тенденцию на хабре, додумать за меня то, что я не говорил, причем додумать каким-то идиотским образом, потом на основании додуманного назвать меня идиотом и на сотню-другую комментов доказывать мне это. God Bless America!
                                                                                                                                                            0
                                                                                                                                                            Результат аутентификации и есть идентификатор пользователя — разве я это сказал? Или это я додумал?

                                                                                                                                                            Я не спорю, а пытаюсь развеять заблуждение :)

                                                                                                                                                            Естественный кандидат на роль primary key в таблице пользователей — это уникальный идентификатор пользователя в системе (логин, мыло, ФИО, табельный номер, ИНН и т. п.), чаще всего текстовый, но с текстовым идентификатором работать неудобно и дорого (прежде всего в СУБД) и вводят суррогатный числовой в виде какого-нибудь id INTEGER AUTO_INCREMENT, который хоть и избыточен для бизнес-целей системы (то есть в бизнес-правилах он вообще не упоминается), но обеспечивает большее удобство и эффективность. Но он не является идентификатором пользователя в системе и, тем более, нельзя называть его получение результатом аутентификации. То, что его удалось получить максимум может служить признаком успешной аутентификации, т. к. он может быть получен только в результате успешной аутентификации. Она может быть не выделена явно в приложении, как, например при выполнении запроса SELECT id FROM users WHERE login='$login' AND password='$password', но её результатом является не id, а то что вообще нашлась запись где login='$login' AND password='$password'.
                                                                                                                                                              0
                                                                                                                                                              Пытаетесь развеять? А не много ли вы на себя берете, возможно, это вы заблуждаетесь?

                                                                                                                                                              Такое чувство, что вы прочитали пару лет назад статью про излишество автоинкрементных полей везде, где нужно, и где нельзя, и теперь применяете противоположный подход — избавляетесь от них и там, где они нужны, и там, где они не нужны.

                                                                                                                                                              Кстати, манера расстановки болдов еще раз подтверждает мое подозрение насчет наркомании.
                                                                                                                                                                0
                                                                                                                                                                Возможно и заблуждаюсь, но на ошибки вы мне не указываете.

                                                                                                                                                                Я от них отнюдь не избавляюсь (почти, только там где действительно не нужны, например в таблицах связи many-many), я просто сознаю для чего я их ввожу. И просто различаю понятия ключ (суррогатный) в БД и идентификатор пользователя в системе. И процессы аутентификации и получения этого ключа.

                                                                                                                                                                Что, болды это новый способ диагностики наркоманов? :)
                                                                                                                                                                0
                                                                                                                                                                А вот эти две фразы, отстоящие друг от друга всего на несколько слов, просто восхищают:
                                                                                                                                                                «нельзя называть его получение результатом аутентификации»
                                                                                                                                                                «он может быть получен только в результате успешной аутентификации»

                                                                                                                                                                Как люди, у которых ТАКИЕ пробелы в логике, могут быть программистами, я не понимаю. Впрочем, такие обычно становятся PM'ами, томно уверяя всех, что программировать им «надоело уже».
                                                                                                                                                                  0
                                                                                                                                                                  С логикой как раз всё нормально, сначала аутентифицируемся, а потом, если результат положительный (успешный), то получаем значение ключа для уже аутентифицированного пользователя.
                                                                                                                                                                    0
                                                                                                                                                                    Расскажите, пожалуйста, максимально подробно, как вы аутентифицируетесь, а как получаете значение ключа, а то у меня тут подозрения, что два этих процесса похожи как две капли воды, за исключением упоминания колонки user_id в списке колонок SELECT'a.
                                                                                            0
                                                                                            Не очень понял, как это связано с местом хранения сессии. Речь о производительности?

                                                                                            Может новое значение будет вписываться в момент обращения к записи.
                                                                                              0
                                                                                              homm спросил о том, как ему указать php, где лежит сессия, чтобы он в эту сессию смог положить текущий прогресс загрузки
                                                                                                0
                                                                                                В таком случае, я думаю, что это происходит автоматически. Было бы странно, если бы для этого пришло писать отдельные инструкции. Теряется весь смысл.
                                                                                                  +4
                                                                                                  Круто. А в следующей версии языка разработчики сделают, чтобы приложение создавалось автоматически, а то я заколебался уже писать :)
                                                                                                    +4
                                                                                                    Данная возможность уже запатентована компаний Adobe для Photoshop. Называется «Сделать п*****о»
                                                                                                    +2
                                                                                                    Эм, в каком смысле «автоматически»? Откуда пхп узнает о том, куда подключаться и с какими логином-паролем?

                                                                                                    Я всё таки подозреваю, что предполагается, что работать оно будет только с дефолтным хандлером
                                                                                                      0
                                                                                                      Мы говорим об автоматической записи размера залитой части файла после его отправки на сервер в сессию с определенным именем для данного файла? Если да, то запись будет происходит автоматически, если указана соответствующая настройка в php.ini или еще где.
                                                                                                        0
                                                                                                        Да, и она автоматически будет писаться в дефолтный хандлер, суть в файлы. А у человека — база, и он хотел бы писать туда (как и всё остальное у него) :-)
                                                                                                          +1
                                                                                                          Добавляй «например», а то josser счас опять докопается :)
                                                                                                            +1
                                                                                                            Чо сразу «докопается»?
                                                                                                            Вы что не верите, что я действительно хотел знать для чего может захотеться хранить сессии в базе?
                                                                                                            0
                                                                                                            Если мы прикручивали базу данных для сессии через session_set_save_handler, то интерфейс доступа к сессиям не изменится. Так что PHP будет писать в базу, потому что PHP на том уровне не положено знать, где лежат сессии физически.

                                                                                                            Если вы реализовали Свои Собственные Сессии, то PHP будет писать в файлы.
                                                                                                              0
                                                                                                              >> Если мы прикручивали базу данных для сессии через session_set_save_handler, то интерфейс доступа к сессиям не изменится
                                                                                                              Кто и в какой момент будет запускать session_set_save_handler(), для инициализации калбэков?
                                                                                                                –1
                                                                                                                html:


                                                                                                                somescript.php:
                                                                                                                session_set_save_handler();

                                                                                                                if (is_uploaded_file… ()) // собсно сам аплоад.
                                                                                                                  0
                                                                                                                  Ох, фейл:

                                                                                                                  html:
                                                                                                                    0
                                                                                                                    Вот жеж,
                                                                                                                    вопщем там код формы с action=«somescript.php»
                                                                                                                    +3
                                                                                                                    ПХП обрабатывает загрузку файла ПЕРЕД передачей управления в ваш код
                                                                                                                      –2
                                                                                                                      Тогда я допускаю что это поведение было изменено в 5.4
                                                                                                                        +2
                                                                                                                        А я не допускаю, потому что не было :-)
                                                                                                                          0
                                                                                                                          Т.е. нужно будет переписывать кучу кода, который не расчитан на то, что во время исполнения файлы еще не докачаны.
                                                                                                                            –2
                                                                                                                            Не понял, покажите пример когда в коде уже известно о том что файл загружен но сам файл еще загружается.
                                                                                                                              +1
                                                                                                                              В том то и дело, что такого не бывает, это вы придумали в своём коде
                                                                                                                                –1
                                                                                                                                Я ничо не придумывал, это homm говорит что этот код надо переписывать.
                                                                                                                                  +1
                                                                                                                                  Придумывали

                                                                                                                                  >> Тогда я допускаю что это поведение было изменено в 5.4

                                                                                                                                  Если это поведение было изменено, тогда весь код придётся переписать
                                                                                                                                0
                                                                                                                                Твое предположение было опровергнуто в моем самом первом комментарии:
                                                                                                                                > Upload делается перед запуском скрипта,
                                                                                                                                > поэтому поставить свои обработчики сессии
                                                                                                                                > в скрипте, который принимает закачку, нельзя.
                                                                                                                                Но кто же будет читать.

                                                                                                                                Твой наезд про гранение сессии в базе вообще не по адресу.

                                                                                                                                Теперь ты просишь привести пример кода, который был бы, если бы твое предположение о изменении поведения php было верным. Я вообще-то сказал что оно неверное, какой код я могу привести?

                                                                                                                                В общем что не комментарий, то бред какой-то. Завязывайте.
                                                                                                                                  –1
                                                                                                                                  Я прошу привести пример кода который станет некорректно работать в случае если мое предположение верно.
                                                                                                                                    0
                                                                                                                                    <?php

                                                                                                                                    copy($_FILES['file']['tmp_name'], '/path/to/file');


                                                                                                                                    Вот конкретно этот код будет работать неправильно
                                                                                                                                      0
                                                                                                                                      $img = imagecreatefrompng($_FILES['image']['tmp_name']);
                                                                                                                                      0
                                                                                                                                      Про хранение сессий в базе, я второй раз напишу, никакой это не наезд. Где вы там увидели наезд?
                                                                                                                                      Я ПРОСТО спросил. Мне очень интересен юс-кейс.
                                                                                                                                        0
                                                                                                                                        Пофилософствую на эту тему.
                                                                                                                                        В самом первом вашем камменте речь шла о memcached. Что такое memcached? Система кэширования данных. Для чего служит кэш? Для ускорения доступа к используемым данным.

                                                                                                                                        Какая есть брешь? Кэш не гарантирует сохранности данных, т.е. в любой момент при падении сервера или memcached'а все данные теряются.

                                                                                                                                        С БД этого не произойдет, конечно, если тип таблицы не memory.

                                                                                                                                        Такой ответ сойдет?
                                                                                                                                –1
                                                                                                                                Клиент начинает загрузку файла во фрейм. Загрузка файла идет некоторое время. Мы хотим отрисовать прогресс-бар. Дергаем другой процесс PHP (но с теми же cookies) — получаем объем загруженной части файла.

                                                                                                                                То, что PHP не отдает нам массив $_FILES, ничего не меняет, потому что все, что нам нужно — узнавать раз в секунду загруженную часть.
                                                                                                                                  +1
                                                                                                                                  И это никак не отвечает на вопрос о том, как пхп узнает данные о не-дефолтном хандлере для сессий

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

                                                                                                                                      Но проще всего проверить, PHP 5.4 уже в достаточно стабильной стадии RC5.
                                                                                                                                        0
                                                                                                                                        Очевидно, что никак :-)

                                                                                                                                        Так что те, кто хранят сессии во всяких редисах теперь будут озабочены ещё и проблемой очистки старых сессий (совершенно верно, на продакшне никто не пользуется стандартным GC ведь)
                                                                                                                                          0
                                                                                                                                          Не понятно почему не пользуются.
                                                                                                                                          Я вижу что в случае переопределения хендлера я также должен написать функцию delete для сессии.
                                                                                                                                          Я подозреваю что GC использует ее для удаления сессий, не?
                                                                                                                                            0
                                                                                                                                            Эх…

                                                                                                                                            Не пользуются потому, что GC непрогнозируемо замедляет выполнение скрипта. Потому и создаются задачи в кроне, которые подчищают старые файлы в директории
                                                                                                                                        0
                                                                                                                                        Я вас наконец понял, о чем вы.

                                                                                                                                        Возможно, вам поможет эта ссылка.
                                                                                                                                          +1
                                                                                                                                          Мне-то она чем поможет? Я знаю об этой директиве.

                                                                                                                                          И продолжаю утверждать, что в базе вы сессию хранить не сможете. На эту тему вы что-то добавите?
                                                                                                                                            0
                                                                                                                                            Нет, добавить нечего. Разве что соглашусь с утверждениями выше о том, что хранить сессии в базе — странно.
                                                                                                                  0
                                                                                                                  Данная информация не особенно полезна для запроса, непосредственно закачивающего файл, однако, в течение данной загрузки приложение может посылать POST-запросы на отдельную страницу (например, с помощью XHR) для проверки статуса.

                                                                                                                  Опции session.upload_progress.freq и session.upload_progress.min_freq контролируют частоту обновления информации о прогрессе загрузки. При разумных значениях этих двух настроек, накладные расходы данной функции практически неощутимы.
                                                                                                                    0
                                                                                                                    > в течение данной загрузки приложение может посылать POST-запросы
                                                                                                                    > на отдельную страницу (например, с помощью XHR) для проверки статуса.
                                                                                                                    Ну вот эта отдельная страница откуда-то берет информацию о процессе загрузки. Берет она её из сессии. В сессии эта информация как-то оказывается. Вопрос: как?
                                                                                                                      0
                                                                                                                      Для memcache так:
                                                                                                                      session.save_handler = memcache
                                                                                                                      session.save_path = "tcp://127.0.0.1:11211"

                                                                                                                      Для мускула не нашёл…