Mặc dù chúng tôi triển khai PSR-18 bằng cách sử dụng Guzzle - thông qua HttPlug - tôi không muốn sử dụng các lớp cụ thể của Guzzle trong cơ sở mã của mình, vì điều đó có thể ngăn chúng tôi di chuyển suôn sẻ sang một bản tóm tắt HTTP khác. Và nó không tương thích với PSR-18
Gửi yêu cầu đăng bài
Có hai phương thức gửi dữ liệu với yêu cầu POST; . Đầu tiên là bản dịch cấu trúc GET sang phần thân POST
POST /a/post/url HTTP/1.1
Host: www.domain.ext
Content-Type: application/x-www-form-urlencoded
field=value&another+field=another+value
Phần thân này có thể đạt được thông qua PHP's
3$body = http_build_query[
['field' => 'value', 'another field' => 'another value'],
'',
'&',
PHP_QUERY_RFC1738
];
Nhưng sử dụng phương pháp tạo yêu cầu POST này không cho phép gửi tệp đính kèm. Đối với những tình huống đó, bạn sẽ cần dùng đến multipart/form-data
nhiều phần/biểu mẫu dữ liệu
Tệp đính kèm không chỉ là dữ liệu [nhị phân] của tệp, nó là tên tệp, loại nội dung và thông tin meta có thể khác. Vì điều này cần một số hình thức cấu trúc, loại nội dung multipart/form-data
đã được giới thiệu trong
6Thực tế, những gì đoạn mã trên làm là tạo một yêu cầu giống như thế này
POST /a/post/url HTTP/1.1
Host: www.domain.ext
Content-Type: multipart/format-data; boundary="a.random.boundary"
--a.random.boundary
Content-Disposition: form-data; name="name"
Content-Length: 4
name
--a.random.boundary
Content-Disposition: form-data; name="file"; filename="screenshot.png"
Content-Type: image.png
{$screenshotData}
--a.random.boundary--
Và mặc dù điều này có thể thực hiện được khi sử dụng giao diện PSR-18 và PSR-15, nhưng nó yêu cầu một số kiến thức về cách thức hoạt động của phần này trong thông số kỹ thuật HTTP
$boundary = 'a.random.boundary';
$request = [new RequestFactory[]]
->createRequest['POST', '//www.domain.ext/a/post/url']
->withHeader['Content-Type', "multipart/form-data; boundary=\"{$boundary}\""]
->withBody[[new StreamFactory[]]->createStream["--{$boundary}" . "\r\n".
"Content-Disposition: form-data; name=\"name\"" . "\r\n" .
"\r\n" .
"{$name}" . "\r\n" .
"--{$boundary}" . "\r\n" .
"Content-Disposition: form-data; name=\"file\"; filename=\"screenshot.php\"" . "\r\n" .
"Content-Type: image/png" . "\r\n" .
"\r\n" .
"{$screenShotData}" . "\r\n" .
"--{$boundary}--"]];
$this->httpClient->sendRequest[$request];
Đây là rất nhiều công việc và nó có một vài cạm bẫy; . Nhưng khi tôi cố gắng gửi tệp tới JIRA, tôi nhận được thông báo lỗi là
7. Sau khi gỡ lỗi khá nhiều, tôi nhận thấy rằng JIRA [hoặc Java] yêu cầu
8 làm ký tự dòng mớiBây giờ tôi có thể tạo một thư viện đẹp cho, nhưng tôi hơi lười, vì vậy tôi thường chuyển sang Packagist trước để xem có ai đã làm việc này chưa. Khi tìm kiếm Packagist cho các gói để xử lý tất cả những điều này cho tôi, bạn sẽ tìm thấy một số gói, nhưng các gói nổi bật là lượt tải xuống và các ngôi sao khôn ngoan.
9Trình tạo luồng nhiều phần
Trình tạo luồng nhiều phần là một gói được tạo bởi nhóm cũng chịu trách nhiệm về HttPlug. Nó - như tên cho thấy - thực sự có nghĩa là xây dựng các luồng nhiều phần
Trình tạo cho Luồng PSR-7 nhiều phần. Trình tạo tạo các luồng độc lập từ bất kỳ triển khai PSR-7 nào
Để tạo yêu cầu tuân thủ PSR-7 với nội dung nhiều phần, chúng tôi cần tạo một phiên bản của trình tạo luồng nhiều phần
use Http\Message\MultipartStream\MultipartStreamBuilder;
$builder = new MultipartStreamBuilder[$streamFactory];
$builder->addResource[
'file',
fopen['/path/to/uploaded/file', 'r'],
[
'filename' => 'filename.ext',
'headers' => ['Content-Type' => 'application/octet-stream']
]
];
$request = $requestFactory
->createRequest['POST', '//...']
->withHeader['Content-Type', 'multipart/form-data; boundary="' . $builder->getBoundary[] . '"']
->withBody[$builder->build[]];
$response = $client->sendRequest[$request];
Điều thú vị về thư viện này là nó trả về một thể hiện của
POST /a/post/url HTTP/1.1
Host: www.domain.ext
Content-Type: application/x-www-form-urlencoded
field=value&another+field=another+value
0. Ngẫu nhiên cùng một loại đối tượng POST /a/post/url HTTP/1.1
Host: www.domain.ext
Content-Type: application/x-www-form-urlencoded
field=value&another+field=another+value
1 mong đợiNhược điểm của thư viện này là trình tạo luồng không phải là bất biến. Việc đưa nó vào ứng dụng của bạn có thể hơi phức tạp vì bộ chứa DI của bạn sẽ trả về một phiên bản mới của trình tạo luồng mỗi khi nó được đưa vào. Bên cạnh đó, tôi thích tiêm dựa trên giao diện, đó là sở thích cá nhân. Một cách giải quyết nhỏ cho vấn đề này có thể dễ dàng tạo ra thông qua một nhà máy