dongshuo6503 2016-10-18 19:48
浏览 50

在您自己的类中访问Slim框架

I'm using Slim Framework version 3.

I've followed the tutorial on creating an app. Part of this involves setting up a classes directory where you can put your own PHP classes.

What I can't understand is how you can access Slim inside those. For example if I have a class src/classes/Users.php and wanted to use the Slim Response code e.g.

return $response->withStatus(302)->withHeader('Location', 'login');

Obviously, $response, is not accessible at that point. It only seems to be in index.php where each callback recieves it as an argument.

Do I have to pass something to every constructor of my own classes, or use or require statements in my classes?

  • 写回答

1条回答 默认 最新

  • dongxi1680 2016-10-19 04:27
    关注

    I'd say when domain layer components need to access application level components - this is a code smell. So, consider doing things otherwise, request object describes request. Request contains some data, and that data should be passed to your User class, not request object itself.

    If you still wish to use Request object in Users class, simply pass it as argument, like this:

    // in your routes
    $app->post('users', function($request, $response) {
        $user = new User;
        $user->hydrateAndPersist($request); // there you pass it as argument
    });
    
    // in your user class
    class User
    {
        public function hydrateAndPersist(
            \Psr\Http\Message\ServerRequestInterface $request,
            \Psr\Http\Message\ResponseInterface $response // yes, you force yourself into injecting response object
        ) {
            // request is here, let's extract data from it
            $submittedData = $request->getParams();
            // terrible indeed, but this is just an example:
            foreach ($submittedData as $prop => $value) {
                $this->prop = $value;
            }
            $result = $this->save();
            return $response->withJson($result);
        }
    }
    

    However, in this case your User class is coupled heavily with PSR-7 request and response objects. Sometimes coupling is not a problem, but in your case User class belongs to domain layer (since it describes User entity), while $request and $response are components of application layer.

    Try to reduce coupling:

    $app->post('users', function($request, $response) {
    
        $submittedData = $request->getParams();
    
        $user = new User;
        $result = $user->hydrateAndPersist($submittedData);
        // response is already declared in this scope, let's "put" result of the operation into it
        $response = $response->withJson($result);
        return $response;
    });
    
    class User
    {
        public function hydrateAndPersist(array $data) : bool
        {
            $result = false;
            foreach ($submittedData as $prop => $value) {
                $this->prop = $value;
            }
            $result = $this->save();
            return $result;
        }
    }
    

    See the benefit? User::hydrateAndPersist now accepts array as argument, it has no knowledge of $request and $response. So, it is not tied to HTTP (PSR-7 describes HTTP messages), it can work with anything. Classes separated, layers separated, ease of maintenance.

    To sum up: you can access $request object in your User class by simply passing $request to one of User methods. However, this is poor design that will reduce maintainability of your code.

    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog