* @since 2.0.6 */ abstract class MultiFieldSession extends Session { /** * @var callable a callback that will be called during session data reading. * The signature of the callback should be as follows: * * ``` * function ($fields) * ``` * * where `$fields` is the storage field set for read session and `$session` is this session instance. * If callback returns an array, it will be merged into the session data. * * For example: * * ```php * function ($fields) { * return [ * 'expireDate' => Yii::$app->formatter->asDate($fields['expire']), * ]; * } * ``` */ public $readCallback; /** * @var callable a callback that will be called during session data writing. * The signature of the callback should be as follows: * * ``` * function ($session) * ``` * * where `$session` is this session instance, this variable can be used to retrieve session data. * Callback should return the actual fields set, which should be saved into the session storage. * * For example: * * ```php * function ($session) { * return [ * 'user_id' => Yii::$app->user->id, * 'ip' => $_SERVER['REMOTE_ADDR'], * 'is_trusted' => $session->get('is_trusted', false), * ]; * } * ``` */ public $writeCallback; /** * Returns a value indicating whether to use custom session storage. * This method overrides the parent implementation and always returns true. * @return bool whether to use custom storage. */ public function getUseCustomStorage() { return true; } /** * Composes storage field set for session writing. * @param string $id Optional session id * @param string $data Optional session data * @return array storage fields */ protected function composeFields($id = null, $data = null) { $fields = $this->writeCallback ? call_user_func($this->writeCallback, $this) : []; if ($id !== null) { $fields['id'] = $id; } if ($data !== null) { $fields['data'] = $data; } return $fields; } /** * Extracts session data from storage field set. * @param array $fields storage fields. * @return string session data. */ protected function extractData($fields) { if ($this->readCallback !== null) { if (!isset($fields['data'])) { $fields['data'] = ''; } $extraData = call_user_func($this->readCallback, $fields); if (!empty($extraData)) { session_decode($fields['data']); $_SESSION = array_merge((array) $_SESSION, (array) $extraData); return session_encode(); } return $fields['data']; } return isset($fields['data']) ? $fields['data'] : ''; } }