1、php如何实现session

执行php脚本,session_start()会从php.ini中读取配置项,将生成的唯一值sessionID保存文件放到配置项中的保存路径和地点。并通过HTTP协议返回响应消息头setCookie
Cookie名=Cookie值发送给客户端。
客户端接受到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定义都是接口类(契约)。
看一下session接口定义的是什么?
<?phpnamespace 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
<?phpnamespace 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);        }    }}