How to use zf3-way to get sessonid? I operate session like "$sessionContainer = new Container('api');"

In my zf3 model, I use the following way to operate my session stuff.
$sessionContainer = new Container(‘api’);

Now I need to get sessionid in my logic, if use the pure php, it will like:
$sessionId = session_id();

I wonder if there is a zf3-official way to get sessionid.

Thanks!

Do you create a zend-mvc based application?

yes! :slightly_smiling_face: :slightly_smiling_face:

Here is the standard way of using zend-session within a zend-mvc-based application:

Install and set configuration

  1. install zend-session per Composer

  2. enable zend-session as module

config/modules.config.php:

return [
    'Zend\Router',
    'Zend\Session', // <-- Add this line
    'Zend\Validator',
    'Application',
];
  1. extend the conifguration

config/autoload/global.config.php:

return [
    // ...
    'session_config'  => [],
    'session_storage' => [
        'type' => Zend\Session\Storage\SessionArrayStorage::class,
    ],
];

Usage with session-container

The session-manager is set for all session-containers per default and the session itself is started in the constructor of a container.

  1. use a session-container

module/Application/src/Controller/IndexController.php:

    public function indexAction()
    {
        $container = new \Zend\Session\Container();
        var_dump($container->getManager()->getId());

        return new ViewModel();
    }

Usage with session-manager (without containers)

  1. add the session-manager to the controller

module/Application/src/Controller/IndexController.php:

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\Session\SessionManager;
use Zend\View\Model\ViewModel;

class IndexController extends AbstractActionController
{
    /**
     * @var SessionManager
     */
    private $sessionManager;

    public function __construct(SessionManager $sessionManager)
    {
        $this->sessionManager = $sessionManager;
    }

    // ...
}
  1. update the controller configuration

module/Application/config/module.config.php:

return [
    'controllers'  => [
        'factories' => [
            Controller\IndexController::class => Zend\Mvc\Controller\LazyControllerAbstractFactory::class,
        ],
    ],
    // ...
];
  1. use the session-manager

You have to start the session yourself!

module/Application/src/Controller/IndexController.php:

    public function indexAction()
    {
        $this->sessionManager->start();
        var_dump($this->sessionManager->getId());

        return new ViewModel();
    }

(The example is based on the zend-skeletion-application.)

The configuration is documented at: https://docs.zendframework.com/zend-session/config/
The session-manager is described at: https://docs.zendframework.com/zend-session/manager/
The containers her: https://docs.zendframework.com/zend-session/container/

And you can get the session-id also with PHP’s standard function session_id. Nothing else is done in the session-manager: https://github.com/zendframework/zend-session/blob/2cfd90e1a2f6b066b9f908599251d8f64f07021b/src/SessionManager.php#L309-L319

2 Likes

Hi Froschdesign, thank you so much!

$this->sessionManager->getId(); It is the right zf3 way solution!

I will use your way to improve my image drag auth plugin as I asked with topic how to get $container in static method. I saw you kindly answer me as well. thank you again.

@froschdesign,

Hi Froschdesign, sorry for bothering you again. I found I got a empty string when I call the getId() method.

The following is my code for your reference:

modules.config.php

return [
    'Zend\Paginator',
    'Zend\Navigation',
    'Zend\ServiceManager\Di',
    'Zend\Session',
    'Zend\Mvc\Plugin\Prg',
    'Zend\Mvc\Plugin\Identity',
    'Zend\Mvc\Plugin\FlashMessenger',
    'Zend\Mvc\Plugin\FilePrg',
    'Zend\Mvc\I18n',
    'Zend\Mvc\Console',
    'Zend\Log',
    'Zend\Form',
    'Zend\Cache',
    'Zend\Db',
    'Zend\Router',
    'Zend\Validator',
    'Application',
    'Album',
    'Blog',
    'Admin',
    'Api',
];

global.php

(before, I use exactly the same with the code you give as configuration. empty seession_id I got, so I changed to the following, still got an empty string via ->getId() method)

'session_config'  => [
    'remember_me_seconds' => 1800,
    'name' => 'wendang',
    'use_cookies' => true,
],
'session_storage' => [
    'type' => SessionArrayStorage::class,
],

module.config.php

is this equal to the factories configuration in the module.config.php?

'controllers' => [
    'abstract_factories' => [
        LazyControllerAbstractFactory::class
    ],
],

Then my controller construction method like:

class ImagedragauthController extends AbstractActionController
{
    private $container;
    private $sessionManager;
    
    public function __construct(ServiceManager $container, SessionManager $sessionManager)
    {
        $this->container = $container;
        $this->sessionManager = $sessionManager;
    }
   
    //****here I passed the $this->sessionManager to a model function as a param, and use this param in the model function as follow***//
}

concrete code using in my demo:

public function validation($container, $sessionManager)
{
    $sessionId = $sessionManager->getId();
    var_dump($sessionId);exit;  //output string(0) "" in the browser
}

output string(0) “” in the browser

Any idea? I thought I can get a long string. Pls tell me.

This is the normal behaviour of PHP’s session_id:

session_id() returns the session id for the current session or the empty string (“”) if there is no current session (no current session id exists).

http://php.net/manual/en/function.session-id.php#refsect1-function.session-id-returnvalues

You must the start a session:

$this->sessionManager->start();
var_dump($this->sessionManager->getId());

$this->sessionManager->getStorage()['foo'] = 'bar';

Then test it in another action:

$this->sessionManager->start();
var_dump($this->sessionManager->getStorage()->toArray());
1 Like

Btw. do not inject the entire service-manager, only a single service!

1 Like

@froschdesign
Thanks for your reply! it do helpful to me! It works.

But I have a question about the session container, I used to set seesion value via session container as:

public function generator()
{
    $bgX = imagesx($this->backgroundImgSrc);
    $bgY = imagesy($this->backgroundImgSrc);
    $smX = imagesx($this->transparentImgSrc);
    $smY = imagesy($this->transparentImgSrc);
    
    $randX = rand(10,($bgX - $smX -5));
    $randY = rand(5,($bgY - $smY - 5));
    
    $sessionContainer = new Container('api'); // <--------------------------
    $sessionContainer->{$this->sessionXname} = $randX; // <--------------------------
    $sessionContainer->{$this->sessionYname} = $randY;  // <--------------------------
    
    return $randY;
} 

In this way, I need to write the $this->sessionManager->start(); before?
It seems the programe works without ** $this->sessionManager->start();** first.
Or I just need to write ** $this->sessionManager->start();** ahead of $this->sessionManager->getId(), pls let me know, thank you!

As you mentioned:

Btw. do not inject the entire service-manager, only a single service!

I need to use the sm as follow, I just knew this way to use service manager inside a model:

public function validation($container, $sessionManager)
{
    $sessionManager->start();

    $threshold = 4;
    $x = (int) $container->get('Request')->getQuery('x'); // <--------------------------
    $y = (int) $container->get('Request')->getQuery('y'); // <--------------------------
    $privateKey = (string) $container->get('Request')->getQuery('privateKey'); // <--------------------------
    $type = (string) $container->get('Request')->getQuery('type');
    
    $config = $container->get("config"); // <--------------------------
}

So my question is that: If not inject the sm as a entire service, what can I do in such situation? You can see I need to get the global config and query params from Request

If you use a session-container and the standard configuration, then the session-manager is set as default manager for session containers. The container start then the session on the manager for you.

See: https://github.com/zendframework/zend-session/blob/master/src/AbstractContainer.php#L83

No, you do not need the entire service-manager, only the request and config. (And I’m sure you do not need the entire configuration. :wink:)

1 Like

@froschdesign

No, I tried, if I wanna to get the session_id, it is no way to write $this->sessionManager->getId() after $sessonContainer = new Container(‘api’) , It must have a $this->sessionManager->start() before these! It is true, you can test in your demo.

I know it will be better to pass the request and config than to pass the entire service-manager. However in the developing process, I am not sure about the structure about the function validation at the beginning.

Besides, I know how to get the request in the controller action, like $this->getRequest()->getQuery(‘privateKey’), and then pass it to the model function I wanna use.
However, I really don’t know how to get the config in the controller action. So as you can see above that I use this way in my controller’s construction function, the magic method __construct like:

class ImagedragauthController extends AbstractActionController
{
    private $container;
    private $sessionManager;
    
    public function __construct(ServiceManager $container, SessionManager $sessionManager)
    {
        $this->container = $container;
        $this->sessionManager = $sessionManager;
    }
   
    //****here I passed the $this->sessionManager to a model function as a param, and use this param in the model function as follow***//
}

As to the config which set in global.php, I only know this way: get it from container. the service_locator in zf2, I used to do it this way. I don’t know any other way. Would you pls teach me a different one?

In fact, not only in the controller-action, but also the viewhelper, model, controller plugin etc.
In zf2, when you got the service-locator, you got everything. Inf zf3, it seems all the entrance is the controller’s __construct() function. To me, a beginning, if I can get the service which configured in the module.php freely, whenever and whereever I want. Hard to dream it, LOL

class Module implements ConfigProviderInterface
{
    public function getConfig()
    {
        return include __DIR__ . '/../config/module.config.php';
    }
    
    public function getServiceConfig()
    {
        return [
            'factories' => [ // <--- all the service defined here, how to get these freely in anywhere, action, model, service, entity, viewhelper, etc
                Model\ApiModel::class => function($container){
                    return new Model\ApiModel($container);
                },
            ],
        ];
    }
}

If you want to use containers, then you do not need the session-manager:

$container = new Zend\Session\Container();
var_dump($container->getManager()->getId());

It works, because with the default configuration the session-manager are added to all session-containers:

1 Like

no!!!
I used like this, but failed again!!! crazy.

$sessionContainer = new Container('api');
$sessionId = $sessionContainer->getManager()->getId(); // <--- empty again!!

I guess there are something wrong with my session configuration in the global.php, Pls teach me:

'session_config'  => [
    'remember_me_seconds' => 1800,
    'name' => 'wendang',
    'use_cookies' => true,
],
'session_storage' => [
    'type' => SessionArrayStorage::class,
],

I deleted all the inject about the session manager already, my application crashed.:joy:

Please create a new application and then test it there. The skeleton application helps here: The Skeleton Application - Tutorials - Zend Framework Docs

No problem here.

Sorry, I can’t see your errors…

1 Like

@froschdesign

Sorry, My fault, it runs okay!! I test it again! Before I judged it via the phenomenon not debug the code really. Sorry for that.

Thank you so much!

No problem.

I have also updated my introduction above. (Note to me: add the example to the documentation)

1 Like

@froschdesign

No problem.

I have also updated my introduction above. (Note to me: add the example to the documentation)

I don’t understand Note to me: add the example to the documentation
Should I paste the full code here? I don’t know how to do so[files locate in different folder], If you need to see the full code, I can send a copy to you. I run a demo for it demo page

It means that it is now my job to add the introduction with code example to the documentation. :smiley:

@froschdesign

It is your job to wirte the documentation for zend framework? You are such a big gun!

Oh no, everyone can contribute to the Zend Framework and also to the documentation. I am a member of the documentation team, but that does not mean that I have to write or can write the entire documentation.

The zend-session documentation is missing the description of how it can be used in an application. Therefore it is difficult for you to find the right way. I hope I can fix that in the near future.