Php slimframework'有问题;中国不变的反应

Php slimframework'有问题;中国不变的反应,php,immutability,slim,psr-7,Php,Immutability,Slim,Psr 7,我正在尝试使用slim framework版本3为API设置一个项目,我不知道是谁制作了PSR-7并将响应对象标记为不可变,我看不出这有什么用(IMHO。如果我错了,请解释我)。当它是苗条的时候,事情就容易多了。过了很长一段时间,我又回到了斯利姆 我有一个路由,它是一个post方法,我正在获取数据并将其保存到数据库中,我正在尝试发送201作为响应代码。所有的示例和文档都向您展示了如何更改index.php文件本身中的响应代码,但我试图从一个响应生成器中进行更改,我尝试使用factory模式来提供

我正在尝试使用slim framework版本3为API设置一个项目,我不知道是谁制作了PSR-7并将响应对象标记为不可变,我看不出这有什么用(IMHO。如果我错了,请解释我)。当它是苗条的时候,事情就容易多了。过了很长一段时间,我又回到了斯利姆

我有一个路由,它是一个post方法,我正在获取数据并将其保存到数据库中,我正在尝试发送201作为响应代码。所有的示例和文档都向您展示了如何更改index.php文件本身中的响应代码,但我试图从一个响应生成器中进行更改,我尝试使用factory模式来提供不同的响应。问题是,无论我从响应生成器类调用什么函数,响应代码始终保持在200。我尝试了许多论坛和不同的瘦身方式,但仍然无法实现。我几乎决定放弃PSR7路由器的实现,转而实现我自己的路由解决方案。但我记得不要再重新发明轮子了,所以我来这里做最后的尝试。下面是代码

路线定义

$app->post('/users', function(ServerRequestInterface $req, ResponseInterface $res) {
    $data = $req->getParsedBody();
    $model = new \Apex\Models\User(ApexDB::getInstance());
    $jsonBuilder = ApexResponse::getBuilder('JSON', $res);
    $control = new \Apex\Controllers\User($model, $jsonBuilder);
    $control->create($data);

});
控制器方法(抽象我只是在设置它)

JSON生成器

class JSONBuilder implements Response
{
    public $response;

    public function __construct($response)
    {
        $this->response = $response;
    }

    public function build($data, $status)
    {
        $response = $this->response->withJSON($data,$status);
        return $response;
    }
}

有人能给我指出正确的方向吗?

元文档的章节中记录了PSR-7使用不可变对象进行请求和响应的决策

对于Slim 3,您必须始终从控制器方法返回
响应
实例

$app->post('/users', function(ServerRequestInterface $req, ResponseInterface $res) {
    $data = $req->getParsedBody();
    $model = new \Apex\Models\User(ApexDB::getInstance());
    $jsonBuilder = ApexResponse::getBuilder('JSON', $res);
    $control = new \Apex\Controllers\User($model, $jsonBuilder);

    return $control->create($data);
});
然后您的
create
方法还需要返回
$response

public function create($data) {
    if($this->model->save($data)) {
        $this->response->build($data,201);
    } else {
        $this->response->build('error',400);
    }
    return $this->response;
}
然后它应该会起作用

但是,您可以直接从路由声明中使用控制器方法,并避免需要关闭:

$app->post('/users', `Apex\Controllers\User::create`);
控制器的
create
方法如下所示:

namespace Apex\Controllers;

class User
{
    public function create($request, $response)
    {
        $data = $request->getParsedBody();

        $model = new \Apex\Models\User(ApexDB::getInstance());
        $jsonBuilder = ApexResponse::getBuilder('JSON', $response);

        if ($model->save($data)) {
            $response = $jsonBuilder->build($data, 201);
        } else {
            $response = $jsonBuilder->build('error', 400);
        }
        return $response;
    }
}
<>最后,考虑一下<代码> JsonBuilder <代码>,尽管它可能比你所展示的要多。


更新:

理想情况下,您应该使用构造函数注入将用户模型注入控制器。为此:

  • 更新控制器:

    namespace Apex\Controllers;
    
    use Apex\Models\User as UserModel;
    
    class User
    {
        protected $userModel;
    
        public function __construct(UserModel $userModel)
        {
            $this->userModel = $userModel;
        }
    
        public function create($request, $response)
        {
            $data = $request->getParsedBody();
    
            $jsonBuilder = ApexResponse::getBuilder('JSON', $response);
    
            if ($this->userModel->save($data)) {
                $response = $jsonBuilder->build($data, 201);
            } else {
                $response = $jsonBuilder->build('error', 400);
            }
            return $response;
        }
    }
    
  • 为Pimple依赖项注入容器编写工厂:

    $container = $app->getContainer();
    $container['Apex\Controllers\User'] = function ($c) {
        $userModel = new \Apex\Models\User(ApexDB::getInstance());
        return new \ApexController\User($userModel);
    };
    

  • PSR-7使用不可变对象进行请求和响应的决策记录在元文档的一节中

    对于Slim 3,您必须始终从控制器方法返回
    响应
    实例

    $app->post('/users', function(ServerRequestInterface $req, ResponseInterface $res) {
        $data = $req->getParsedBody();
        $model = new \Apex\Models\User(ApexDB::getInstance());
        $jsonBuilder = ApexResponse::getBuilder('JSON', $res);
        $control = new \Apex\Controllers\User($model, $jsonBuilder);
    
        return $control->create($data);
    });
    
    然后您的
    create
    方法还需要返回
    $response

    public function create($data) {
        if($this->model->save($data)) {
            $this->response->build($data,201);
        } else {
            $this->response->build('error',400);
        }
        return $this->response;
    }
    
    然后它应该会起作用

    但是,您可以直接从路由声明中使用控制器方法,并避免需要关闭:

    $app->post('/users', `Apex\Controllers\User::create`);
    
    控制器的
    create
    方法如下所示:

    namespace Apex\Controllers;
    
    class User
    {
        public function create($request, $response)
        {
            $data = $request->getParsedBody();
    
            $model = new \Apex\Models\User(ApexDB::getInstance());
            $jsonBuilder = ApexResponse::getBuilder('JSON', $response);
    
            if ($model->save($data)) {
                $response = $jsonBuilder->build($data, 201);
            } else {
                $response = $jsonBuilder->build('error', 400);
            }
            return $response;
        }
    }
    
    <>最后,考虑一下<代码> JsonBuilder <代码>,尽管它可能比你所展示的要多。


    更新:

    理想情况下,您应该使用构造函数注入将用户模型注入控制器。为此:

  • 更新控制器:

    namespace Apex\Controllers;
    
    use Apex\Models\User as UserModel;
    
    class User
    {
        protected $userModel;
    
        public function __construct(UserModel $userModel)
        {
            $this->userModel = $userModel;
        }
    
        public function create($request, $response)
        {
            $data = $request->getParsedBody();
    
            $jsonBuilder = ApexResponse::getBuilder('JSON', $response);
    
            if ($this->userModel->save($data)) {
                $response = $jsonBuilder->build($data, 201);
            } else {
                $response = $jsonBuilder->build('error', 400);
            }
            return $response;
        }
    }
    
  • 为Pimple依赖项注入容器编写工厂:

    $container = $app->getContainer();
    $container['Apex\Controllers\User'] = function ($c) {
        $userModel = new \Apex\Models\User(ApexDB::getInstance());
        return new \ApexController\User($userModel);
    };
    

  • 哦,您可能还想考虑在<代码> 201 < /COD>响应中返回保存的用户对象的<代码> ID <代码>。在猜测中包含一个指向该用户资源(/users/:id)端点的
    位置
    头也是一个好主意。感谢详细的回答,在控制器内创建模型实例不是会产生硬耦合吗?我想我可以使用构造函数注入?还是服务容器?在你看来,哪一个是好的?我将使用构造函数注入模型,是的。哦,你也可以考虑在<代码> 201 < /COD>响应中返回保存的用户对象的<代码> ID <代码>。在猜测中包含一个指向该用户资源(/users/:id)端点的
    位置
    头也是一个好主意。感谢详细的回答,在控制器内创建模型实例不是会产生硬耦合吗?我想我可以使用构造函数注入?还是服务容器?你认为哪一个是好的?我会使用构造函数注入的模型,是的。