Session will be NULL at the second call

Hi guys,
In one method, I define session like this:

    $sessionPHP->open();
    $sessionPHP['searchModel'] = $searchModel;
    $sessionPHP['dataProvider'] = $dataProvider;
    $sessionPHP->close();

Using another method, which will be called like this:

    [
        'class' => 'yii\grid\ActionColumn',
        'template' => '{kunde} {map}<br>{update}',
        'buttons' => [
            'map' => function $id,$model) {
                return Html::a('<span class="glyphicon glyphicon-zoom-in"></span>', ['/termin/map', 'id' => $model->id], ['title' => 'Treffpunkt in Karte anzeigen', 'data' => ['pjax' => '0']]);
            },
        ],
    ],

will show an empty array for both sessions first at the second time I will push on glyphicon icon. Here is code of method, which will 'cause error:

public function actionMap($id) {
    $sessionPHP = Yii::$app->session;
    $sessionPHP->open();
    echo $this->RenderGoolge($id);
    if (empty($sessionPHP['dataProvider']) || empty($sessionPHP['searchModel'])) {
        var_dump($sessionPHP['dataProvider']);
        var_dump($sessionPHP['searchModel']);
        die();
    }
    return $this->render('index', [
                'dataProvider' => $sessionPHP['dataProvider'],
                'searchModel' => $sessionPHP['searchModel']
    ]);
}

.

You can’t store an object to a session. It must be a scalar value or an array.
A model may be converted into an array, but a data provider can not.

Consider storing the parameters that can be used to reconstruct the model and the data provider.

Are you sure @softark? We store objects in session in our project.

Oh, really? I didn’t know that we could store objects in session.

OK, I’m now reading this
stack overflow - PHP: Storing ‘objects’ inside the $_SESSION

Thanks @thefsb for correcting me. I was wrong. I’ve never thought that we could store objects in session.

BTW, what do you think is the cause of the error that @tklustig reported?

I wonder if the problem is related to autoloading. Iiuc, PHP needs the object’s class to be loaded or it cannot unserialize it. I suppose Yii unserializes session data early but isn’t it rather lazy about loading classes? If this is the problem then there should be a PHP error.

Btw, the application component Yii::$app->session should be active when actionMap() runs so invoking $sessionPHP->open() is unnecessary and a bit confusing.

Maybe @tklustig is destroying session data by himself somewhere else, because he was unnecessarily calling Session::destroy() in another context (Yii::$app->request->post() is always empty). But I really don’t know for sure.

BTW, I would still hesitate to store an ActiveDataProvider instance into session even if it would be possible. Simple objects including Model and ActiveRecord might be OK, but it looks dangerous to me to store/restore a complicated object into/from session.

I don’t destroy whole session any more, I am removing special session element instead. Nevertheless, second time, I will push on Css, respectively glyphicon icon, sessions will be empty, both, as already having shown up. So,

if (empty($sessionPHP['dataProvider']) || empty($sessionPHP['searchModel']))

will be true, even for &&

I see. But …

You mean that the session entries are empty when you call termin/map action from the map button?
I’d like to see the controller code where you show the gridview and set the variables to the session.

I already posted all code being invloved in at my first post. As well as setting variables to session, as also rendering Grid(index), using these sessions!

Yes, but you posted only the code snippet that will set the session variables. I’d like to see the whole code of actionIndex.

Here, it is:

public function actionIndex($id = NULL) {
    //keine Termine vorhanden?
    $countTermine = Besichtigungstermin::find()->count('id');
    if ($countTermine == 0) {
        $link = \Yii::$app->urlManagerBackend->baseUrl . '/home';
        $zusatz = '?message=Es+exisitieren+noch+keine+Besichtigungstermine++in+der+Datenbank.+Steigern+Sie+Ihre+Kundenaqkuise%21';
        return $this->redirect($link . $zusatz);
    }
    $searchModel = new TerminSearch();
    /*  sofern eine Maklerid übergeben wurde, zeige nur diejenigen Records an, deren PK als FK(besichtigungstermin_id) 
      in adminbesichtigungkunde vorhanden ist */
    $arrayOfFk = array();
    if ($id != null) {
        $modelAdminBesKu = Adminbesichtigungkunde::find()->all();
        foreach ($modelAdminBesKu as $item) {
            if ($item->admin_id == $id)
                array_push($arrayOfFk, $item->besichtigungstermin_id);
        }
        /*  sofern das Array nicht leer, lege eine Session an, da nur so der Wert an die Methode actionLink(), die in der index über eine 
          Anonymous Function aufgerufen wird, übergeben werden kann
         */
        if (!empty($arrayOfFk)) {
            $searchModel->foreignKeys = $arrayOfFk;
            $sessionPHP = Yii::$app->session;
            $sessionPHP->open();
            $sessionPHP['foreignKeys'] = $arrayOfFk;
            $sessionPHP->close();
        }
    }
    $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
    if (!$sessionPHP->isActive)
        $sessionPHP->open();
    $sessionPHP['searchModel'] = $searchModel;
    $sessionPHP['dataProvider'] = $dataProvider;
    $sessionPHP->close();
    //wurden keine Besichtigungstermine gefunden, aber danach gesucht?
    if ($id != null && empty($arrayOfFk)) {
        $message = 'Für diesen Makler wurde noch kein Besichtigungstermin festgelegt. Wir raten zur umgehender Kündigung dieser faulen Ratte.';
        $this->message($message, 'Warnung!', 2000, Growl::TYPE_WARNING);
        return $this->redirect(['/termin/preselect', 'message' => $message]);
        //wurden Besichtigungstermine gefunden, dann erstelle den Header für den entsprechenden Makler(intern:User)
    } else if ($id != null && !empty($arrayOfFk)) {
        $makler = User::findOne(['id' => $id])->username;
        $header = "Besichtigungstermine für Makler $makler anzeigen";
        return $this->render('index', [
                    'searchModel' => $searchModel,
                    'dataProvider' => $dataProvider,
                    'header' => $header
        ]);
        //nix traf zu? Dann render die index ohne Einschränkungen
    } else {
        return $this->render('index', [
                    'searchModel' => $searchModel,
                    'dataProvider' => $dataProvider
        ]);
    }
}

Thank you.
Well, I don’t know what’s wrong.

Well, that’s shaking me. If u can’t fix bug, nobody will be able fixing it. Because of that, I decided reimplementing code of creating searchModel and dataProvider in actionMap in order to render index again, which is only comromise solution.

I would be hesitant too but a) I’d like to know if it works and if so b) I’d like to clearly understand why it’s a bad idea.

Did you try without the line

?

Yes, I did. No change! By the way, closing session will not remove it!

I’ve just tested it.

Controller: StaffController.php (a bit simplified)

    public function actionIndex()
    {
        $searchModel = new StaffSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        $session = Yii::$app->session;
        $session['searchModel'] = $searchModel;
        $session['dataProvider'] = $dataProvider;
        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }
    public function actionTest()
    {
        $session = Yii::$app->session;
        $searchModel = $session['searchModel'];
        $dataProvider = $session['dataProvider'];
        return $this->render('test', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

View: index.php (simplified)

<div class="staff-index">
    <h1><?= Html::encode($this->title) ?></h1>
    <?= $this->render('_search', ['model' => $searchModel]); ?>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'columns' => [...],
    ]); ?>
    <p><?= Html::a('TEST', ['test'], ['class' => 'btn btn-primary']) ?></p>
</div>

And it worked.

The following is a screen shot of my PhpStorm. The break point is just after

        $session = Yii::$app->session;
        $searchModel = $session['searchModel'];
        $dataProvider = $session['dataProvider'];

And $serchModel and $dataProvider are unserialized from session as expected.

I know. But it makes me nervous when an action method is directly managing the session when that’s the application component’s responsibility. Knowing that such a line does no harm is ok but even better is not needing to know.