如何在 PHP 中创建 dev.to API 包装器来获取最新帖子

2025-06-08

如何在 PHP 中创建 dev.to API 包装器来获取最新帖子

dev.to 平台在内容生产者中越来越受欢迎,尤其是那些专注于分享开发相关教程和文章的人们。与此同时,关于内容所有权的持续讨论也有一定的道理,尽管这也带来了新的需求和问题,即如何提高内容的曝光度并触达更广泛的受众,而像 dev.to 这样的平台极大地促进了这一点。

我们可以两者兼得!

幸运的是,dev.to 有一个公共 API,您可以使用它来获取您的所有帖子,并且您可以自由地处理您自己的内容。

在本教程中,您将学习如何使用原生 PHP(不包含用户空间依赖项)创建 dev.to API 的包装器。我们将构建一个类,使用Curl PHP 扩展来获取您在 dev.to 上的最新帖子。

先决条件

您需要 PHP(php-cli就足够了),并且php-curl扩展安装在您的本地机器或远程开发服务器上。

我们将从命令行运行此脚本,但如果您愿意,也可以从浏览器运行它。在这种情况下,您需要运行以下命令来使用 PHP 的内置 Web 服务器来测试该脚本:

php -S 0.0.0.0:8000
Enter fullscreen mode Exit fullscreen mode

这将使用当前目录作为文档根目录运行测试服务器。您可以通过浏览器访问 来访问它localhost:8000

1. Dev.to API 概述

dev.to API 有几个端点需要通过个人 API 令牌进行授权,但您不需要这样做来从用户那里获取公共帖子。

要获取您的帖子,您需要连接到/articles端点并username使用您自己的 dev.to 用户提供参数。

您可以从浏览器中尝试此查询:

https://dev.to/api/articles?username=erikaheidi
Enter fullscreen mode Exit fullscreen mode

在下一步中,我们将使用它curl来查询此端点并在 PHP 脚本中处理结果。

2. 使用 Curl 查询 API

php-curl扩展允许我们在 PHP 中进行 HTTP 查询,并且是连接和从 API 获取数据的流行选择。

以下代码将使用curl函数连接到 dev.to API 并从指定用户那里提取最新帖子:

<?php

$user = "erikaheidi";
$endpoint = "https://dev.to/api/articles?username=" . $user;

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_URL => $endpoint,
]);

$response = curl_exec($curl);
curl_close($curl);

$articles = json_decode($response, true);
print_r($response);
Enter fullscreen mode Exit fullscreen mode

此代码首先定义我们将要获取其帖子的用户名,以及要查询的端点。

然后,我们初始化一个新的 Curl 资源,并使用该curl_setopt_array函数定义查询的详细信息。该函数CURLOPT_RETURNTRANSFER保证查询生成的输出将在结果中完整返回,而该CURLOPT_URL选项则定义了查询端点。

curl_exec函数进行查询并将其结果返回给一个$response变量。然后,我们关闭 Curl 资源,并使用json_decode将返回的 json 解码为一个数组,稍后我们可以循环遍历该数组来展示帖子。

print_r方法是一种调试方法,用于向我们显示有关$articles数组的详细信息。

当您运行此代码时(从命令行或浏览器),您应该获得类似如下的输出:

Array
(
    [0] => Array
        (
            [type_of] => article
            [id] => 261347
            [title] => Which Techie Are You?
            [description] => Our desks tell a lot about ourselves, don't they? What is your style? 
            [cover_image] => https://res.cloudinary.com/practicaldev/image/fetch/s--PkX-bPVo--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/i/76j8y68yfscszyf3ripv.png
            [readable_publish_date] => Feb 14
            [social_image] => https://res.cloudinary.com/practicaldev/image/fetch/s--m81Jlno9--/c_imagga_scale,f_auto,fl_progressive,h_500,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/i/76j8y68yfscszyf3ripv.png
            [slug] => which-techie-are-you-1251
            [path] => /erikaheidi/which-techie-are-you-1251
            [url] => https://dev.to/erikaheidi/which-techie-are-you-1251
            [canonical_url] => https://dev.to/erikaheidi/which-techie-are-you-1251
            [comments_count] => 109
            [positive_reactions_count] => 121
            [collection_id] => 
            [created_at] => 2020-02-14T07:18:34Z
            [edited_at] => 2020-02-21T16:01:57Z
            [crossposted_at] => 
            [published_at] => 2020-02-14T11:31:10Z
            [last_comment_at] => 2020-02-25T09:17:36Z
            [published_timestamp] => 2020-02-14T11:31:10Z
            [tag_list] => Array
                (
                    [0] => discuss
                    [1] => illustrations
                    [2] => comics
                    [3] => humour
                )

            [tags] => discuss, illustrations, comics, humour
            [user] => Array
                (
                    [name] => Erika Heidi
                    [username] => erikaheidi
                    [twitter_username] => erikaheidi
                    [github_username] => erikaheidi
                    [website_url] => http://heidislab.com
                    [profile_image] => https://res.cloudinary.com/practicaldev/image/fetch/s--ABUlwZrQ--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/162988/5faf315a-4b14-4103-8640-983dfe9d57c2.jpg
                    [profile_image_90] => https://res.cloudinary.com/practicaldev/image/fetch/s--V9Gwrj-u--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/162988/5faf315a-4b14-4103-8640-983dfe9d57c2.jpg
                )

            [flare_tag] => Array
                (
                    [name] => discuss
                    [bg_color_hex] => #000000
                    [text_color_hex] => #FFFFFF
                )

        )

    [1] => Array
        (
            [type_of] => article
            [id] => 252194
            [title] => A Git from the Future (Comic)
            [description] => When working with Git, we often clone existing projects, since this is part of a typical collaboration workflow. What if we want to bootstrap a whole new project of our own?
            [cover_image] => https://res.cloudinary.com/practicaldev/image/fetch/s--WsP0wEBA--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/i/pvb1vbr5k5tirzqxhlp2.jpg
            [readable_publish_date] => Jan 31
            [social_image] => https://res.cloudinary.com/practicaldev/image/fetch/s--2m-4zDiP--/c_imagga_scale,f_auto,fl_progressive,h_500,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/i/pvb1vbr5k5tirzqxhlp2.jpg
            [slug] => a-git-from-the-future-comic-p86
            [path] => /erikaheidi/a-git-from-the-future-comic-p86
            [url] => https://dev.to/erikaheidi/a-git-from-the-future-comic-p86
            [canonical_url] => https://dev.to/erikaheidi/a-git-from-the-future-comic-p86
            [comments_count] => 15
            [positive_reactions_count] => 147
            [collection_id] => 4483
            [created_at] => 2020-01-31T11:12:49Z
            [edited_at] => 2020-01-31T11:51:03Z
            [crossposted_at] => 
            [published_at] => 2020-01-31T11:48:56Z
            [last_comment_at] => 2020-02-10T04:59:03Z
            [published_timestamp] => 2020-01-31T11:48:56Z
            [tag_list] => Array
                (
                    [0] => git
                    [1] => beginners
                    [2] => comics
                    [3] => illustrated
                )

            [tags] => git, beginners, comics, illustrated
            [user] => Array
                (
                    [name] => Erika Heidi
                    [username] => erikaheidi
                    [twitter_username] => erikaheidi
                    [github_username] => erikaheidi
                    [website_url] => http://heidislab.com
                    [profile_image] => https://res.cloudinary.com/practicaldev/image/fetch/s--ABUlwZrQ--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/162988/5faf315a-4b14-4103-8640-983dfe9d57c2.jpg
                    [profile_image_90] => https://res.cloudinary.com/practicaldev/image/fetch/s--V9Gwrj-u--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/162988/5faf315a-4b14-4103-8640-983dfe9d57c2.jpg
                )

        )

...
)

Enter fullscreen mode Exit fullscreen mode

您会注意到,结果仅包含文章信息的摘要,而不包含文章本身的正文。根据您的用例,您可能还想获取文章的内容;这将需要对列表中的每篇文章进行额外的查询。

在下一节中,我们将重构此代码以将其转变为一个类,然后我们将包含一种新方法来获取单个文章。

3.创建 API 包装类

到目前为止,我们已经了解了如何使用 Curl PHP 扩展向 dev.to API 发出查询,以获取包含最新帖子的列表。现在,我们将创建一个 Wrapper 类,以便于处理这些操作并在多个位置复用代码。

在您选择的目录中创建一个新文件夹并DevtoWrapper.php在其中命名一个新文件。

下面的代码定义了一个名为的新类,DevtoWrapper其中包含我们在上一节中看到的代码,现在重构为一个类:

<?php

class DevtoWrapper
{
    static $ARTICLES_ENDPOINT = 'https://dev.to/api/articles';

    public function fetchArticlesFromUser($username)
    {
        return $this->get(self::$ARTICLES_ENDPOINT . "?username=" . $username);
    }

    private function get($endpoint)
    {
        $curl = curl_init();
        curl_setopt_array($curl, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_URL => $endpoint,
        ]);

        $response = curl_exec($curl);
        curl_close($curl);

        return json_decode($response, true);
    }
}
Enter fullscreen mode Exit fullscreen mode

我们已经创建了一个get方法,如果我们要包含查询 API 的新方法,其中的部分代码将会重复,就像我们接下来要做的那样。

但首先,让我们替换test.php代码以包含该类文件,实例化一个新DevtoWrapper对象并调用该fetchArticlesFromUser方法:

<?php

require('DevtoWrapper.php');

$user = "erikaheidi";
$wrapper = new DevtoWrapper();

$articles = $wrapper->fetchArticlesFromUser($user);
print_r($articles);

Enter fullscreen mode Exit fullscreen mode

现在运行test.php脚本将产生与之前相同的输出。

现在,您可以向该类添加其他方法DevtoWrapper。我们将添加一个方法来调用/articles/{article_id}端点,该方法将获取完整的文章信息,包括 Markdown 和 HTML 格式的内容正文。

DevtoWrapper包含该方法后,更新后的类如下所示fetchArticle

<?php

class DevtoWrapper
{
    static $ARTICLES_ENDPOINT = 'https://dev.to/api/articles';

    public function fetchArticlesFromUser($username)
    {
        return $this->get(self::$ARTICLES_ENDPOINT . "?username=" . $username);
    }

    public function fetchArticle($article_id)
    {
        return $this->get(self::$ARTICLES_ENDPOINT . "/" . $article_id);
    }

    private function get($endpoint)
    {
        $curl = curl_init();
        curl_setopt_array($curl, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_URL => $endpoint,
        ]);

        $response = curl_exec($curl);
        curl_close($curl);

        return json_decode($response, true);
    }
}
Enter fullscreen mode Exit fullscreen mode

更新您的DevtoWrapper课程后,您现在可以通过循环列表并调用fetchArticle每篇文章的方法来获取所有文章的完整内容。

以下代码将获取您最近的 30 篇文章,并将其完整的 Markdown 正文保存到.md名为 的目录中的本地文件中articles。请确保在运行代码之前创建此目录:

<?php

require('DevtoWrapper.php');

$user = "erikaheidi";
$articles_dir = "articles";

$wrapper = new DevtoWrapper();

$articles = $wrapper->fetchArticlesFromUser($user);

foreach ($articles as $article) {
    echo "Importing " . $article['title'] . "...\n";

    $filename = $article['slug'] . '.md';
    $full_article = $wrapper->fetchArticle($article['id']);

    try {
        $file = fopen($articles_dir . '/' . $filename, 'w+');
        fwrite($file, $full_article['body_markdown']);
        fclose($file);
    } catch (Exception $e) {
        echo "There was an error while trying to save the file.";
    }
}
Enter fullscreen mode Exit fullscreen mode

运行此代码时,它会在每次循环迭代时输出一条消息,告知您正在导入哪篇文章foreach。完成后,请检查您的articles文件夹 - 您应该在那里找到您的文章,它们位于单独的.md文件中,包含您在 dev.to 帐户上发布的完整 Markdown 正文。

ls articles
Enter fullscreen mode Exit fullscreen mode
a-git-from-the-future-comic-p86.md
an-introduction-to-3d-printing-ln1.md
a-primer-on-basic-electronics-and-circuits-n3e.md
bootstrapping-a-cli-php-application-in-vanilla-php-4ee.md
building-minicli-autoloading-command-namespaces-3ljm.md
creativity-is-the-pipeline-2pm6.md
...
Enter fullscreen mode Exit fullscreen mode

如果您想在自己的博客或网站上显示全部内容,将 dev.to 帖子导入 markdown 文件会非常有用,但如果您只想展示帖子摘要,也可以使用列表并链接回 dev.to。

结论

在本教程中,我们了解了如何将您的 dev.to 文章导入本地 markdown 文件,然后您可以将其聚合到现有的博客或网站。

接下来,您可以使用 Markdown 解析器(例如ParseDownExtra)将 Markdown 内容转换为 HTML,或者使用数据库来保存文章内容以及与其相关的所有元数据,从而更轻松地在您自己的博客或网站上搜索和列出这些帖子。

鏂囩珷鏉ユ簮锛�https://dev.to/erikaheidi/how-to-create-a-dev-to-api-wrapper-in-php-to-fetch-your-latest-posts-1fei
PREV
设置 Obsidian 进行内容规划和项目管理
NEXT
基础电子学和电路入门