承接 chronoarc/comicvine 相关项目开发

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

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

chronoarc/comicvine

Composer 安装命令:

composer require chronoarc/comicvine

包简介

A PHP wrapper for the Comicvine API

README 文档

README

Tests Packagist Version Packagist Downloads

A lightweight, slightly opinionated PHP SDK for the ComicVine API, built on top of Saloon v4. Every documented ComicVine endpoint is covered, with typed DTOs for every response.

📦 Installation

composer require chronoarc/comicvine

Requires PHP 8.2+. Grab an API key at comicvine.gamespot.com/api.

🚀 Quick start

use Chronoarc\Comicvine\Comicvine;

$comicvine = new Comicvine('your-api-key');

// Fetch a single resource — /issue/4000-6
$issue = $comicvine->issues()->get(6)->dto();
echo $issue->name;              // "The Lost Race"
echo $issue->volume->name;      // "Chamber of Chills Magazine"
echo $issue->image->originalUrl;

// List resources — /volumes
$volumes = $comicvine->volumes()->all(limit: 50)->dto();
echo $volumes->numberOfTotalResults;
foreach ($volumes->results as $volume) {
    echo $volume->name;
}

// Search everything — /search
$results = $comicvine->search()->query('Batman', resources: ['character'])->dto();

Every resource method returns a Saloon Response; you choose how to consume it:

$response = $comicvine->characters()->get(1699);

$response->dto();     // typed DTO (Character)
$response->json();    // raw decoded payload
$response->status();  // HTTP status code

🗂 Resources

Every ComicVine resource is exposed through a method on the Comicvine connector:

Connector method Endpoints DTOs
$comicvine->characters() /characters, /character Character, CharactersList
$comicvine->chats() /chats, /chat Chat, ChatsList
$comicvine->concepts() /concepts, /concept Concept, ConceptsList
$comicvine->episodes() /episodes, /episode Episode, EpisodesList
$comicvine->issues() /issues, /issue Issue, IssuesList
$comicvine->locations() /locations, /location Location, LocationsList
$comicvine->movies() /movies, /movie Movie, MoviesList
$comicvine->objects() /objects, /object ComicObject, ObjectsList
$comicvine->origins() /origins, /origin Origin, OriginsList
$comicvine->people() /people, /person Person, PeopleList
$comicvine->powers() /powers, /power Power, PowersList
$comicvine->promos() /promos, /promo Promo, PromosList
$comicvine->publishers() /publishers, /publisher Publisher, PublishersList
$comicvine->search() /search SearchResults
$comicvine->series() /series_list, /series Series, SeriesList
$comicvine->storyArcs() /story_arcs, /story_arc StoryArc, StoryArcsList
$comicvine->teams() /teams, /team Team, TeamsList
$comicvine->videoCategories() /video_categories, /video_category VideoCategory, VideoCategoriesList
$comicvine->videos() /videos, /video Video, VideosList
$comicvine->videoTypes() /video_types, /video_type VideoType, VideoTypesList
$comicvine->volumes() /volumes, /volume Volume, VolumesList
$comicvine->meta() /types Type, TypesList

All list endpoints share the same signature:

$comicvine->issues()->all(
    limit: 100,                          // page size, API max is 100
    offset: 200,                         // zero-based offset for pagination
    fieldList: ['id', 'name', 'volume'], // trim the response to specific fields
    sort: 'cover_date:desc',             // field:asc or field:desc
    filter: ['volume' => 1487],          // field => value pairs
);

All detail endpoints share the same signature:

$comicvine->characters()->get(1699, fieldList: ['id', 'name', 'publisher']);

Pagination

List DTOs extend PaginatedList and expose the full envelope:

$page = $comicvine->issues()->all(limit: 100)->dto();

$page->numberOfTotalResults; // e.g. 1024872
$page->numberOfPageResults;  // e.g. 100
$page->limit;                // 100
$page->offset;               // 0
$page->hasMorePages();       // true

$next = $comicvine->issues()->all(limit: 100, offset: $page->offset + $page->limit)->dto();

Search

/search paginates with a 1-based page parameter and caps limit at 10. Results are mixed-type: each item is hydrated into the DTO matching its resource_type (unknown types are kept as raw arrays):

use Chronoarc\Comicvine\Dto\Character\Character;

$results = $comicvine->search()->query('Batman', resources: ['character', 'volume'], page: 1)->dto();

foreach ($results->results as $result) {
    if ($result instanceof Character) {
        echo $result->realName; // "Bruce Wayne"
    }
}

🧬 DTOs

  • Every DTO is readonly and hydrated via ::fromArray(); you never parse JSON yourself.
  • Fields the API omits — association fields on list responses, or anything excluded via field_list — are null, never missing. null means "not fetched", an empty array means "fetched, and empty".
  • Cross-resource pointers are Reference objects (id, name, apiDetailUrl, siteDetailUrl). Specialised references add context: IssueReference (issueNumber), EpisodeReference (episodeNumber), PersonCredit (role), CountedReference (count, used by volume credits).
  • image fields hydrate into Image with all size renditions (iconUrloriginalUrl).
  • Gender is the Chronoarc\Comicvine\Enum\Gender enum (Other / Male / Female).
  • Quirks are normalised: the story arc count_of_isssue_appearances typo (sic, ComicVine's spelling) maps to countOfIssueAppearances, and a person's death object is flattened to a date string.

⚠️ Error handling

The connector uses Saloon's AlwaysThrowOnErrors, so any non-2xx response throws a Saloon request exception:

use Saloon\Exceptions\Request\RequestException;

try {
    $comicvine->issues()->get(999999999)->dto();
} catch (RequestException $e) {
    $e->getResponse()->status();
}

ComicVine rate-limits API keys to 200 requests per resource per hour. Be a good citizen: request only the fields you need via fieldList, and cache responses where you can.

🧩 Extending

The SDK is deliberately thin so you can reach into any layer:

  • Custom requests — extend Chronoarc\Comicvine\Requests\ListRequest or DetailRequest and send them with $comicvine->send(new MyRequest()).
  • Saloon features — the connector is a regular Saloon connector: middleware, retries, caching plugins and mock clients all work as documented at docs.saloon.dev.
  • Raw responses — skip DTOs entirely with ->json() when you need something the DTOs don't model.

🧪 Testing

composer test

Tests use Saloon's MockClient with recorded fixtures — no live API calls, no API key needed.

The test suite also demonstrates how to mock the SDK in your own app:

use Chronoarc\Comicvine\Requests\GetIssueRequest;
use Saloon\Http\Faking\MockClient;
use Saloon\Http\Faking\MockResponse;

$mockClient = new MockClient([
    GetIssueRequest::class => MockResponse::fixture('valid_single_issue'),
]);

$comicvine = new Comicvine('fake-key');
$comicvine->withMockClient($mockClient);

🤝 Contributions Welcome

Your feedback and contributions are highly appreciated! Whether it's submitting an issue, suggesting improvements, or adding new features, every bit helps make this SDK better for everyone.

Feel free to fork the repository, make pull requests, or just share ideas! Let's make this SDK awesome together.

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-11-15

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固