Save your Medium posts into your Laravel Application

Arnolfo Federis
4 min readMar 17, 2019
Save your Medium posts into your Laravel Application

Before we start, We need to have Integration tokens from your account. To enable it, we must request access by emailing yourfriends@medium.com.

Once you have your Integration token to navigate it go to settings page under Membership.

Integration tokens from your account

Add your Integration token by Entering the description.

Once you add your token let’s try it in Insomnia REST Client.

Add this url: https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fmedium.com%2Ffeed%2F@yourusername and set Request method to GET.

Add Authorization header and set value to Bearer <your-token>

Click send and see the sample response below.

Sample Response to your Medium Posts

Now we have our Medium posts, Let’s begin to install new Laravel Application.

composer create-project --prefer-dist laravel/laravel blog

Go to your newly Installed Laravel and run some command.

Create Post, Tag Model and Migration.$ php artisan make:model Post -m$ php artisan make:model Tag -m-m to make new migration.Create Pivot table for Post and Tag
$ php artisan make:migration create_post_tag_table --create=post_tag
Create new command to save Medium posts.
$ php artisan make:command SaveMediumPosts

Let’s edit our Model, Migration and Command.

  • Post Model
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
protected $guarded = [];
protected $casts = ['categories' => 'array'];

public function tags()
{
return $this->belongsToMany(Tag::class)->withTimestamps();
}
}
  • Post Migration
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('slug');
$table->string('title');
$table->string('link');
$table->string('guid');
$table->string('author');
$table->string('author_image');
$table->string('author_link');
$table->string('thumbnail');
$table->longText('description');
$table->longText('content');
$table->json('categories');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
  • Tag Model
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
protected $guarded = [];

public function posts()
{
return $this->belongsToMany(Post::class)->withTimestamps();
}
}
  • Tag Migration
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateTagsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string('slug')->unique();
$table->string('name')->unique();
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('tags');
}
}
  • Post Tag Migration
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostTagTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('post_tag', function (Blueprint $table) {
$table->primary(['post_id', 'tag_id']);
$table->unsignedInteger('post_id');
$table->unsignedInteger('tag_id');
$table->timestamps();

$table->foreign('post_id')
->references('id')
->on('posts')
->onDelete('cascade');

$table->foreign('tag_id')
->references('id')
->on('tags')
->onDelete('cascade');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('post_tag');
}
}
  • SaveMediumPosts Command
<?php

namespace App\Console\Commands;

use App\Post;
use App\Tag;
use GuzzleHttp\Client;
use Illuminate\Console\Command;

class SaveMediumPosts extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medium-posts:save';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Save Medium Posts';

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->comment('Saving your Medium posts.');
$client = new Client();
$rss_url = urlencode('https://medium.com/feed/@yourusername');
$url = "https://api.rss2json.com/v1/api.json?rss_url={$rss_url}";
$options = [
'headers' => [
'Authorization' => 'Bearer <your-token>'
]
];

$request = $client->get($url, $options);

$response = $request->getBody();
$this->comment('Your Medium posts saved.');
return $this->handleResponse(json_decode($response->getContents(), true));
}

protected function handleResponse($response)
{
// Check if response is status is ok.
if (strtoupper($response['status']) === 'OK') {
$feed = $response['feed'];
$items = $response['items'];

// Loop the items in response
foreach ($items as $item) {
// Update or Create posts.
$post = Post::updateOrCreate(['guid' => $item['guid']], [
'slug' => str_slug($item['title']),
'title' => $item['title'],
'link' => $item['link'],
'guid' => $item['guid'],
'author' => $item['author'],
'author_image' => $feed['image'],
'author_link' => $feed['url'],
'thumbnail' => $item['thumbnail'],
'description' => $item['description'],
'content' => $item['content'],
'categories' => $item['categories'],
'created_at' => $item['pubDate']
]);

$tags = [];
// Loop categories in item response.
foreach ($item['categories'] as $category) {
// Update or Create tags and save it into $tags variable.
$tags[] = Tag::updateOrCreate(['slug' => $category], [
'slug' => $category,
'name' => ucwords($category)
]);
}

$tag_id = [];
// Loop Saved tags.
foreach ($tags as $tag) {
// Pass saved tags id to $tag_id variable.
$tag_id[] = $tag->id;
}

// Sync tags into your post.
$post->tags()->sync($tag_id);
}
}
}
}
  • Edit .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<your-mysql-database>
DB_USERNAME=<your-mysql-username>
DB_PASSWORD=<your-mysql-password>
  • Migrate
$ php artisan migrate
  • Run SaveMediumPosts Command
$ php artisan medium-posts:saveSaving your Medium posts.
Your Medium posts saved.

That’s All, Check your posts ,tags andpost_tag in your database.

Clap and Share my story on Save your Medium posts into your Laravel Application.

Thanks!

--

--