php如何实现session,自己实现session,laravel如何实现session

栏目: PHP · 发布时间: 5年前

内容简介:执行php脚本,session_start()会从php.ini中读取配置项,将生成的唯一值sessionID保存文件放到配置项中的保存路径和地点。并通过HTTP协议返回响应消息头setCookie客户端接受到Set-Cookie,将cookie值写入cookie文件在接下来的访问中,客户端会携带cookie访问浏览器,浏览器接受到cookie值,生成http请求头将包含的COOKIE发送给Php,php识别cookie值,从保存路径中找对应的文件。

1、 php 如何实现session

执行php脚本,session_start()会从php.ini中读取配置项,将生成的唯一值sessionID保存文件放到配置项中的保存路径和地点。并通过HTTP协议返回响应消息头setCookie

客户端接受到Set-Cookie,将cookie值写入cookie文件

在接下来的访问中,客户端会携带cookie访问浏览器,浏览器接受到cookie值,生成http请求头将包含的COOKIE发送给Php,php识别cookie值,从保存路径中找对应的文件。

找到文件之后,检验是否在有效期内,在有效期内就读取文件,不再有效期内就清空文件

2、自己实现session需要考虑的几个问题

1)、生成唯一值的算法

2)、将session存到文件里还是存到 redis 还是memcache,应该存什么数据

3)、接受cookie值,从保存位置找到对应的文件或数据

4)、session垃圾回收机制,删除session文件和数据

5)、分布式的话,session同步问题

3、分析一下 laravel 如何实现session.

vendor/laravel/framework/src/Illuminate/Contracts定义都是接口类(契约)。

<?php

namespace Illuminate\Contracts\Session;

interface Session
{
    public function getName();//获得session名字

    public function getId();//获得当前sessionID

    public function setId($id);//修改sessionID

    public function start();//启动session,从配置文件中读取数据

    public function save();//将session数据保存

    public function all();//获得所有的session

    public function exists($key);//检查session名称是否存在

    public function has($key);//检查session名称是否存在和不为空

    public function get($key, $default = null);//通过session名称获取session值

    public function put($key, $value = null);//将session名称和session值存入session文件或数据库

    public function token(); //获得csrf token的值
 
    public function remove($key);//根据session名称删除session信息

    public function forget($keys);//根据session名称删除session信息

    public function flush();//清空所有的session内容

    public function migrate($destroy = false); //为session会话创建一个新的session会话

    public function isStarted();//确定会话是否启动

    public function previousUrl();//从会话中获取session的url

    public function setPreviousUrl($url);//设置previous的url存入session

    public function getHandler();//获得session处理实例

    public function handlerNeedsRequest();//确定会话程序是否需要请求

    public function setRequestOnHandler($request);//在处理请求实例上设置请求
}

实现接口类的具体实现类只有一个vendor/laravel/framework/src/Illuminate/Session/Store.php

<?php

namespace Illuminate\Session;

use Closure;
use stdClass;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use SessionHandlerInterface;
use Illuminate\Contracts\Session\Session;

class Store implements Session
{
    protected $id;

    protected $name;

    protected $attributes = [];

    protected $handler;

    protected $started = false;

    public function __construct($name, SessionHandlerInterface $handler, $id = null)
    {
        $this->setId($id);
        $this->name = $name;
        $this->handler = $handler;
    }

    public function start()
    {
        $this->loadSession();

        if (! $this->has('_token')) {
            $this->regenerateToken();
        }

        return $this->started = true;
    }

    protected function loadSession()
    {
        $this->attributes = array_merge($this->attributes, $this->readFromHandler());
    }

    protected function readFromHandler()
    {
        if ($data = $this->handler->read($this->getId())) {
            $data = @unserialize($this->prepareForUnserialize($data));

            if ($data !== false && ! is_null($data) && is_array($data)) {
                return $data;
            }
        }

        return [];
    }

    protected function prepareForUnserialize($data)
    {
        return $data;
    }


    public function save()
    {
        $this->ageFlashData();

        $this->handler->write($this->getId(), $this->prepareForStorage(
            serialize($this->attributes)
        ));

        $this->started = false;
    }

    protected function prepareForStorage($data)
    {
        return $data;
    }


    public function ageFlashData()
    {
        $this->forget($this->get('_flash.old', []));

        $this->put('_flash.old', $this->get('_flash.new', []));

        $this->put('_flash.new', []);
    }


    public function all()
    {
        return $this->attributes;
    }


    public function exists($key)
    {
        $placeholder = new stdClass;

        return ! collect(is_array($key) ? $key : func_get_args())->contains(function ($key) use ($placeholder) {
            return $this->get($key, $placeholder) === $placeholder;
        });
    }


    public function has($key)
    {
        return ! collect(is_array($key) ? $key : func_get_args())->contains(function ($key) {
            return is_null($this->get($key));
        });
    }

    public function get($key, $default = null)
    {
        return Arr::get($this->attributes, $key, $default);
    }


    public function pull($key, $default = null)
    {
        return Arr::pull($this->attributes, $key, $default);
    }

    public function hasOldInput($key = null)
    {
        $old = $this->getOldInput($key);

        return is_null($key) ? count($old) > 0 : ! is_null($old);
    }

    public function getOldInput($key = null, $default = null)
    {
        return Arr::get($this->get('_old_input', []), $key, $default);
    }


    public function replace(array $attributes)
    {
        $this->put($attributes);
    }

    public function put($key, $value = null)
    {
        if (! is_array($key)) {
            $key = [$key => $value];
        }

        foreach ($key as $arrayKey => $arrayValue) {
            Arr::set($this->attributes, $arrayKey, $arrayValue);
        }
    }


    public function remember($key, Closure $callback)
    {
        if (! is_null($value = $this->get($key))) {
            return $value;
        }

        return tap($callback(), function ($value) use ($key) {
            $this->put($key, $value);
        });
    }


    public function push($key, $value)
    {
        $array = $this->get($key, []);

        $array[] = $value;

        $this->put($key, $array);
    }


    public function increment($key, $amount = 1)
    {
        $this->put($key, $value = $this->get($key, 0) + $amount);

        return $value;
    }


    public function decrement($key, $amount = 1)
    {
        return $this->increment($key, $amount * -1);
    }


    public function flash(string $key, $value = true)
    {
        $this->put($key, $value);

        $this->push('_flash.new', $key);

        $this->removeFromOldFlashData([$key]);
    }

    public function now($key, $value)
    {
        $this->put($key, $value);

        $this->push('_flash.old', $key);
    }

    public function reflash()
    {
        $this->mergeNewFlashes($this->get('_flash.old', []));

        $this->put('_flash.old', []);
    }

    public function keep($keys = null)
    {
        $this->mergeNewFlashes($keys = is_array($keys) ? $keys : func_get_args());

        $this->removeFromOldFlashData($keys);
    }


    protected function mergeNewFlashes(array $keys)
    {
        $values = array_unique(array_merge($this->get('_flash.new', []), $keys));

        $this->put('_flash.new', $values);
    }

    protected function removeFromOldFlashData(array $keys)
    {
        $this->put('_flash.old', array_diff($this->get('_flash.old', []), $keys));
    }


    public function flashInput(array $value)
    {
        $this->flash('_old_input', $value);
    }


    public function remove($key)
    {
        return Arr::pull($this->attributes, $key);
    }

    public function forget($keys)
    {
        Arr::forget($this->attributes, $keys);
    }

    public function flush()
    {
        $this->attributes = [];
    }

    public function invalidate()
    {
        $this->flush();

        return $this->migrate(true);
    }

    public function regenerate($destroy = false)
    {
        return tap($this->migrate($destroy), function () {
            $this->regenerateToken();
        });
    }

    public function migrate($destroy = false)
    {
        if ($destroy) {
            $this->handler->destroy($this->getId());
        }

        $this->setExists(false);

        $this->setId($this->generateSessionId());

        return true;
    }

    public function isStarted()
    {
        return $this->started;
    }


    public function getName()
    {
        return $this->name;
    }


    public function setName($name)
    {
        $this->name = $name;
    }

    public function getId()
    {
        return $this->id;
    }

    public function setId($id)
    {
        $this->id = $this->isValidId($id) ? $id : $this->generateSessionId();
    }

    public function isValidId($id)
    {
        return is_string($id) && ctype_alnum($id) && strlen($id) === 40;
    }

    protected function generateSessionId()
    {
        return Str::random(40);
    }

    public function setExists($value)
    {
        if ($this->handler instanceof ExistenceAwareInterface) {
            $this->handler->setExists($value);
        }
    }


    public function token()
    {
        return $this->get('_token');
    }


    public function regenerateToken()
    {
        $this->put('_token', Str::random(40));
    }


    public function previousUrl()
    {
        return $this->get('_previous.url');
    }


    public function setPreviousUrl($url)
    {
        $this->put('_previous.url', $url);
    }


    public function getHandler()
    {
        return $this->handler;
    }

    public function handlerNeedsRequest()
    {
        return $this->handler instanceof CookieSessionHandler;
    }

    public function setRequestOnHandler($request)
    {
        if ($this->handlerNeedsRequest()) {
            $this->handler->setRequest($request);
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Text Processing in Python

Text Processing in Python

David Mertz / Addison-Wesley Professional / 2003-6-12 / USD 54.99

Text Processing in Python describes techniques for manipulation of text using the Python programming language. At the broadest level, text processing is simply taking textual information and doing som......一起来看看 《Text Processing in Python》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换