PHP 语言 使用PSR 139标准实现HTTP消息工厂

PHP阿木 发布于 12 天前 5 次阅读


摘要:

随着互联网技术的发展,HTTP协议已成为现代网络通信的基础。在PHP开发中,正确处理HTTP请求和响应是构建高效、可维护的应用的关键。PSR-139标准为PHP HTTP消息工厂的实现提供了规范,本文将围绕这一主题,详细探讨如何在PHP中使用PSR-139标准实现HTTP消息工厂。

一、

PSR-139标准(PHP Standard Recommendation: HTTP Message Factory)是PHP社区为了统一HTTP消息处理而制定的一个规范。该规范定义了HTTP请求和响应的接口,使得开发者可以更容易地创建和操作HTTP消息。本文将基于PSR-139标准,使用PHP实现一个简单的HTTP消息工厂。

二、PSR-139标准概述

PSR-139标准定义了两个接口:`HttpFactoryInterface`和`MessageInterface`。

1. `HttpFactoryInterface`:定义了创建HTTP请求和响应的方法。

2. `MessageInterface`:定义了HTTP请求和响应的公共接口。

三、实现HTTP消息工厂

下面是一个简单的PHP实现,包括`HttpFactoryInterface`和`MessageInterface`的实现。

php

<?php

namespace HttpFactory;

use PsrHttpMessageRequestFactoryInterface;


use PsrHttpMessageRequestInterface;


use PsrHttpMessageResponseFactoryInterface;


use PsrHttpMessageResponseInterface;

class HttpFactory implements RequestFactoryInterface, ResponseFactoryInterface


{


public function createRequest(string $method, $uri): RequestInterface


{


return new Request($method, $uri);


}

public function createResponse(): ResponseInterface


{


return new Response();


}


}

class Request implements RequestInterface


{


private $method;


private $uri;


private $headers = [];


private $body;

public function __construct(string $method, $uri)


{


$this->method = $method;


$this->uri = $uri;


}

public function getMethod(): string


{


return $this->method;


}

public function getUri(): UriInterface


{


return new Uri($this->uri);


}

public function withMethod($method): RequestInterface


{


$new = clone $this;


$new->method = $method;


return $new;


}

public function withUri($uri, $flags = UriInterface::RFC_3986): RequestInterface


{


$new = clone $this;


$new->uri = $uri;


return $new;


}

public function getHeaders(): array


{


return $this->headers;


}

public function hasHeader(string $name): bool


{


return isset($this->headers[$name]);


}

public function getHeader(string $name): array


{


return $this->hasHeader($name) ? $this->headers[$name] : [];


}

public function withHeader(string $name, $value): RequestInterface


{


$new = clone $this;


$new->headers[$name] = $value;


return $new;


}

public function withAddedHeader(string $name, $value): RequestInterface


{


$new = clone $this;


$new->headers[$name] = $value;


return $new;


}

public function withoutHeader(string $name): RequestInterface


{


$new = clone $this;


unset($new->headers[$name]);


return $new;


}

public function getBody(): BodyInterface


{


return new Body($this->body);


}

public function withBody(BodyInterface $body): RequestInterface


{


$new = clone $this;


$new->body = $body;


return $new;


}


}

class Response implements ResponseInterface


{


private $statusCode;


private $reasonPhrase;


private $headers = [];


private $body;

public function __construct($statusCode = 200, $reasonPhrase = 'OK')


{


$this->statusCode = $statusCode;


$this->reasonPhrase = $reasonPhrase;


}

public function getStatusCode(): int


{


return $this->statusCode;


}

public function getReasonPhrase(): string


{


return $this->reasonPhrase;


}

public function withStatus($statusCode, $reasonPhrase = ''): ResponseInterface


{


$new = clone $this;


$new->statusCode = $statusCode;


$new->reasonPhrase = $reasonPhrase;


return $new;


}

public function getHeaders(): array


{


return $this->headers;


}

public function hasHeader(string $name): bool


{


return isset($this->headers[$name]);


}

public function getHeader(string $name): array


{


return $this->hasHeader($name) ? $this->headers[$name] : [];


}

public function withHeader(string $name, $value): ResponseInterface


{


$new = clone $this;


$new->headers[$name] = $value;


return $new;


}

public function withAddedHeader(string $name, $value): ResponseInterface


{


$new = clone $this;


$new->headers[$name] = $value;


return $new;


}

public function withoutHeader(string $name): ResponseInterface


{


$new = clone $this;


unset($new->headers[$name]);


return $new;


}

public function getBody(): BodyInterface


{


return new Body($this->body);


}

public function withBody(BodyInterface $body): ResponseInterface


{


$new = clone $this;


$new->body = $body;


return $new;


}


}

class Body implements BodyInterface


{


private $body;

public function __construct($body)


{


$this->body = $body;


}

public function getContents(): string


{


return $this->body;


}

public function getIterator(): Traversable


{


return new ArrayIterator((array) $this->body);


}

public function getStream(): StreamInterface


{


return new Stream($this->body);


}

public function close(): void


{


// Implementation for closing the stream if needed


}


}

class Stream implements StreamInterface


{


private $body;

public function __construct($body)


{


$this->body = $body;


}

public function isReadable(): bool


{


return true;


}

public function isWritable(): bool


{


return false;


}

public function isSeekable(): bool


{


return false;


}

public function read($length): string


{


return $this->body;


}

public function write($string): int


{


throw new Exception('Stream is not writable');


}

public function seek($offset, $whence = SEEK_SET): void


{


throw new Exception('Stream is not seekable');


}

public function tell(): int


{


return 0;


}

public function eof(): bool


{


return true;


}

public function setMetadata($key, $value): void


{


// Implementation for setting metadata if needed


}

public function getMetadata($key = null): array


{


return [];


}


}

class Uri implements UriInterface


{


private $uri;

public function __construct($uri)


{


$this->uri = $uri;


}

public function getScheme(): string


{


return parse_url($this->uri, PHP_URL_SCHEME);


}

public function withScheme($scheme): UriInterface


{


$new = clone $this;


$new->uri = $scheme . '://' . $this->uri;


return $new;


}

public function getHost(): string


{


return parse_url($this->uri, PHP_URL_HOST);


}

public function withHost($host): UriInterface


{


$new = clone $this;


$new->uri = $this->getScheme() . '://' . $host . $this->uri;


return $new;


}

public function getPort(): ?int


{


return parse_url($this->uri, PHP_URL_PORT);


}

public function withPort($port): UriInterface


{


$new = clone $this;


$new->uri = $this->getScheme() . '://' . $this->getHost() . ':' . $port . $this->uri;


return $new;


}

public function getUserInfo(): string


{


return parse_url($this->uri, PHP_URL_USER);


}

public function withUserInfo($user, $password = null): UriInterface


{


$new = clone $this;


$new->uri = $this->getScheme() . '://' . $user . (isset($password) ? ':' . $password : '') . '@' . $this->getHost() . $this->uri;


return $new;


}

public function getPath(): string


{


return parse_url($this->uri, PHP_URL_PATH);


}

public function withPath($path): UriInterface


{


$new = clone $this;


$new->uri = $this->getScheme() . '://' . $this->getHost() . ':' . $this->getPort() . '/' . $path;


return $new;


}

public function getQuery(): string


{


return parse_url($this->uri, PHP_URL_QUERY);


}

public function withQuery($query): UriInterface


{


$new = clone $this;


$new->uri = $this->getScheme() . '://' . $this->getHost() . ':' . $this->getPort() . '/' . $this->getPath() . '?' . $query;


return $new;


}

public function getFragment(): string


{


return parse_url($this->uri, PHP_URL_FRAGMENT);


}

public function withFragment($fragment): UriInterface


{


$new = clone $this;


$new->uri = $this->getScheme() . '://' . $this->getHost() . ':' . $this->getPort() . '/' . $this->getPath() . '?' . $this->getQuery() . '' . $fragment;


return $new;


}

public function __toString(): string


{


return $this->uri;


}


}


四、使用HTTP消息工厂

现在我们已经实现了HTTP消息工厂,接下来是如何使用它。

php

<?php

use HttpFactoryHttpFactory;

require 'path/to/HttpFactory.php';

$factory = new HttpFactory();

$request = $factory->createRequest('GET', 'http://example.com');


$response = $factory->createResponse();

// 设置请求头


$request = $request->withHeader('Host', 'example.com');

// 设置响应状态码和原因短语


$response = $response->withStatus(200, 'OK');

// 设置响应体


$response = $response->withBody(new Body('Hello, World!'));

// 输出响应


echo $response;


五、总结

本文介绍了PSR-139标准,并使用PHP实现了HTTP消息工厂。通过遵循PSR-139标准,我们可以创建更加统一和可维护的HTTP消息处理代码。在实际项目中,可以根据需要扩展和定制HTTP消息工厂,以满足不同的需求。

注意:以上代码仅为示例,实际应用中可能需要根据具体情况进行调整和优化。