loading...

How to load your posts from dev.to onto your site/app

jamesrweb profile image James Robb Updated on ・4 min read

Working with the DEV API (2 Part Series)

1) How to load your posts from dev.to onto your site/app 2) How to build a paginated blog using the DEV API

While working on my website after some time of non-maintenance, I noticed that I had previously been hand coding the links to blog posts I had made on the DEV platform. This was pretty unruly and didn't look great in the codebase, nor was it efficient of me to keep doing.

My website runs on a PHP and I use Pico CMS which has a really nice plugin setup, so I decided to create a new plugin for Pico to grab the posts programattically for me rather than continuing the hard coded madness of before.

To simplify things though for readers who may not have used something like PICO before, I will just show you the regular PHP implementation without any framework being used.

Before we begin

To follow along and use the implementation below, you will first need to get an API key for the DEV API. This is quite simple to do, so follow these steps before we begin to access your key:

  1. Go to your profile settings page
  2. Enter the description of what you want the API key for
  3. Click Generate API Key
  4. Copy the generated key
  5. Done 😁

The DevPostFetcher class

/**
 * DevPostFetcher - A class to fetch posts from your dev.to profile
 * @author James Robb
 * @version 1.0.0
 */
class DevPostFetcher
{
  /** @var int The page of posts to access */
  private $page = 1;
  /** @var int How many posts to provide per page request */
  private $per_page = 10;
  /** @var string dev.to API Key to access posts */
  private $api_key;

  public function __construct(string $api_key) {
    $this->api_key = $api_key;
  }

  /**
   * @param   int   $per_page The amount of posts to fetch per page request
   * @return  void
   */
  public function setPerPage(int $per_page): void {
    $this->per_page = $per_page;
  }

  /**
   * @return  int
   */
  public function getPerPage(): int {
    return $this->per_page;
  }

  /**
   * @param   int   $page  The page of posts to fetch
   * @return  void
   */
  public function setPage(int $page): void {
    $this->page = $page;
  }

  /**
   * @return  int
   */
  public function getPage(): int {
    return $this->page;
  }

  /**
   * @throws Exception if the DEV API curl request fails
   * @return array An associative (key => value) array of DEV posts
  */
  public function fetch() {
    $page = $this->getPage();
    $per_page = $this->getPerPage();
    $api_key = $this->api_key;
    $ch = curl_init(
      "https://dev.to/api/articles/me?page=$page&per_page=$per_page"
    );
    $requestHeaders = [
      "api-key:$api_key"
    ];

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);
    $posts = curl_exec($ch);
    if (curl_errno($ch)) {
      throw new Exception(curl_error($ch));
    }
    curl_close($ch);
    return json_decode($posts, true);
  }
}

The class revolves around 3 private properties:

  1. $page - the page of posts we want to access
  2. $per_page - how many posts to load per page request
  3. $api_key - the api key we generated earlier

We also have a getter and setter for $page and $per_page setup, these become useful for pagination for example as we will see later in this post.

A sidenote

Sometimes you might get curl errors relating to SSL Certificates on your local machine, to get around these you can add the following lines of code into the fetch() method:

  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Do not use these in production: Use in local development only since this is a security issue and you don't want insecure requests coming in and out on a live server.

Using the class

Latest posts

Let's say we are happy with only getting the latest 10 posts from your account and you want to display them, we can do the following for example:

<?php
  $devPosts = new DevPostFetcher("your_api_key");
  $devPostsList = $devPosts->fetch();
?>
<ul>
  <?php foreach($devPostsList as $post): ?>
    <li>
      <a href="<?php echo $post['url']; ?>">
        <?php echo $post['title']; ?>
      </a>
    </li>
  <?php endforeach; ?>
</ul>

Paginating posts

Let's say we want to paginate our posts, again, it's pretty easy:

<?php
  $devPosts = new DevPostFetcher("your_api_key");
  $firstPagePosts = $devPosts->fetch(); // posts 1 - 10
  $devPosts->setPage(2);
  $secondPagePosts = $devPosts->fetch(); // posts 11 - 20
?>

Note: In the next post of this series, we will build a properly paginated posts application using the DevPostFetcher class, Composer and Flight.

Load more than the default post count

You probably guessed by now but if you wanted to load more than 10 posts per fetch, we could do:

<?php
  $devPosts = new DevPostFetcher("your_api_key");
  $devPosts->setPerPage(20);
  $firstPagePosts = $devPosts->fetch(); // posts 1 - 20
?>

Putting it all together

A full example could be something like this:

<?php
$devPosts = new DevPostFetcher("your_api_key");
$devPosts->setPerPage(5);
$devPosts->setPage(2);
$devPostsList = $devPosts->fetch();
?>
<ul>
  <?php foreach($devPostsList as $post): ?>
    <li>
      <a href="<?php echo $post['url']; ?>">
        <?php echo $post['title']; ?>
      </a>
    </li>
  <?php endforeach; ?>
</ul>

In conclusion

The DEV API is basic but well formed from what I have experienced with this foray into using it, why not go and check it out for yourself?

This series will continue with us building a paginated blog application using the DevPostFetcher class from this post, Composer and Flight.

Working with the DEV API (2 Part Series)

1) How to load your posts from dev.to onto your site/app 2) How to build a paginated blog using the DEV API

Posted on by:

jamesrweb profile

James Robb

@jamesrweb

I am a Polyglot Software Engineer focussed on the web πŸ§‘πŸ»β€πŸ’», an ardent Accessibility Advocate β™Ώ, amateur creative coder πŸ§‘πŸ»β€πŸŽ¨ and an aspiring teacher πŸ‘¨πŸ»β€πŸ«

Discussion

markdown guide
 

You can just get the current page with

$pageQuery = $_GET['page'];
$currentPage = isset($pageQuery) ? $pageQuery : 1;
 

Hey Hammed, thanks for the comment!

I didn't want to add the use of super globals like $_GET, $_POST, $_SESSION, etc since this class should be framework agnostic. By this, I mean, for example you could do any of the following:

Using PHP:

$devPosts = new DevPostFetcher("your_api_key");
$pageQueryParam = $_GET['page'];
$page = 1;

if(isset($pageQueryParam)) {
  $page = (int) $pageQueryParam;
  $page = $page !== 0 ? $page : 1;
}

$devPosts->setPage($page);
$posts = $devPosts->fetch();
require_once 'path/to/template';

Using the Flight framework:

Flight::route('/posts/@page:[1-9]+', function($page) {
  $devPosts = new DevPostFetcher("your_api_key");
  $devPosts->setPage((int) $page);
  $posts = $devPosts->fetch();
  return Flight::render('posts_page', ['posts' => $posts]);
});

Using the Symfony framework:

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

class PostsController extends AbstractController
{
    /**
     * @Route("/posts/{page}", name="post_list", requirements={"page"="\d+"})
     */
    public function list(int $page)
    {
         $devPosts = new DevPostFetcher("your_api_key");
         $devPosts->setPage($page);
         $posts = $devPosts->fetch();
         return $this->render('posts/index.twig', ['posts' => $posts]);
    }
}

The idea, in short, was to not bias anyones implementation choice but merely to show a reusable class that we will build on top of in later posts and that anyone can use, anywhere. I hope that clears up things a bit for anyone else reading the post and this comment later too πŸ˜„.