Image Principale

Afficher un flux de photos Instagram avec Laravel


Dans cet article, nous verrons comment créer un système qui récupère les posts Instagram d'un compte pour les afficher ensuite sur une page. Dans cet article, nous créerons une commande Artisan pour aller récupérer les posts toutes les heures, pour les stocker ensuite dans une base de données.

Pour afficher les photos Instagram d'un compte, on pourrait penser qu'il serait simple de simplement faire un appel à l'API d'instagram à chaque fois que l'on souhaite afficher le flux sur une page.

Avec cette méthode, on rencontre assez rapidement plusieurs problèmes:

  • Si l'API d'Instagram possède une limite de requêtes, et que votre site a un traffic non négligeable, vous atteindrez rapidement cette limite, et ne pourrez donc plus afficher le flux au bout d'un moment.
  • Imaginez que vous avez bien optimisé vos performances et que votre site répond en 50ms. Faire un appel à l'API d'Instagram rajoutera à chaque fois, au moins 30ms, et le simple affichage de ce flux divisera vos performances par 2.

Nous allons donc faire de la façon suivante:

  1. Chaque heure, notre application lancera une commande qui ira chercher les informations sur Instagram
  2. Nous allons sauvegarder ces informations dans notre base de données
  3. Nous renverrons directement les informations de notre base de données à nos utilisateurs

Dans cet article, nous verrons uniquement comment afficher la photo, ainsi que le nombre de likes associés.

Cet article est rédigé pour Laravel 5.4

I Création d'une commande Artisan

Comme souvent avec Laravel, il suffit de lancer une petite commande pour créer notre Commande Artisan:

$ php artisan make:command RefreshInstagram

Après avoir fait entrée, vous découvrirez un nouveau fichier dans le dossier /app/Console/Commands. C'est dans ce fichier que nous allons écrire la logique de notre commande.

La première étape est de donner un nom à notre commande. J'ai choisi de l'appeler instagram:refresh

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'instagram:refresh';

Vous pouvez ensuite donner une description à votre commande qui s'affichera lorsqu'un développeur entrera php artisan list.

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Refresh Instagram feed';

Nous écrirons ensuite dans la méthode handle() les actions que nous souhaitons effectuer. Pour l'instant, on va juste lui faire afficher Hello World lorsqu'on lance la commande:

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->info('Hello World');
    }

Il suffit ensuite de déclarer l'existence de notre commande dans le fichier app/Console/Kernel.php pour que le framework la prenne en compte:

    use App\Console\Commands\RefreshInstagram;

    ...

    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        RefreshInstagram::class
    ];

Vous pouvez maintenant lancer votre nouvelle commande pour voir si tout va bien:

$ php artisan instagram:refresh
Hello World

Tout va bien!

Création des modèles pour stocker les informations

Je vais opter pour un stockage assez classique dans une base de données MySQL. Pour cela, j'ai besoin de créer un model qui représentera les informations d'un post Instagram. Je vais l'appeler InstagramPost tout simplement:

$ php artisan make:model InstagramPost -m

Le flag -m va automatiquement créer une migration pour cette entité dans database/migrations. Nous aurons trois champs:

  1. identifier qui représentera l'identifiant unique du post du point de vue d'Instagram
  2. url qui représentera l'url de la photo que l'on souhaite afficher
  3. likes_count qui représentera le nombre de likes de ce post là
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('instagram_posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('identifier');
            $table->text('url');
            $table->integer('likes_count');
            $table->timestamps();
        });
    }

On n'a plus qu'à lancer la commande php artisan migrate pour créer la bonne structure SQL.

Ecrire le contenu de notre commande

On va ensuite écrire le contenu de notre commande. Celle-ci va se charger d'aller récupérer les posts et de les stocker dans la base de données, rien de plus.

Pour effectuer les requêtes, nous allons utiliser un client HTTP pour PHP nommé Guzzle. Si vous ne l'avez pas déjà, il vous suffit de l'installer avec composer: composer require guzzlehttp/guzzle.

Une fois que c'est fait, vous pouvez lire le code suivant que j'ai commenté:

    use GuzzleHttp\Client;

    ...

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // On créé un client HTTP
        $client = new Client();

        // On fait appel à l'API d'Instagram
        $response = $client->get('https://www.instagram.com/el_matella/media/');

        // On transforme la réponse en Array PHP
        $content = json_decode($response->getBody()->getContents(), true);

        // On boucle sur cette réponse
        foreach ($content['items'] as $result) {
            // On vérifie si le post existe déjà dans notre base
            $post = InstagramPost::where('identifier',$result['id'])->first();
            if (is_null($post)) {
                // S'il n'existe pas, on le créé
                $post = new InstagramPost();
                $post->identifier = $result['id'];
            }
            // On met à jour les informations du post
            $post->likes_count = $result['likes']['count'];
            $post->url = $result['images']['standard_resolution']['url'];

            // On sauvegarde les informations dans notre base
            $post->save();
        }

        $this->info('Les posts instagrams ont été mis à jour');
    }

Votre commande est prêt à être utilisée, vous pouvez la lancer dans votre console et vérifier que les posts sont bien sauvegardés dans votre base de données.

Il ne reste plus qu'à dire à Laravel tous les combien de temps vous souhaitez que ces informations soient rafraîchies, toutes les heures me semble être bien. Pour cela, il faut se rendre encore une fois dans le fichier app/Console/Kernel.php et de remplir la méthode schedule():

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('instagram:refresh')
            ->hourly();
    }

C'est fait! Votre commande se lancera toutes les heures, et vous pourrez utiliser les données de votre base de données pour les afficher à vos utilisateurs.