通过 HTTP 请求实例使用会话与在 Laravel 中使用全局会话助手之间的区别

Posted

技术标签:

【中文标题】通过 HTTP 请求实例使用会话与在 Laravel 中使用全局会话助手之间的区别【英文标题】:difference between using the session via an HTTP request instance versus using the global session helper in Laravel 【发布时间】:2017-07-21 17:19:56 【问题描述】:

我找不到与两种会话访问方法相关的任何信息。 $request->session() 来自 HTTP 请求实例,session() 来自 Laravel 5.3 中的会话助手。 有什么区别或者什么时候用哪一个?

使用 P.H.P 单元时如何向以下控制器方法发送 get 请求

public function testMyMethod(Request $request)
$userExist = $request->session()->exists('user_id');

【问题讨论】:

【参考方案1】:

Service Container 是 Laravel 架构的核心。所有服务、组件和依赖项都在此处注册,您可以在需要时请求其中的任何一个。

但是 Laravel 提供了不止一种“请求它”的方法。你有全局辅助函数,你有门面,你有方法签名中组件实例的“正确”、“更纯粹”的注入。我认为 Laravel 哲学的很大一部分是干净、简单、直观的 API。在这种情况下,您可以根据个人喜好来定义什么是“干净和简单”,并且根据定义,任何与您的风格相匹配的东西对您来说都是直观的。

我知道 php 社区一直在激烈争论哪种方法是“最好的”,外观一直存在争议,传统的依赖注入 OOP 纯粹主义者说唯一正确的方法可能是注入带有控制器方法签名的对象。 .

最后,这些不同的方法中的任何一种都只是从同一个服务容器袋中抓取对象。在性能方面没有区别(我敢打赌,两个间接函数调用不会影响您的性能)或其他方面。因此,请使用更适合您风格的任何东西。如果我在一个典型的控制器中,我个人还是会进行“正确”的注入,但如果它可以在其上下文中生成更清晰、更易读的代码,我可能会使用全局帮助器。

<?php

namespace App\Http\Controllers;

use Illuminate\Contracts\Session\Session;
use Facades\Illuminate\Contracts\Session\Session as SessionRealTimeFacade;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Request as RequestFacade;
use Illuminate\Support\Facades\Session as SessionFacade;
use PHPUnit\Framework\Assert;

class TestController extends Controller

    public function sessionTest(Request $request, Session $session)
    
        $options = [
            $request->session()->get('_token'),
            session()->get('_token'),
            session('_token'),
            $session->get('_token'),
            SessionFacade::get('_token'),
            SessionRealTimeFacade::get('_token'),
            app('session')->get('_token'),
        ];

        array_reduce(
            $options,
            function ($one, $other) 
                Assert::assertEquals($one, $other);
                return $other;
            ,
            array_shift($options)
        );

        return 'All tests passed!';
        

顺便说一句,正如您所见,您有不止 2 个选项 :)

当然,这不仅仅适用于会话,获取请求数据、获取数据库连接等等也是如此。

(另外,我认为您在 5.3 中还没有实时外观)

【讨论】:

感谢您的详细回答。您说request()-&gt;session()session() 之间的区别类似于2 个函数调用,但那不是更复杂吗?我的意思是他们最终返回两个不同的对象***.com/a/43680476/2311074【参考方案2】:

    Laravel 文档

根据 Laravel 文档 - https://laravel.com/docs/5.3/session - “通过 HTTP 请求实例使用会话与使用全局会话帮助程序之间几乎没有实际区别”,并且两者都是可测试的。

-&gt;assertSessionHas($key, $value = null);

    Laravel 启动并运行 - Matt Stauffer

在他的书中(第 320 页),Matt 谈到了访问会话信息的不同方法:

使用Session门面

session()-&gt;get('user_id');

对任何给定的 Illuminate Request 对象使用 session() 方法

Route::get('dashboard', function(Request $request) $request->session()->get('user_id'); );

注入Illuminate\Session\Store的实例

Route::get('dashboard', function(Illuminate\Session\Store $session) return $session->get('user_id'); );

使用全局 session() 助手

$value = session()->get('key); $value = session('key);

他最后的评论是:如果你是 Laravel 的新手并且不确定要使用哪个,我建议使用全局帮助器

所以,我不会担心差异,只选择适合您的“感觉正确”。如果您对任何一种方式都没有偏好,请按照 Matt Stauffer 的建议进行。

【讨论】:

【参考方案3】:

最终,您通常使用这两个选项的方式,$request-&gt;session()session() 之间没有实际区别。但是,从技术上讲,它们返回的对象并不相同。

session() 将返回SessionManager$request-&gt;session() 将返回会话 Store

Store 实际上是包含会话数据的对象。

SessionManager 是管理可用会话Stores 的对象。大多数应用程序只会使用一个会话存储(默认的)。

它们似乎充当同一个对象的原因是,当您在 SessionManager 上调用一个不存在的方法时,它会将该方法调用转发到默认会话 Store

因此,在您的示例中,您使用exists() 方法。 SessionManager 上不存在此方法。因此,如果您要调用session()-&gt;exists('user_id'),它将将该调用转发到默认会话Store,这相当于调用$request-&gt;session()-&gt;exists('user_id')

有人可能会争辩说,在尝试访问会话数据时直接使用$request-&gt;session() 更合适,因为这是返回的内容,并且不需要额外的转发函数调用。但是,您可以权衡利弊来确定使用哪种方法。

【讨论】:

【参考方案4】:

$request->session() 和 session() 都是同一个东西。

在 Laravel 中有两种处理会话数据的主要方式:session() 助手中的全局函数和通过 $request 实例。

你可以这样使用它

public function testMyMethod(Request $request)

    //$userExist = $request->session()->exists('user_id');
    $userExist = $request->session()->has('user_id');


【讨论】:

Ive used both ways. Want to know the difference (is there any performance impact , etc ...) since its 使用会话助手时 php 单元更容易 谢谢朋友,但我真的很想知道他们为什么要分开这个 我们可以在任何地方直接使用 session() 函数,但是 $request 对象不能这就是引入这个函数的原因。 这没有回答问题。如果您始终可以在控制器中使用函数session(),为什么还要使用$request-&gt;session() 访问它?【参考方案5】:

实际上,原生 PHP 会话是一个现成的解决方案,而不是 Laravel 和 Symfony 的更好的实现,后者已经投入了更多的思考。阅读Symfony Session configuration manual entry 的解释,你会明白我的想法。所以有区别,但在思考和实施的方式上。从性能的角度来看,我认为没有太多。我会让你得出你的结论。另一个有帮助的条目是PHP manual

【讨论】:

以上是关于通过 HTTP 请求实例使用会话与在 Laravel 中使用全局会话助手之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

HAProxy动静分离和会话粘性实例

Spring Bean作用域实例

Httpclient4.5.*HttpClient请求,对于新建httpclient实例时保持会话

网络知识补习❄️| 由浅入深了解HTTP典型的 HTTP 会话介绍 + 简单实例

使用Larave5.6l提交POST请求出现The page has expired due to inactivity错误

如何在 http 和 https 之间共享 asp.net 会话