Проверьте, началась ли сессия PHP


461

У меня есть файл PHP, который иногда вызывается со страницы, с которой начался сеанс, а иногда со страницы, с которой не начался сеанс. Поэтому, когда у меня есть session_start()этот скрипт, я иногда получаю сообщение об ошибке «сессия уже началась». Для этого я поставил эти строки:

if(!isset($_COOKIE["PHPSESSID"]))
{
  session_start();
}

но на этот раз я получил это предупреждение:

Примечание: неопределенная переменная: _SESSION

Есть ли лучший способ проверить, началась ли сессия уже?

Если я использую @session_start, это заставит вещи работать должным образом и просто закроет предупреждения?



См. Также ответы Stackoverflow: stackoverflow.com/questions/1545357/…
contact-form.co_you_go

Ответы:


761

Рекомендуемый способ для версий PHP> = 5.4.0, PHP 7

if (session_status() == PHP_SESSION_NONE) {
    session_start();
}

Ссылка: http://www.php.net/manual/en/function.session-status.php

Для версий PHP <5.4.0

if(session_id() == '') {
    session_start();
}

1
Я думаю, что есть проблема с решением для PHP <5.4. Параметр session_id устанавливается при первом запуске сеанса, но не удаляется при закрытии сеанса. Так, например, если перед вашим фрагментом есть код вроде session_start();session_write_close();: тогда условие if не выполняется, но у нас нет открытого сеанса ...
Nicolò Martini

@Nicolo Martini Насколько я понимаю: сессия, начинающаяся session_start()в верхней части скрипта, ЗАКРЫВАЕТСЯ при выходе из скрипта, ИЛИ когда session_write_closed()вызывается до его завершения. Т.е. сеанс ЗАКРЫВАЕТСЯ, когда его данные записываются в файл cookie сеанса, и сеанс разблокируется для доступа другим скриптом, который также вызывает 'session_start'. ЗАКРЫТИЕ НЕ означает, что сеанс УНИЧТОЖЕН, поэтому. Вы можете закрыть сеанс, выйдя из текущего скрипта или вызова session_write_close(), и вы можете открыть его снова, вызвав session_start(). Мое понимание, по крайней мере.
Стефан

1
Это все еще хороший способ начать сеанс? Потому что в ссылке нет ничего связанного с этим ответом
csandreas1

@ csandreas1 вы увидите по ссылке описание session_status и его ожидаемые возвращаемые значения. Ответ на ваш вопрос - да!
lovelyramos

У меня был этот сбой в некоторых обстоятельствах - я использовал if (! Isset ($ _ SESSION)) с успехом
Скотт

161

Для версий PHP до PHP 5.4.0:

if(session_id() == '') {
    // session isn't started
}

Хотя, IMHO, вам стоит подумать о рефакторинге кода управления сеансом, если вы не знаете, запущен сеанс или нет ...

Тем не менее, мое мнение субъективно, и есть ситуации (примеры которых описаны в комментариях ниже), где может быть невозможно узнать, начался ли сеанс.


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

1
Также в некоторых средах apache настроил автозапуск сеанса
LeonardChallis

Пример для тестирования, если session_id () возвращает пустую строку во включаемом файле:
tgoneil

3
Комментарий о рефакторинге управления сеансом, если вы не знаете, был ли он отфильтрован или нет, не очень актуален. Например, если кодировать расширенные функции в тему WordPress, вы никогда не узнаете, начал ли плагин использовать сеансы без проверки. Мир кодирования не всегда такой черно-белый: P
Джимбо Джонни

Ммм, хорошие моменты действительно. Я признаю, что мои комментарии очень субъективны - я исправлю свой ответ, чтобы отразить это.
Алекс

71

В PHP 5.4 введен метод session_status () , который более надежен, чем полагается session_id().

Рассмотрим следующий фрагмент:

session_id('test');
var_export(session_id() != ''); // true, but session is still not started!
var_export(session_status() == PHP_SESSION_ACTIVE); // false

Итак, чтобы проверить, запущен ли сеанс, рекомендуемый путь в PHP 5.4:

session_status() == PHP_SESSION_ACTIVE

3
Фрагмент кода, который использует session_status, когда он доступен, и более старые методы, когда он не кажется идеальным, кстати, подсказка :)
Джимбо Джонни

1
Спасибо за обновление, Бенджамин. Хорошо знать, что с PHP 5.4 можно использовать новый метод.
Логан

1
Это гораздо лучший способ проверить это, вы не всегда знаете, если у вас начался сеанс, особенно когда пользователь очищает куки, когда он находится в середине просмотра сайта ... Я всегда пишу код для двухлетнего, вы никогда не знаю, что собираются делать пользователи ;-) Что касается меня, у меня есть небольшой файл Config.php, который вызывается во всех моих сценариях для настройки переменных и другой информации, поэтому простое добавление этого в этот файл всегда гарантирует, что сеанс запускается, если это необходимо
Энди Брахам

35

Вы можете сделать это, и это действительно легко.

if (!isset($_SESSION)) session_start();

Надеюсь, поможет :)


6
@zloctb: я не могу придумать ни одной ситуации, в которой бы я поступил $_SESSION=array();, поэтому этот ответ кажется нормальным.
Оффер

5
@halfer Смотрите ответ Райана. Если session_destroy()был вызван, то $_SESSIONвсе еще может быть установлен. Кроме того, в модульных тестах вы можете установить $_SESSIONнапрямую. Но я высказался против этого, так как для большинства практических ситуаций этот ответ должен быть достаточно хорошим (до тех пор, пока PHP 5.3 больше никогда не увидится ...)
Даррен Кук

22
if (version_compare(phpversion(), '5.4.0', '<')) {
     if(session_id() == '') {
        session_start();
     }
 }
 else
 {
    if (session_status() == PHP_SESSION_NONE) {
        session_start();
    }
 }

21

До PHP 5.4 не было надежного способа узнать, кроме установки глобального флага.

Рассматривать:

var_dump($_SESSION); // null
session_start();
var_dump($_SESSION); // array
session_destroy();
var_dump($_SESSION); // array, but session isn't active.

Или:

session_id(); // returns empty string
session_start();
session_id(); // returns session hash
session_destroy();
session_id(); // returns empty string, ok, but then
session_id('foo'); // tell php the session id to use
session_id(); // returns 'foo', but no session is active.

Итак, до PHP 5.4 вы должны установить глобальное логическое значение.


12

Для всех версий PHP

if ((function_exists('session_status') 
  && session_status() !== PHP_SESSION_ACTIVE) || !session_id()) {
  session_start();
}

1
Точно так же можно было бы сделатьif ((defined('PHP_SESSION_ACTIVE') && session_status() !== PHP_SESSION_ACTIVE) || !session_id())
Энтони Хатзопулос

9

Проверь это :

<?php
/**
* @return bool
*/
function is_session_started()
{
    if ( php_sapi_name() !== 'cli' ) {
        if ( version_compare(phpversion(), '5.4.0', '>=') ) {
            return session_status() === PHP_SESSION_ACTIVE ? TRUE : FALSE;
        } else {
            return session_id() === '' ? FALSE : TRUE;
        }
    }
    return FALSE;
}

// Example
if ( is_session_started() === FALSE ) session_start();
?>

Источник http://php.net




5

Это должно работать для всех версий PHP. Он определяет версию PHP, а затем проверяет, запущен ли сеанс на основе версии PHP. Затем, если сеанс не запущен, он начинает его.

function start_session() {
  if(version_compare(phpversion(), "5.4.0") != -1){
    if (session_status() == PHP_SESSION_NONE) {
      session_start();
    }
  } else {
    if(session_id() == '') {
      session_start();
    }
  }
}

4

Единственное, что вам нужно сделать, это:

<?php
if(!isset($_SESSION))
{
session_start();
}
?>

Это тот, который я использовал на протяжении многих лет. Кто-нибудь советует не использовать этот? Конечно, хорошо использовать проверку, если сеанс иногда запускается - в некоторых средах apache имеет настройку автозапуска сеанса, ленивую загрузку (только начало сеанса, когда это необходимо) или просто что иногда нужно просто сделать быстрый взлом
K Килиан Линдберг

ТО ЖЕ ОТВЕТ ВЫШЕ (@miyuru)

2

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

   /**
    * Start session
    * Fall back to ukrainian language
    */
   function valid_session() {
    if(session_id()=='') {
        session_start();
        $_SESSION['lang']='uk';
        $_SESSION['lang_id']=3;
    }
    return true;
  }

2

@ перед вызовом функции подавляет любые ошибки, о которых можно сообщить во время вызова функции.

Добавление @before session_startзаставляет PHP избегать вывода сообщений об ошибках.

Например:

Использование session_start()после того, как вы уже что-то напечатали в браузере, приводит к ошибке, поэтому PHP отобразит что-то вроде «заголовки не могут быть отправлены: началось с (строка 12)», @session_start()в этом случае все равно не будет работать, но сообщение об ошибке не будет напечатано экран.

Перед включением файлов или перенаправлением на новую страницу используйте exit()функцию, иначе она выдаст ошибку.

Этот код можно использовать во всех случаях:


    <?php 
        if (session_status() !== PHP_SESSION_ACTIVE || session_id() === ""){
            session_start(); 
        }
    ?>

1

На PHP 5.3 это работает для меня:

if(!strlen(session_id())){
    session_name('someSpecialName');
    session_start();
} 

тогда у вас есть. Если вы не поместите оператор not at if в начало, сеанс начнется любым способом, я не знаю почему.


1

Ответ на основе @Meliza Ramos Response (см. Первый ответ) и http://php.net/manual/en/function.phpversion.php ,

ДЕЙСТВИЯ:

  • определить PHP_VERSION_ID, если не существует
  • определить функцию для проверки версии на основе PHP_VERSION_ID
  • определить функцию для openSession () безопасный

использовать только openSession ()

    // PHP_VERSION_ID is available as of PHP 5.2.7, if our
    // version is lower than that, then emulate it
    if (!defined('PHP_VERSION_ID')) {
        $version = explode('.', PHP_VERSION);

        define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));


        // PHP_VERSION_ID is defined as a number, where the higher the number
        // is, the newer a PHP version is used. It's defined as used in the above
        // expression:
        //
        // $version_id = $major_version * 10000 + $minor_version * 100 + $release_version;
        //
        // Now with PHP_VERSION_ID we can check for features this PHP version
        // may have, this doesn't require to use version_compare() everytime
        // you check if the current PHP version may not support a feature.
        //
        // For example, we may here define the PHP_VERSION_* constants thats
        // not available in versions prior to 5.2.7

        if (PHP_VERSION_ID < 50207) {
            define('PHP_MAJOR_VERSION',   $version[0]);
            define('PHP_MINOR_VERSION',   $version[1]);
            define('PHP_RELEASE_VERSION', $version[2]);

            // and so on, ...
        }
    }

    function phpVersionAtLeast($strVersion = '0.0.0')
    {
        $version = explode('.', $strVersion);

        $questionVer = $version[0] * 10000 + $version[1] * 100 + $version[2];

        if(PHP_VERSION_ID >= $questionVer)
            return true;
        else
            return false;

    }

    function openSession()
    {
        if(phpVersionAtLeast('5.4.0'))
        {
            if(session_status()==PHP_SESSION_NONE)
                session_start();
        }
        else // under 5.4.0
        {
            if(session_id() == '')
                session_start();
        }
    }

1
if (version_compare(PHP_VERSION, "5.4.0") >= 0) {
    $sess = session_status();
    if ($sess == PHP_SESSION_NONE) {
        session_start();
    }
} else {
    if (!$_SESSION) {
        session_start();
    }
}

На самом деле, сейчас слишком поздно, чтобы объяснить это здесь, так как это было решено. Это был файл .inc одного из моих проектов, где вы настраивали меню для ресторана, выбирая блюдо и удаляя / добавляя или изменяя порядок. Сервер, на котором я работал, не имел реальной версии, поэтому я сделал его более гибким. Это зависит от авторов, которые хотят использовать и попробовать.


1

Этот фрагмент кода работает для вас?

if (!count($_SESSION)>0) {
    session_start();
}

0

Вы должны реорганизовать свой код так, чтобы вы вызывали его session_start()ровно один раз за исполнение страницы.


4
в некоторых ситуациях вызывать его ровно один раз за выполнение страницы может быть нежелательно.
Тимо Хуовинен

Если вы убиваете сеанс, чтобы воссоздать его, тогда, конечно, но это особый случай. В общем, приложение должно иметь код, который запускается в самом начале один раз, и именно туда идет session_start ().
SamT

1
например, приложение сохраняет сеансы в файле и должно загрузить 2 одновременных медленных запроса данных, ни один из этих запросов не требует сеансов, но один будет блокировать другой, потому что session_start блокирует файл сеанса.
Тимо Хуовинен

Точно. @YuriKolovsky прав. Вопрос Алекса уместен, потому что такие случаи могут случиться, и они не редкость.
Пауло Коги - Восстановить Монику

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


0

PHP_VERSION_ID доступен начиная с PHP 5.2.7, поэтому сначала проверьте это и, если необходимо, создайте его. session_statusдоступно с версии PHP 5.4, поэтому мы должны проверить это тоже:

if (!defined('PHP_VERSION_ID')) {
    $version = explode('.', PHP_VERSION);
    define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
}else{
    $version = PHP_VERSION_ID;
}
if($version < 50400){
    if(session_id() == '') {
        session_start();
    }
}else{
    if (session_status() !== PHP_SESSION_ACTIVE) {
        session_start();
    }
}

0

Исходя из моей практики, перед обращением к $_SESSION[]вам нужно session_startкаждый раз звонить, чтобы использовать скрипт. Смотрите ссылку ниже для руководства.

http://php.net/manual/en/function.session-start.php

Для меня, по крайней мере session_start, сбивает с толку, как имя. А session_loadможет быть более понятным.


0

я закончил с двойной проверкой статуса. PHP 5.4+

if(session_status() !== PHP_SESSION_ACTIVE){session_start();};
if(session_status() !== PHP_SESSION_ACTIVE){die('session start failed');};

0

Вы можете использовать следующее решение, чтобы проверить, начался ли уже сеанс PHP:

if(session_id()== '')
{
   echo"Session isn't Start";
}
else
{
    echo"Session Started";
}

Действительный ответ более подробно.
Клеман Прево

0

Это то, что я использую, чтобы определить, начался ли сеанс. Используя empty и isset следующим образом:

if (empty($_SESSION)  && !isset($_SESSION))  {
    session_start();
}

-3

Заменить session_start();на:

if (!isset($a)) {
    a = False;
    if ($a == TRUE) {
        session_start();
        $a = TRUE;
    }
}

он содержит ошибки кода и будет работать только в том случае, если один и тот же файл будет включен несколько раз, но не при закрытии.
BananaAcid
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.