Перевірте, чи вже почався сеанс PHP


461

У мене є файл PHP, який іноді викликається зі сторінки, яка розпочала сеанс, а іноді зі сторінки, на якій не було запущено сеанс. Тому, коли у мене є session_start()цей сценарій, я іноді отримую повідомлення про помилку "сеанс вже розпочався". Для цього я поставив наступні рядки:

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

але цього разу я отримав це попередження:

Примітка: Не визначена змінна: _SESSION

Чи є кращий спосіб перевірити, чи сеанс вже розпочався?

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



Дивіться також ці відповіді Stackoverflow: stackoverflow.com/questions/1545357 / ...
контактно-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

Я мав цю помилку за деяких обставин - я використовував, якщо (! Isset ($ _ SESSION)) з успіхом
Скотт

161

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

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

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

Зважаючи на це, моя думка є суб'єктивною, і є ситуації (приклади яких описані в коментарях нижче), де, можливо, неможливо дізнатися, чи розпочато сеанс.


37
Не обов’язково погано не знати, чи розпочато сеанс. Якщо ви ледаче завантажуєтесь (починаєте сеанс лише тоді, коли це вперше потрібно), то тест у вашій відповіді був би чудово.
Малюнок

1
Також у деяких середовищах у апачі встановлено автоматичне запуску сеансу
LeonardChallis,

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

3
Коментар щодо керування сеансом рефакторингу, якщо ви не знаєте, чи він відзначений, чи ні, не дуже важливий. Наприклад, якщо кодування розширених функцій у тему WordPress, ви ніколи не дізнаєтесь, чи плагін уже почав використовувати сеанси без перевірки. Світ кодування не завжди такий чорно-білий: P
Jimbo Jonny

Ммм, справді хороші бали. Я визнаю, що мої коментарі є дуже суб'єктивними - я зміню свою відповідь, щоб відобразити це.
Алекс

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 за наявності та старіші методи, коли тут не здасться ідеальним. До речі, підказка :)
Jimbo Jonny

1
Дякую за оновлення Бенджаміна. Добре знати, що за PHP 5.4 можна використовувати новий метод.
Логан

1
Це набагато кращий спосіб перевірити це, ви не завжди знаєте, чи розпочався сеанс, особливо коли користувач очищає файли cookie, коли він знаходиться посеред перегляду сайту ... Я завжди кодую 2-річного віку, ви ніколи не знаю, що збираються робити користувачі ;-) Що стосується самого себе, у мене є невеликий файл 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


6

Використовуйте session_id () , він повертає порожній рядок, якщо його не встановлено. Це надійніше, ніж перевірка $_COOKIE.

if (strlen(session_id()) < 1) {
    session_start();
}


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();
}
?>

Це той, який я використовував протягом багатьох років. Хто не радить не користуватися цим? Звичайно, добре використовувати перевірку, якщо сеанс запускається іноді - у деяких середовищах апач налаштовує автозапуск сеансу, ледачу завантаження (лише запуск сеансу, коли це потрібно спочатку) або просто те, що іноді потрібно просто зробити швидкий злом
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

@ перед тим, як виклик функції придушує будь-які помилки, про які можна повідомити під час виклику функції.

Додавання @до цього 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();
} 

то у вас є. Якщо ви не ставите не, якщо заява, що починає сеанс, розпочнеться будь-яким чином, я не знаю чому.


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 одного з моїх проектів, коли ви налаштовуєте меню ресторану, вибравши блюдо та видаливши / додавши або змінивши замовлення. Сервер, на якому я працював, не мав фактичної версії, тому я зробив його більш гнучким. Це автори хочуть використати та спробувати.



0

Ви повинні реорганізувати свій код, щоб ви зателефонували session_start()рівно один раз за виконання сторінки.


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

Якщо ви вбиваєте сеанс, щоб відтворити його, то впевнено, але це особливий випадок. Загалом, у програмі повинен бути код, який запускається на самому початку один раз, куди йде сесія_start ().
SamT

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

Саме так. @ЮріКоловський має рацію. Питання Алекса актуальне тому, що ці випадки можуть траплятися, і вони не є рідкістю.
Paulo Coghi - Відновіть Моніку

14
-1, Більшість веб-сайтів керовані CMS і містять такі речі, як теми та плагіни, які часто пишуться різними сторонами, ніколи не знаючи, розпочали коди один одного сесії чи ні. Мається на увазі, що це лише проблема організації коду - помилкова.
Jimbo Jonny


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";
}

Дійсна відповідь більш детальна.
Clément Prévost

0

Це я використовую, щоб визначити, чи почався сеанс. Використовуючи порожній і набір наступним чином:

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.