承接 flytachi/winter-cast 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

flytachi/winter-cast

最新稳定版本:v1.0.1

Composer 安装命令:

composer require flytachi/winter-cast

包简介

Winter framework cast component

README 文档

README

Latest Version on Packagist Software License

A modern, fluent HTTP client for PHP 8.3+ with a focus on developer experience, type safety, and ease of use.

Features

Fluent API - Chainable methods for building requests
🎯 Type-Safe - Full PHP 8.3+ type declarations
🚀 Zero Config - Works out of the box with sensible defaults
🔄 Auto-Retry - Built-in retry logic for failed requests
Fast - Powered by cURL for maximum performance
🛡️ Secure - URL validation, response size limits, timeout controls
🎭 Facade Pattern - Simple static interface or DI-friendly client
📝 PSR-3 Logging - Automatic request/response logging
💥 Smart Exceptions - Specific exception types for different errors

Installation

composer require flytachi/winter-cast

Requirements:

  • PHP >= 8.3
  • ext-curl

Quick Start

Simple GET Request

use Flytachi\Winter\Cast\Cast;

// One-liner
$response = Cast::sendGet('https://api.example.com/users');
$users = $response->json();

// Or with fluent API
$response = Cast::get('https://api.example.com/users')
    ->timeout(5)
    ->send();

POST with JSON

use Flytachi\Winter\Cast\Cast;
use Flytachi\Winter\Cast\Common\CastHeader;

$response = Cast::post('https://api.example.com/users')
    ->withHeaders(
        CastHeader::instance()
            ->json()
            ->authBearer($token)
    )
    ->withJsonBody([
        'name' => 'John Doe',
        'email' => 'john@example.com'
    ])
    ->throwOnError()
    ->send();

$user = $response->json();

Core Concepts

1. Cast Facade (Simple Usage)

The Cast facade provides a zero-configuration entry point:

// Build request (returns CastRequest)
$request = Cast::get('https://api.com/data');

// Send immediately (returns CastResponse)
$response = Cast::sendGet('https://api.com/data');

Available methods:

  • get(), post(), put(), patch(), delete(), head()
  • sendGet(), sendPost(), sendPut(), sendPatch(), sendDelete(), sendHead()

2. CastRequest (Request Builder)

Build requests with a fluent interface:

use Flytachi\Winter\Cast\Common\CastRequest;

$request = CastRequest::get('https://api.com/users')
    ->withQueryParam('page', 1)
    ->withQueryParam('limit', 10)
    ->timeout(30)
    ->connectTimeout(5)
    ->retry(3, 1000)  // 3 retries, 1s delay
    ->maxResponseSize(50 * 1024 * 1024)  // 50MB limit
    ->throwOnError()
    ->send();

3. CastHeader (Header Builder)

Fluent interface for headers:

use Flytachi\Winter\Cast\Common\CastHeader;

$headers = CastHeader::instance()
    ->json()                      // Accept + Content-Type
    ->authBearer($token)          // Authorization: Bearer
    ->acceptLanguage('ru')        // Accept-Language
    ->userAgent('MyApp/1.0')      // User-Agent
    ->set('X-Custom', 'value');   // Custom header

Built-in helpers:

  • json() - Set Accept and Content-Type for JSON
  • authBearer($token) - Bearer authentication
  • authBasic($user, $pass) - Basic authentication
  • acceptLanguage($lang) - Accept-Language header
  • userAgent($agent) - User-Agent header
  • referer($url) - Referer header
  • contentType($type) - Content-Type header

4. CastResponse (Response Object)

Immutable response with helper methods:

$response->statusCode;        // int: HTTP status code
$response->body();            // ?string: Raw body
$response->json();            // ?array: Parsed JSON
$response->headers();         // array: All headers
$response->header('X-Rate-Limit');  // ?string: Specific header
$response->info();            // array: cURL info

// Status checks
$response->isSuccess();       // 2xx
$response->isClientError();   // 4xx
$response->isServerError();   // 5xx
$response->isRedirection();   // 3xx
$response->isConnectionError(); // Connection failed

Advanced Usage

Query Parameters

// Static params
Cast::get('https://api.com/search', ['q' => 'php', 'type' => 'repos']);

// Dynamic params
Cast::get('https://api.com/search')
    ->withQueryParam('q', 'php')
    ->withQueryParam('type', 'repos')
    ->withQueryParams(['sort' => 'stars', 'order' => 'desc'])
    ->send();

Request Body

// JSON body
Cast::post($url)
    ->withJsonBody(['key' => 'value'])
    ->send();

// Form data
Cast::post($url)
    ->withFormParams(['key' => 'value'])
    ->send();

// Multipart (file upload)
Cast::post($url)
    ->withMultipartBody([
        'file' => new CURLFile('/path/to/file.jpg'),
        'title' => 'My Image'
    ])
    ->send();

// Raw body
Cast::post($url)
    ->withBody('<xml>data</xml>')
    ->send();

Timeouts & Retries

Cast::get($url)
    ->timeout(30)           // Total request timeout (seconds)
    ->connectTimeout(10)    // Connection timeout (seconds)
    ->retry(3, 2000)        // 3 retries, 2 second delay
    ->send();

Error Handling

use Flytachi\Winter\Cast\Exception\TimeoutException;
use Flytachi\Winter\Cast\Exception\ConnectionException;
use Flytachi\Winter\Cast\Exception\RequestException;

try {
    $response = Cast::get($url)
        ->throwOnError()  // Enable exceptions for HTTP errors
        ->send();
        
} catch (TimeoutException $e) {
    // Request timed out - retry with longer timeout
    echo "Timeout: {$e->getMessage()}";
    
} catch (ConnectionException $e) {
    // Connection failed - try backup server
    echo "Connection failed: {$e->getMessage()}";
    
} catch (RequestException $e) {
    // HTTP error (4xx/5xx) - access response object
    echo "HTTP {$e->response->statusCode}: {$e->response->body()}";
}

Exception hierarchy:

  • CastException - Base exception
    • TimeoutException - Request/connection timeout
    • ConnectionException - DNS, connection refused, etc.
    • RequestException - HTTP errors (4xx/5xx)

Dependency Injection

use Flytachi\Winter\Cast\Common\CastClient;
use Flytachi\Winter\Cast\Common\CastRequest;

class ApiService
{
    public function __construct(
        private readonly CastClient $httpClient
    ) {}
    
    public function fetchUsers(): array
    {
        $request = CastRequest::get('https://api.com/users')
            ->timeout(5);
            
        $response = $this->httpClient->send($request);
        return $response->json();
    }
}

// DI Container configuration
$client = new CastClient(
    defaultTimeout: 30,
    defaultConnectTimeout: 10
);
$service = new ApiService($client);

Custom Client Configuration

$client = new CastClient(
    defaultTimeout: 60,
    defaultConnectTimeout: 15,
    defaultOptions: [
        CURLOPT_SSL_VERIFYPEER => false,  // Disable SSL verification (dev only!)
        CURLOPT_FOLLOWLOCATION => true,
    ]
);

// Use custom client
Cast::setGlobalClient($client);

Security Features

URL Validation

Automatically validates URLs and rejects dangerous protocols:

// ✅ Allowed
Cast::get('https://api.com/data')->send();
Cast::get('http://localhost/api')->send();

// ❌ Rejected (throws CastException)
Cast::get('file:///etc/passwd')->send();
Cast::get('ftp://example.com')->send();

Response Size Limit

Prevent memory exhaustion with automatic size limits:

// Default: 10MB limit
Cast::get($url)->send();

// Custom limit
Cast::get($url)
    ->maxResponseSize(50 * 1024 * 1024)  // 50MB
    ->send();

// Disable limit (use with caution!)
Cast::get($url)
    ->maxResponseSize(null)
    ->send();

Logging

Automatic PSR-3 logging via LoggerRegistry:

Logged events:

  • Request start (DEBUG)
  • Request completion (DEBUG)
  • Request failures (DEBUG)
  • Retry attempts (DEBUG)
  • HTTP errors (DEBUG)

Example log output:

[DEBUG] Sending request {"method":"GET","url":"https://api.com/users","timeout":10}
[DEBUG] Completed request {"method":"GET","url":"https://api.com/users","status":200,"duration":0.234}

Testing

use Flytachi\Winter\Cast\Common\CastClient;
use Flytachi\Winter\Cast\Common\CastResponse;

// Mock client for testing
class MockClient extends CastClient
{
    public function send(CastRequest $request): CastResponse
    {
        return new CastResponse(
            statusCode: 200,
            body: '{"id":1,"name":"Test User"}',
            headers: ['Content-Type' => 'application/json'],
            info: []
        );
    }
}

$service = new ApiService(new MockClient());

Examples

GitHub API

$repos = Cast::get('https://api.github.com/users/flytachi/repos')
    ->withHeaders(
        CastHeader::instance()
            ->acceptLanguage('en')
            ->userAgent('Winter-Cast/1.0')
    )
    ->send()
    ->json();

Authenticated API Request

$response = Cast::post('https://api.example.com/data')
    ->withHeaders(
        CastHeader::instance()
            ->json()
            ->authBearer($accessToken)
    )
    ->withJsonBody(['key' => 'value'])
    ->throwOnError()
    ->send();

File Download

$response = Cast::get('https://example.com/file.pdf')
    ->maxResponseSize(100 * 1024 * 1024)  // 100MB
    ->timeout(120)
    ->send();

file_put_contents('/tmp/file.pdf', $response->body());

Pagination

$page = 1;
$allUsers = [];

do {
    $response = Cast::get('https://api.com/users')
        ->withQueryParam('page', $page)
        ->withQueryParam('limit', 100)
        ->send();
        
    $data = $response->json();
    $allUsers = array_merge($allUsers, $data['users']);
    $page++;
    
} while (!empty($data['users']));

License

The MIT License (MIT). Please see License File for more information.

Credits

  • Author: Flytachi
  • Framework: Winter Framework
  • Built with: PHP 8.3+, cURL

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 4
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-01-09