wtfzdotnet/php-tmdb-api

PHP 对 TMDB (TheMovieDatabase) API v3 的包装。支持两种方法,一种使用存储库、模型和工厂建模,另一种通过简单数组访问来自电影数据库的原始数据。

4.1.3 2022-11-04 19:25 UTC

README

License License Build Status Build Status codecov PHP Total Downloads

使用最小、正常和开发依赖运行测试。

买我一杯咖啡,或者一杯啤酒 :-)

我的胃会感激你的捐赠!

主要功能

  • 电影数据库的数组实现(原始)
  • 利用存储库的电影数据库的模型实现
  • 一个 ImageHelper 类,帮助构建图片 URL 或 HTML 元素。

注意 PHP 新手

如果你是 PHP 新手并开始一个项目来学习,我建议你跳到安装部分,然后遵循专为你们准备的快速入门

我确实建议你在以后更广泛地了解所有这些 PSR 标准对 PHP 社区意味着什么以及它们的作用。

PSR 合规性

我们尽量为这个库的最终用户提供尽可能多的选项,因此,在 4.0 版本中,我们对其进行了修改,以引入我们可以的 PSR 合规性。你带来你喜欢的符合 PSR 标准的依赖项,注册监听器,我们处理其余部分。

框架实现

安装

安装 composer

在我们能够安装 API 库之前,您需要安装一系列依赖,这些依赖提供了以下实现。

您必须自行满足的依赖

  • 例如,对于 PSR-7: HTTP 消息接口,例如 nyholm/psr7
  • 例如,对于 PSR-14: 事件调度器,例如 symfony/event-dispatcher
  • 例如,对于 PSR-17: HTTP 工厂,例如 nyholm/psr7
  • 例如,对于 PSR-18: HTTP 客户端,例如 guzzlehttp/guzzle

我强烈建议实现可选的缓存实现

在利用缓存时,请确保在 composer 中也包含 php-http/cache-plugin,此插件为我们处理逻辑,所以我们不必重新发明轮子。然而,您也可以选择实现自己的缓存监听器,或在您选择的 http 客户端内部添加缓存逻辑。

composer require php-http/cache-plugin:^1.7

尽管 themoviedb.org 自 2019 年底已禁用 速率限制,但我仍建议启用缓存以使您的应用程序运行得更顺畅。因此,之前版本中的 427 重试订阅者不再存在。

  • 例如,对于 PSR-6: 缓存接口,例如 symfony/cache
  • 例如,对于 PSR-16: 简单缓存,使用 PSR-6 适配器,例如 symfony/cache,然后使用 PSR-16 到 PSR-6 适配器

这不仅会使您的应用程序更具响应性,通过在可能的情况下从缓存中加载数据,而且还会减少我们需要发送的请求数量。

可选依赖

  • 例如,对于 PSR-3: 记录器接口,例如 monolog/monolog

安装 php-tmdb/api

如果满足上述要求,您就可以安装库了。

composer require php-tmdb/api:^4

包含 Composer 的自动加载器

require_once dirname(__DIR__).'/vendor/autoload.php';

要使用提供的示例,将 examples/apikey.php.dist 复制到 examples/apikey.php 并更改设置。

初次接触 PSR 标准或 composer 吗?

如果您来这里是为了开始一个有趣的项目以开始学习,上面的内容可能看起来有些令人望而却步。

别担心!此处提供的文档也考虑到了初学者。

我们还提供了 examples/ 文件夹中的一系列示例。

要开始:

composer require php-tmdb/api:^4 symfony/event-dispatcher guzzlehttp/guzzle symfony/cache monolog/monolog nyholm/psr7

现在我们已经安装了所有需要的软件,让我们开始设置以使用库。

快速设置

查看下面的设置文件,并查看 示例 文件夹,例如 examples/movies/api/get.phpexamples/movies/api/get.php 文件。

构造客户端

如果您选择了与之前示例不同的实现,显然所有后续的文档都不会匹配。请根据您的依赖关系进行调整,我们将继续使用之前给出的示例。

通用 API 使用

如果您正在寻找一个简单的数组入口点,API 命名空间是您需要去的地方,但我们建议您使用下面的 仓库和模型 功能。

use Tmdb\Client;

$client = new Client();
$movie = $client->getMoviesApi()->getMovie(550);

如果您想提供任何其他查询参数。

use Tmdb\Client;

$client = new Client();
$movie = $client->getMoviesApi()->getMovie(550, ['language' => 'en']);

对于所有后续调用,只需查看提供的 单元测试示例,或直接查看 API 类本身。

模型使用

该库也可以以面向对象的方式使用,我认为这是做事的首选方式。

您不需要直接调用客户端,而是将客户端传递给多个仓库之一,并在其上执行一些操作。

use Tmdb\Repository\MovieRepository;
use Tmdb\Client;

$client = new Client();
$repository = new MovieRepository($client);
$movie = $repository->load(87421);

echo $movie->getTitle();

仓库还包含通过 API 命名空间可用的其他 API 方法。

use Tmdb\Repository\MovieRepository;
use Tmdb\Client;

$client = new Client();
$repository = new MovieRepository($client);
$topRated = $repository->getTopRated(['page' => 3]);
// or
$popular = $repository->getPopular();

对于所有后续调用,只需查看提供的 单元测试示例,或直接查看模型本身。

事件分发

在库内部,我们可以分发以下事件,通过使用事件监听器,您可以修改某些行为。

HTTP 客户端异常

  • Tmdb\Event\HttpClientExceptionEvent
    • 允许在错误可以纠正的情况下仍然设置一个成功的响应,通过在您的监听器中调用 $event->isPropagated() 实现,这需要您提供一个 PSR-7 响应对象,并使用 $event->setResponse($response) 设置它。

TMDB API 异常

  • Tmdb\Event\TmdbExceptionEvent
    • 允许在错误可以纠正的情况下仍然设置一个成功的响应,通过在您的监听器中调用 $event->isPropagated() 实现,这需要您提供一个 PSR-7 响应对象,并使用 $event->setResponse($response) 设置它。

数据填充

  • Tmdb\Event\BeforeHydrationEvent允许在数据被填充之前修改响应数据。
    • 即使将 event_listener_handles_hydration 选项设置为 false,此事件仍将被抛出,这允许例如记录器仍然生成记录。
  • Tmdb\Event\AfterHydrationEvent允许修改最终返回的主题。

在事件分发器中,当前的数据填充实现造成了重大的开销,您可能根本不希望这样做。

未来我们将进一步研究以改进此问题,但现在我们还有更重要的事情要做。

4.0 版本开始,默认情况下已禁用数据填充事件。

要重新启用此功能,我们建议仅对需要修改数据的模型使用它;

use Tmdb\Client;

$client = new Client([
    'hydration' => [
        'event_listener_handles_hydration' => true,
        'only_for_specified_models' => [
            Tmdb\Model\Movie::class
        ]
    ]
]);

如果已应用此配置,请确保您使用的事件分发器了解我们的 HydrationListener

use Symfony\Component\EventDispatcher\EventDispatcher;
use Tmdb\Event\HydrationEvent;
use Tmdb\Event\Listener\HydrationListener;

$eventDispatcher = new EventDispatcher();
$hydrationListener = new HydrationListener($eventDispatcher);
$eventDispatcher->addListener(HydrationEvent::class, $hydrationListener);

如果您在不指定任何模型的情况下重新启用此功能,所有数据填充将通过事件监听器完成。

请求与响应

  • Tmdb\Event\BeforeRequestEvent
    • 允许在发送之前修改 PSR-7 请求数据。
    • 允许通过在您的监听器中调用 $event->isPropagated() 实现早期响应行为(例如缓存),这需要您提供一个 PSR-7 响应对象,并使用 $event->setResponse($response) 设置它。
  • Tmdb\Event\ResponseEvent
    • 包含 Request 对象。
    • 允许在数据填充之前修改PSR-7响应,这需要您提供PSR-7响应对象,并使用$event->setResponse($response)设置它。
    • 允许最终用户实现自己的缓存,或者对给定响应执行任何其他操作。

事件监听器

我们提供了一些可选的事件监听器,您可以将其添加以提供额外功能。

缓存

而不是构建默认的RequestListener,使用Psr6CachedRequestListener构建客户端。

use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Tmdb\Event\Listener\Psr6CachedRequestListener;
use Tmdb\Repository\MovieRepository;
use Tmdb\Client;

$client = new Client();

$cache = new FilesystemAdapter('php-tmdb', 86400, __DIR__ . '/cache');
$requestListener = new Psr6CachedRequestListener(
    $client->getHttpClient(),
    $client->getEventDispatcher(),
    $cache,
    $client->getHttpClient()->getPsr17StreamFactory(),
    []
);

$repository = new MovieRepository($client);
$popular = $repository->getPopular();

当前的实现将来会再次改变,这要么涉及监听器注册的小幅变化,要么在没有您意识到的情况下发生。我们目前基于php-http/cache-plugin,它引入了我们实际上并不使用的额外依赖项。由于缓存是一个相当大的主题,目前我们选择了“快速而粗略的方法”。

日志记录

日志记录被分成几个监听器,因此您可以决定您想要记录的内容,或者不记录。所有这些监听器都支持写入自定义格式化的消息。请参阅位于Tmdb\Formatter命名空间中的相关接口和类。

您可以用任何PSR-3兼容的记录器替换monolog。

Tmdb\Event\Listener\Logger\LogApiErrorListener

use Monolog\Logger;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Tmdb\Event\Listener\Logger\LogApiErrorListener;
use Tmdb\Event\TmdbExceptionEvent;
use Tmdb\Formatter\TmdbApiException\SimpleTmdbApiExceptionFormatter;

$eventDispatcher = new EventDispatcher();
$apiErrorListener = new LogApiErrorListener(
    new Logger(),
    new SimpleTmdbApiExceptionFormatter()
);

$eventDispatcher->addListener(TmdbExceptionEvent::class, $apiErrorListener);

这将记录在成功接收到响应后抛出的异常,但响应指示请求未成功。

[2021-01-01 13:24:14] php-tmdb.CRITICAL: Critical API exception: 7 Invalid API key: You must be granted a valid key. [] []

Tmdb\Event\Listener\Logger\LogHttpMessageListener

use Symfony\Component\EventDispatcher\EventDispatcher;
use Tmdb\Event\BeforeRequestEvent;
use Tmdb\Event\HttpClientExceptionEvent;
use Tmdb\Event\Listener\Logger\LogHttpMessageListener;
use Tmdb\Event\ResponseEvent;
use Tmdb\Formatter\HttpMessage\SimpleHttpMessageFormatter;

$eventDispatcher = new EventDispatcher();
$requestLoggerListener = new LogHttpMessageListener(
    new Monolog\Logger(),
    new SimpleHttpMessageFormatter()
);

$eventDispatcher->addListener(BeforeRequestEvent::class, $requestLoggerListener);
$eventDispatcher->addListener(ResponseEvent::class, $requestLoggerListener);
$eventDispatcher->addListener(HttpClientExceptionEvent::class, $requestLoggerListener);

这将记录出入站请求和响应。

[2021-01-01 13:11:18] php-tmdb.INFO: Sending request: GET https://api.themoviedb.org/3/company/1?include_adult=true&language=en-US&region=us 1.1 {"length":0,"has_session_token":false} []
[2021-01-01 13:11:18] php-tmdb.INFO: Received response: 200 OK 1.1 {"status_code":200,"length":223} []

对于任何其他PSR-18客户端异常(例如连接错误),这些也将被写入日志。

[2021-01-01 13:36:39] php-tmdb.INFO: Sending request: GET https://api.themoviedb.org/3/company/1?include_adult=true&language=en-US&region=us 1.1 {"length":0,"has_session_token":false} []
[2021-01-01 13:36:39] php-tmdb.CRITICAL: Critical http client error: 0 cURL error 7: Failed to connect to api.themoviedb.org port 443: Connection refused (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) {"request":"https://api.themoviedb.org/3/company/1?include_adult=true&language=en-US&region=us"} []

Tmdb\Event\Listener\Logger\LogHydrationListener

use Symfony\Component\EventDispatcher\EventDispatcher;
use Tmdb\Event\BeforeHydrationEvent;
use Tmdb\Event\Listener\Logger\LogHydrationListener;
use Tmdb\Formatter\Hydration\SimpleHydrationFormatter;

$eventDispatcher = new EventDispatcher();
$hydrationLoggerListener = new LogHydrationListener(
    new Monolog\Logger(),
    new SimpleHydrationFormatter(),
    false // set to true if you wish to add the json data passed for each hydration, do not use this in production!
);

$eventDispatcher->addListener(BeforeHydrationEvent::class, $hydrationLoggerListener);

这将记录带有(可选的)数据的模型填充,这对于调试很有用。

[2021-01-01 13:11:18] php-tmdb.DEBUG: Hydrating model "Tmdb\Model\Image\LogoImage". {"data":{"file_path":"/o86DbpburjxrqAzEDhXZcyE8pDb.png"},"data_size":49} []
[2021-01-01 13:11:18] php-tmdb.DEBUG: Hydrating model "Tmdb\Model\Company". {"data":{"description":"","headquarters":"San Francisco, California","homepage":"https://www.lucasfilm.com/","id":1,"logo_path":"/o86DbpburjxrqAzEDhXZcyE8pDb.png","name":"Lucasfilm Ltd.","origin_country":"US","parent_company":null},"data_size":227} []

对于包含大量附加数据的调用,这很快就会在日志文件中生成大量数据,因此我建议仅在必要时使用此功能。

在生产环境中不要启用数据填充的日志记录,它将生成大量日志。.

成人过滤

要启用包含被认为是“成人”的结果,请添加以下监听器。

use Symfony\Component\EventDispatcher\EventDispatcher;
use Tmdb\Event\BeforeRequestEvent;
use Tmdb\Event\Listener\Request\AdultFilterRequestListener;

$eventDispatcher = new EventDispatcher();
$adultFilterListener = new AdultFilterRequestListener(true);

$eventDispatcher->addListener(BeforeRequestEvent::class, $adultFilterListener);

语言过滤

要启用按语言过滤内容,请添加以下监听器。

use Symfony\Component\EventDispatcher\EventDispatcher;
use Tmdb\Event\BeforeRequestEvent;
use Tmdb\Event\Listener\Request\LanguageFilterRequestListener;

$eventDispatcher = new EventDispatcher();
$languageFilterListener = new LanguageFilterRequestListener('nl-NL');

$eventDispatcher->addListener(BeforeRequestEvent::class, $languageFilterListener);

地区过滤

要启用按地区过滤内容,请添加以下监听器。

use Symfony\Component\EventDispatcher\EventDispatcher;
use Tmdb\Event\BeforeRequestEvent;
use Tmdb\Event\Listener\Request\RegionFilterRequestListener;

$eventDispatcher = new EventDispatcher();
$regionFilterListener = new RegionFilterRequestListener('nl');

$eventDispatcher->addListener(BeforeRequestEvent::class, $regionFilterListener);

访客会话

如果您想使用访客会话,您需要在客户端明确指定此操作。

use Tmdb\Client;
use Tmdb\Token\Session\GuestSessionToken;

$client = new Client();
$client->setGuestSessionToken(new GuestSessionToken('my_token'));

// Now you can make calls in the guest sessions namespace. 

图像助手

存在一个ImageHelper类来处理图像,这需要加载配置。

use Tmdb\Client;
use Tmdb\Helper\ImageHelper;
use Tmdb\Model\Image;
use Tmdb\Repository\ConfigurationRepository;

$client = new Client();
$image = new Image();
$configRepository = new ConfigurationRepository($client);
$config = $configRepository->load();

$imageHelper = new ImageHelper($config);

echo $imageHelper->getHtml($image, 'w154', 154, 80);

集合过滤

我们还提供了一些简单的方法来过滤任何集合,但请注意,您始终可以通过使用闭包轻松实现自己的过滤器。

use Tmdb\Model\Movie;
use Tmdb\Model\Image\PosterImage;

$movie = new Movie();

foreach($movie->getImages()->filter(
        function($key, $value){
            return $value instanceof PosterImage;
        }
    ) as $image) {
        // do something with all poster images
}

然而,这些基本的过滤器已经包含在Images集合对象中。

use Tmdb\Model\Movie;

/** @var $movie Movie **/
$backdrop = $movie
    ->getImages()
    ->filterBackdrops()
;

还有更多的集合提供过滤功能,但您将在使用过程中发现它们。

通用集合和结果集合

  • GenericCollection可以存储任何对象的集合(例如,电影的集合)。
  • ResultCollectionGenericCollection的扩展,并从结果集继承了响应参数(页面、总页数、总结果数),这可以用于创建分页。