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

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

查看所有标签

猜你喜欢:

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

创业无畏

创业无畏

彼得· 戴曼迪斯、史蒂芬· 科特勒 / 贾拥民 / 浙江人民出版社 / 2015-8 / 69.90元

 您是否有最大胆的商业梦想?您是否想把一个好主意快速转化为一家市值几百亿甚至几千亿元的公司?《创业无畏》不仅分享了成功创业家的真知灼见,更为我们绘制了一幅激情创业的行动路线图!  创业缺人手怎么办?如何解决钱的问题?把握指数型大众工具,互联网就是你车间,你的仓库。拥有好的创意,自然有人把钱“白白地送给你用”。当你大海捞针的时候,激励性大奖赛会让针自己跑到你的眼前来!  掌握指数级......一起来看看 《创业无畏》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

随机密码生成器
随机密码生成器

多种字符组合密码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具