Mettre en production une application Symfony 5 avec Heroku

Introduction

Je reçois très souvent des messages me demandant comment mettre en production une application Symfony. Il existe de nombreuses possibilités pour réaliser cela, aujourd’hui je vais vous présenter une solution simple (et gratuite dans un cadre d’un apprentissage).

En effet, aujourd’hui nous allons voir ensemble comment déployer une application Symfony (avec une base de donnée) sur les services de Heroku ! Heroku c’est ce que l’on appelle un PaaS (Platform as a Service), et il vous propose de “gérer” pour vous toute la partie infrastructure !

En gros, vous n’avez qu’à vous concentrer sur votre code, Heroku va faire le reste 😉

Le projet

Histoire de rendre cette découverte plus proche d’un cas réel, je vous propose le cas d’usage suivant :

  • On vous demande de développer une petite application permettant aux visiteurs de lister et partager leurs vidéos YouTube favorite
  • Pour chacune des vidéos nous voulons stocker l’url et un nom
  • Une page doit lister toutes les vidéos (pour la démo nous ne mettrons pas en place de pagination) avec la miniature de la vidéo
  • Une page doit permettre de consulter une vidéo, avec le nom et un player YouTube
  • Pour faciliter le déploiement de l’application sur Heroku, la base de données devra être une base Postgres (et non pas MySQL ou MariaDB)

Initialiser le projet Symfony

Commençons par initier un nouveau projet Symfony 5.

symfony new youtube-heroku --full
cd youtube-heroku

Mettre en place une base de donnée Postgres avec Docker

Profitons de l’intégration de docker et docker-compose par le serveur Symfony pour mettre en place notre base de données de développement. Créons un fichier docker-compose.yml à la racine du projet.

version: '3'

services:
    database:
        image: postgres:13-alpine
        environment:
            POSTGRES_USER: main
            POSTGRES_PASSWORD: main
            POSTGRES_DB: main
        ports: [5432]

La prise en charge de ce fichier par le serveur Symfony nous permet de ne pas avoir besoin de déclarer notre base de données dans le fichier .env, cela va être fait pour nous.

Démarrons le conteneur et le serveur Symfony.

docker-compose up  -d
symfony serve  -d

Créons la base de données.

symfony console doctrine:database:create

Créons l’entité Youtube

Créons l’entité qui va stocker les URL et les noms des vidéos.

symfony console make:entity Youtube

 created: src/Entity/Youtube.php
 created: src/Repository/YoutubeRepository.php
 
 Entity generated! Now let's add some fields!
 You can always add more fields later manually or by re-running this command.

 New property name (press <return> to stop adding fields):
 > url

 Field type (enter ? to see all types) [string]:
 > string

 Field length [255]:
 > 255

 Can this field be null in the database (nullable) (yes/no) [no]:
 > no

 updated: src/Entity/Youtube.php

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > name 

 Field type (enter ? to see all types) [string]:
 > string

 Field length [255]:
 > 255

 Can this field be null in the database (nullable) (yes/no) [no]:
 > no

 updated: src/Entity/Youtube.php

 Add another property? Enter the property name (or press <return> to stop adding fields):
 >
      
  Success!

N’oublions pas de générer la migration et de l’appliquée !

symfony console make:migration
symfony console d:m:m

Créons le formulaire YoutubeType

Histoire de pouvoir alimenter notre entité, créons-nous un formulaire.

symfony console make:form YoutubeType

 The name of Entity or fully qualified model class name that the new form will be bound to (empty for none):
 > Youtube

 created: src/Form/YoutubeType.php
      
  Success!

Éditons le fichier src/Form/YoutubeType.php pour personnaliser notre formulaire.

<?php

namespace App\Form;

use App\Entity\Youtube;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class YoutubeType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('url', UrlType::class)
            ->add('name', TextType::class)
            ->add('Submit', SubmitType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Youtube::class,
        ]);
    }
}

Créons un contrôleur pour gérer nos pages

Il est temps de mettre en place le contrôleur qui gérera nos deux pages.

symfony console make:controller Youtube

Éditons le fichier src/Controller/YoutubeController.php, pour dans un premier temps, afficher le formulaire d’ajout.

/**
     * @Route("/", name="app_home")
     */
    public function index(Request $request, EntityManagerInterface $em): Response
    {
        $youtube = new Youtube();

        $form = $this->createForm(YoutubeType::class, $youtube);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $youtube = $form->getData();

            $em->persist($youtube);
            $em->flush();

            return $this->redirectToRoute('app_home');

        }

        return $this->render('youtube/index.html.twig', [
            'form' => $form->createView(),
        ]);
    }

Modifions le fichier /templates/youtube.index.html.twig pour y ajouter le formulaire.

{% extends 'base.html.twig' %}

{% block title %}Best Youtube Video !{% endblock %}

{% block body %}

    {{ form(form) }}

{% endblock %}

Ajoutons le code nécessaire pour récupérer toutes les entrées de notre entités YouTube, et envoyons les vers la vue.

public function index(Request $request, EntityManagerInterface $em, YoutubeRepository $youtubeRepository): Response
    {
        (...)

        return $this->render('youtube/index.html.twig', [
            'form' => $form->createView(),
            'youtubes' => $youtubeRepository->findAll(),
        ]);
    }

Modifions notre fichier /templates/youtube/index.html.twig pour afficher les liens de vidéos.

{% extends 'base.html.twig' %}

{% block title %}Best Youtube Video !{% endblock %}

{% block body %}

    {{ form(form) }}

    {% for youtube in youtubes %}

        <p>{{ youtube.url }} - {{ youtube.name }}</p>
        
    {% endfor %}

{% endblock %}

Vérifions que tout fonctionne dans un navigateur internet.

Ajoutons un peu de style avec Bootstrap !

Histoire que notre petite application soit un peu plus sympathique, nous allons mettre en place Bootstrap via un CDN (pour un vrai projet une technique plus complète et personnalisable est décrite ici). Modifions donc notre fichier /templates/base.html.twig.

<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title>
			{% block title %}Welcome!
			{% endblock %}
		</title>
		{% block stylesheets %}
			<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
		{% endblock %}
	</head>

	<body>
		<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-5">
			<div class="container-fluid">
				<a class="navbar-brand" href="#">YoutubeHeroku</a>
				<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
					<span class="navbar-toggler-icon"></span>
				</button>
				<div class="collapse navbar-collapse" id="navbarNav">
					<ul class="navbar-nav">
						<li class="nav-item">
							<a class="nav-link active" aria-current="page" href="{{ path('app_home') }}">Toutes les vidéos</a>
						</li>
                        <li class="nav-item">
							<a class="nav-link active" aria-current="page" href="{{ path('app_home') }}#addvideo">Ajouter une vidéo</a>
						</li>
					</ul>
				</div>
			</div>
		</nav>

		<div class="container">
            {% block body %}{% endblock %}
		</div>

		{% block javascripts %}
            <!-- JavaScript Bundle with Popper -->
            <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
        {% endblock %}

	</body>
</html>

Indiquons à twig de styliser nos formulaires avec Bootstrap, pour cela modifions le fichier /config/packages/twig.yaml.

twig:
    default_path: '%kernel.project_dir%/templates'
    form_themes: ['bootstrap_4_layout.html.twig']

Affichons la liste de nos vidéos avec leurs miniatures

Rappelez-vous la demande initiale d’afficher toutes nos vidéos avec leurs vignettes. Occupons-nous de cela.

Pour éviter d’écrire les bouts de code permettant de récupérer les vignettes (et plus tard les players), j’ai trouvé cette petite librairie qui fera le job pour cette démo.

composer require copadia/php-video-url-parser

Nous allons utiliser la bibliothèque dans un filtre Twig custom.

symfony console make:twig-extension

 The name of the Twig extension class (e.g. AppExtension):
 > YoutubeExtension

 created: src/Twig/YoutubeExtension.php
    
  Success!

Éditons le fichier src/Twig/YoutubeExtension.php pour écrire un filtre Twig qui renverra la miniature d’une vidéo YouTube à partir de son URL.

<?php

namespace App\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
use RicardoFiorani\Matcher\VideoServiceMatcher;

class YoutubeExtension extends AbstractExtension
{
    private $youtubeParser;

    public function __construct()
    {
        $this->youtubeParser = new VideoServiceMatcher();
    }

    public function getFilters(): array
    {
        return [
            // If your filter generates SAFE HTML, you should add a third
            // parameter: ['is_safe' => ['html']]
            // Reference: https://twig.symfony.com/doc/2.x/advanced.html#automatic-escaping
            new TwigFilter('youtube_thumbnail', [$this, 'youtubeThumbnail']),
        ];
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('function_name', [$this, 'doSomething']),
        ];
    }

    public function youtubeThumbnail($value)
    {
        $video = $this->youtubeParser->parse($value);
        return $video->getLargestThumbnail();
    }
}

Profitons de ce nouveau filtre Twig pour améliorer notre mise en page dans le fichier /template/youtube/index.html.twig.

{% extends 'base.html.twig' %}

{% block title %}Best Youtube Video !
{% endblock %}

{% block body %}

    <h2>Toutes les vidéos</h2>
	<div class="row row-cols-1 row-cols-md-2 g-4">
        {% for youtube in youtubes %}
            <div class="col">
                <div class="card shadow p-3 mb-5 bg-white rounded">
                    <img src="{{ youtube.url|youtube_thumbnail }}" class="card-img-top" alt="...">
                    <div class="card-body">
                        <h5 class="card-title">{{ youtube.name }}</h5>
                    </div>
                </div>
            </div>
        {% endfor %}
	</div>

    <div class="mb-5 mt-5" id="addvideo">
        <h2>Ajouter une vidéo</h2>
        {{ form(form) }}
    </div>

	{% endblock %}

Affichons notre page, elle devrait avoir un peu plus de style 😉

Créons la page avec le player Youtube

Éditons notre fichier /src/Controller/YoutubeController.php pour y ajouter une nouvelle route qui affichera une seule vidéo YouTube.

Nous réutiliserons la librairie “copadia/php-video-url-parser” installée plus tôt pour récupérer le code du player YouTube.

    /**
     * @Route("/{id}", name="app_video")
     */
    public function video(Youtube $youtube): Response
    {
        return $this->render('youtube/video.html.twig', [
            'name' => $youtube->getName(),
            'url' => $youtube->getUrl(),
        ]);
    }

Créons le filtre Twig qui récupère-le code du player en éditant notre fichier /src/Twig/ToutubeExtension.php.

    public function youtubePlayer($value)
    {
        $video = $this->youtubeParser->parse($value);
        return $video->getEmbedCode('100%', 500, true, true);
    }

Il ne nous reste plus qu’a créer le fichier twig /templates/youtube/video.html.twig.

{% extends 'base.html.twig' %}

{% block title %}Best Youtube Video !
{% endblock %}

{% block body %}

    <h2>{{ name }}</h2>
    <div>{{ url|youtube_player|raw }}</div>

{% endblock %}

Pour que la boucle soit boucle, créons un lien de notre liste de vidéos vers la page avec le player. Modifions-le fichier /templates/youtube/index.php.

{% extends 'base.html.twig' %}

{% block title %}Best Youtube Video !
{% endblock %}

{% block body %}

    <h2>Toutes les vidéos</h2>
	<div class="row row-cols-1 row-cols-md-2 g-4">
        {% for youtube in youtubes %}
            <div class="col">
                <div class="card shadow p-3 mb-5 bg-white rounded">
                    <a href="{{ path('app_video', {'id': youtube.id }) }}"><img src="{{ youtube.url|youtube_thumbnail }}" class="card-img-top"></a>
                    <div class="card-body">
                        <h5 class="card-title">{{ youtube.name }}</h5>
                    </div>
                </div>
            </div>
        {% endfor %}
	</div>

    <div class="mb-5 mt-5" id="addvideo">
        <h2>Ajouter une vidéo</h2>
        {{ form(form) }}
    </div>

	{% endblock %}

Et vérifions le résultat !

Versionnons notre code !

Il est pus que temps de versionner notre code (et de le pousser sur un dépôt distant, GitLab dans mon cas !).

git init
git add .
git commit -m "initial commit"
git remote add origin git@gitlab.com:yoandev.co/youtube-heroku.git
git push -u origin --all

Mise en production avec Heroku !

Bon maintenant que nous avons une application qui fonctionne, il est temps de la mettre en production sur Heroku !

Pour réaliser la suite des opérations vous devez disposer d’un compte (gratuit) sur Heroku et vous devez également installer la CLI de Heroku sur votre poste.

Nous devons initialiser un nouveau projet Heroku dans votre projet.

heroku create

Vous devez ensuite créer un fichier Procfile qui décrit la configuration de votre serveur chez Heroku. Ici nous allons lui demander d’utiliser un serveur Apache, avec php, et de servir le répertoire public/.

echo 'web: heroku-php-apache2 public/' > Procfile

Ajoutons une base de données Postgres à notre configuration Heroku.

heroku addons:create heroku-postgresql:hobby-dev

Passons la variable d’environnement “APP_ENV” sur “PROD” pour indiquer que notre application s’exécutera en production.

heroku config:set APP_ENV=prod

Ajoutons une étape dans notre fichier composer.json, pour indiquer que lors du déploiement, les migrations devrons être appliquées.

(...),
"scripts": {
        (...),
        "compile": [
            "php bin/console doctrine:migrations:migrate"
        ]
    },
(...)

Installons le pack Apache pour Symfony (nécessaire pour faire fonctionner les ré écriture d’url). Grosso-modo cela va mettre en place un .htaccess dans votre répertoire /public.

composer require symfony/apache-pack

Commitons ces changements dans notre dépôt Git.

git add .
git commit -m "add config heroku"
git push

Mettons en production !!! Et OUI c’est aussi simple que cela !

git push heroku master

Et ouvrons notre application dans un navigateur web. Oui, votre application est en production et vous pouvez partager l’URL !

heroku open

Conclusions et dépôt GitLab

Dans cet article nous avons développé très rapidement une mini application, qui interagie avec une base de données et nous avons pu expérimenter un déploiement avec Heroku. Vous avez pu vous rendre compte de l’immense simplicité que vous offre Heroku et surtout de la rapidité de mise en œuvre !

Les sources du projet sont disponibles sur ce dépôt GitLab.

9 réflexions sur “Mettre en production une application Symfony 5 avec Heroku”

  1. Coucou,
    J’essaye de faire le tuto, mais je rencontre une erreur à la création de la BDD PostreSql. Je pense avoir activé toutes les extensions de php pour postgresql dans le php.ini (extension=pdo_pgsql et extension=pgsql), mais ca ne change rien.

    Docker PostgreSql est up,
    PHP 7.4.2
    Symfony 5.2.1
    Connexion et création de la BDD avec MySQL ca passe normalement (DATABASE_URL=”mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7″)

    Voila l’erreur :

    “`
    $ symfony console doctrine:database:create

    In AbstractPostgreSQLDriver.php line 102:
    An exception occurred in driver: could not find driver

    In Exception.php line 18:
    could not find driver

    In PDOConnection.php line 38:
    could not find driver
    “`

    Vous auriez des pistes svp ?

    1. Réponse trouvée,
      J’ai installé `apt install php-pgsql`, ce qui n’avait pas fonctionné, j’ai spécifié la version de PHP à update : `apt install php7.4-pgsql` et c’est passé.

  2. Bonsoir Mr Yoan
    Je tiens énormement à vous remercier pour vos Tuteriels
    C’est d’une immense compétence et aide dans le développement web
    En essayant de rependre le tuto, je rencontre de probleme lors de l’execution de la commande: symfony console doctrine:database:create
    de la creation de la base de donnée postgresl, ce qui me bloque….
    Pourtant j’arrive à créer le conteneur
    En lisant l’erreur je comprends qu’il ne touve/manque le driver driver postgresql
    Je croyais que le conteneur d’image postgresql allait contenir toutes ses dependances?
    Est obligatoire d’installer postgresql sur son machine local avant ou celui du container suffit pr avoir la BD postgresql ?
    Je n’arrive pas trouver de solution …
    J’ai besoin de votre aide
    Merci beaucoup
    voici la sortie de mon execution avec l’erreur
    PS F:\CodePhp\yoa_mettre-en-production> docker-compose up -d
    Creating network “yoa_mettre-en-production_default” with the default driver
    Creating yoa_mettre-en-production_database_1 … done
    PS F:\CodePhp\yoa_mettre-en-production> symfony serve -d

    [OK] Web server listening
    The Web server is using PHP CGI 7.4.9
    https://127.0.0.1:8001

    Stream the logs via symfony.exe server:log
    PS F:\CodePhp\yoa_youtube_heroku> symfony console doctrine:database:create
    [2021-04-16T10:04:27.427410+00:00] console.CRITICAL: Error thrown while running command “doctrine:database:create”. Message: “An exception occurred in driver: could not find driver” {“exception”:”[object] (Doctrine\\DBAL\\Exception\\DriverException(code: 0): An exception occurred in driver: could not find driver at F:\\CodePhp\\yoa_youtube_heroku\\vendor\\doctrine\\dbal\\lib\\Doctrine\\DBAL\\Driver\\AbstractPostgreSQLDriver.php:102)\n[previous exception] [object] (Doctrine\\DBAL\\Driver\\PDO\\Exception(code: 0): could not find driver at F:\\CodePhp\\yoa_youtube_heroku\\vendor\\doctrine\\dbal\\lib\\Doctrine\\DBAL\\Driver\\PDO\\Exception.php:18)\n[previous exception] [object] (PDOException(code: 0): could not find driver at F:\\CodePhp\\yoa_youtube_heroku\\vendor\\doctrine\\dbal\\lib\\Doctrine\\DBAL\\Driver\\PDOConnection.php:39)”,”command”:”doctrine:database:create”,”message”:”An exception occurred in driver: could not find driver”} []
    [2021-04-16T10:04:27.445517+00:00] console.DEBUG: Command “doctrine:database:create” exited with code “1” {“command”:”doctrine:database:create”,”code”:1} []

    In AbstractPostgreSQLDriver.php line 102:

    An exception occurred in driver: could not find driver

    In Exception.php line 18:

    could not find driver

    In PDOConnection.php line 39:

    could not find driver

    doctrine:database:create [-s|–shard SHARD] [-c|–connection [CONNECTION]] [–if-not-exists]

    exit status 1

    1. Bonjour !
      Lorsque j’ai activé les extensions de php pour postgresql dans le php.ini (pdo_pgsql et pgsql),
      j’ai reussi à créer la base de données postgesql,la table, le filtre, à publier une vidéo et à lister toutes les vidéos …
      Merci

      1. Bonjour,
        j’ai exactement le même soucis.
        J’ai essayé d’activer postgre sur wamp mais je galère.
        sur phpinfo j’ai :
        DATABASE_DRIVER postgres
        DATABASE_USER main
        DATABASE_SERVER postgres://127.0.0.1:52816
        PGDATABASE main
        DATABASE_URL postgres://main:main@127.0.0.1:52816/main?sslmode=disable&charset=utf8

        et dans php.ini :
        [PostgreSQL]
        ; Allow or prevent persistent links.
        ; http://php.net/pgsql.allow-persistent
        pgsql.allow_persistent = On
        et
        extension=pdo_pgsql
        extension=pgsql

        Déjà je ne comprend pas pourquoi phpinfo me renvoi le port 52816 alors que si je regarde dans le fichier
        postgresql.conf j’ai :
        port = 5432

        Bon merci par avance si tu à la moindre idée du problème.

        1. Bon et bien je me répond à moi même.
          Je modifiais directement le fichier php.ini par le logiciel wamp et le fichier ne s’enregistrait pas correctement.
          Modifié directement dans le répertoire d’install de wamp/ php et cela fonctionne.
          Dsl pour le dérangement
          Et merci pour ce tuto.

  3. Malheusement, J’ai de nouveaux problemes, erreurs lors du déploiement que j’arrive pas à solutionner:

    PS F:\CodePhp\yoa_youtube-heroku> git remote
    heroku
    origin
    PS F:\CodePhp\yoa_youtube-heroku> git push heroku master
    Enumerating objects: 96, done.
    Counting objects: 100% (96/96), done.
    Delta compression using up to 4 threads
    Compressing objects: 100% (88/88), done.
    Writing objects: 100% (96/96), 50.38 KiB | 143.00 KiB/s, done.
    Total 96 (delta 11), reused 0 (delta 0), pack-reused 0
    remote: Compressing source files… done.
    remote: Building source:
    remote:
    remote: —–> Building on the Heroku-20 stack
    remote: —–> Determining which buildpack to use for this app
    remote: —–> PHP app detected
    remote: —–> Bootstrapping…
    remote: —–> Installing platform packages…
    remote: – php (8.0.3)
    remote: – apache (2.4.46)
    remote: – nginx (1.18.0)
    remote: – composer (2.0.12)
    remote: —–> Installing dependencies…
    remote: Composer version 2.0.12 2021-04-01 10:14:59
    remote: Installing dependencies from lock file
    remote: Verifying lock file contents can be installed on current platform.
    remote: Package operations: 96 installs, 0 updates, 0 removals
    remote: – Downloading composer/package-versions-deprecated (1.11.99.1)
    remote: – Downloading symfony/flex (v1.12.2)
    remote: – Downloading copadia/php-video-url-parser (v1.0.3)
    remote: – Downloading doctrine/deprecations (v0.5.3)
    remote: – Downloading symfony/polyfill-php80 (v1.22.1)
    remote: – Downloading symfony/deprecation-contracts (v2.2.0)
    remote: – Downloading symfony/routing (v5.2.6)
    remote: – Downloading symfony/polyfill-mbstring (v1.22.1)
    remote: – Downloading symfony/polyfill-php73 (v1.22.1)
    remote: – Downloading symfony/http-foundation (v5.2.4)
    remote: – Downloading symfony/http-client-contracts (v2.3.1)
    remote: – Downloading psr/event-dispatcher (1.0.0)
    remote: – Downloading symfony/event-dispatcher-contracts (v2.2.0)
    remote: – Downloading symfony/event-dispatcher (v5.2.4)
    remote: – Downloading symfony/var-dumper (v5.2.6)
    remote: – Downloading psr/log (1.1.3)
    remote: – Downloading symfony/error-handler (v5.2.6)
    remote: – Downloading symfony/http-kernel (v5.2.6)
    remote: – Downloading symfony/finder (v5.2.4)
    remote: – Downloading symfony/filesystem (v5.2.6)
    remote: – Downloading psr/container (1.1.1)
    remote: – Downloading symfony/service-contracts (v2.2.0)
    remote: – Downloading symfony/dependency-injection (v5.2.6)
    remote: – Downloading symfony/config (v5.2.4)
    remote: – Downloading symfony/var-exporter (v5.2.4)
    remote: – Downloading psr/cache (1.0.1)
    remote: – Downloading symfony/cache-contracts (v2.2.0)
    remote: – Downloading symfony/cache (v5.2.6)
    remote: – Downloading symfony/framework-bundle (v5.2.6)
    remote: – Downloading symfony/stopwatch (v5.2.4)
    remote: – Downloading symfony/polyfill-intl-normalizer (v1.22.1)
    remote: – Downloading symfony/polyfill-intl-grapheme (v1.22.1)
    remote: – Downloading symfony/string (v5.2.6)
    remote: – Downloading symfony/console (v5.2.6)
    remote: – Downloading laminas/laminas-zendframework-bridge (1.2.0)
    remote: – Downloading laminas/laminas-eventmanager (3.3.1)
    remote: – Downloading laminas/laminas-code (4.2.0)
    remote: – Downloading friendsofphp/proxy-manager-lts (v1.0.3)
    remote: – Downloading doctrine/event-manager (1.1.1)
    remote: – Downloading doctrine/cache (1.10.2)
    remote: – Downloading doctrine/dbal (2.13.0)
    remote: – Downloading doctrine/migrations (3.1.1)
    remote: – Downloading doctrine/collections (1.6.7)
    remote: – Downloading doctrine/lexer (1.2.1)
    remote: – Downloading doctrine/annotations (1.12.1)
    remote: – Downloading doctrine/persistence (2.1.0)
    remote: – Downloading symfony/doctrine-bridge (v5.2.6)
    remote: – Downloading doctrine/sql-formatter (1.1.1)
    remote: – Downloading doctrine/doctrine-bundle (2.3.1)
    remote: – Downloading doctrine/doctrine-migrations-bundle (3.1.1)
    remote: – Downloading doctrine/instantiator (1.4.0)
    remote: – Downloading doctrine/inflector (2.0.3)
    remote: – Downloading doctrine/common (3.1.2)
    remote: – Downloading doctrine/orm (2.8.4)
    remote: – Downloading webmozart/assert (1.10.0)
    remote: – Downloading phpdocumentor/reflection-common (2.2.0)
    remote: – Downloading phpdocumentor/type-resolver (1.4.0)
    remote: – Downloading phpdocumentor/reflection-docblock (5.2.2)
    remote: – Downloading sensio/framework-extra-bundle (v5.6.1)
    remote: – Downloading symfony/apache-pack (v1.0.1)
    remote: – Downloading symfony/asset (v5.2.4)
    remote: – Downloading symfony/dotenv (v5.2.4)
    remote: – Downloading symfony/expression-language (v5.2.4)
    remote: – Downloading symfony/property-info (v5.2.4)
    remote: – Downloading symfony/property-access (v5.2.4)
    remote: – Downloading symfony/options-resolver (v5.2.4)
    remote: – Downloading symfony/polyfill-intl-icu (v1.22.1)
    remote: – Downloading symfony/intl (v5.2.4)
    remote: – Downloading symfony/form (v5.2.6)
    remote: – Downloading symfony/http-client (v5.2.6)
    remote: – Downloading symfony/polyfill-intl-idn (v1.22.1)
    remote: – Downloading symfony/mime (v5.2.6)
    remote: – Downloading egulias/email-validator (3.1.1)
    remote: – Downloading symfony/mailer (v5.2.6)
    remote: – Downloading monolog/monolog (2.2.0)
    remote: – Downloading symfony/monolog-bridge (v5.2.5)
    remote: – Downloading symfony/monolog-bundle (v3.7.0)
    remote: – Downloading symfony/notifier (v5.2.4)
    remote: – Downloading symfony/process (v5.2.4)
    remote: – Downloading symfony/proxy-manager-bridge (v5.2.4)
    remote: – Downloading symfony/security-core (v5.2.6)
    remote: – Downloading symfony/security-http (v5.2.6)
    remote: – Downloading symfony/security-guard (v5.2.4)
    remote: – Downloading symfony/security-csrf (v5.2.4)
    remote: – Downloading symfony/security-bundle (v5.2.6)
    remote: – Downloading symfony/serializer (v5.2.4)
    remote: – Downloading symfony/translation-contracts (v2.3.0)
    remote: – Downloading symfony/translation (v5.2.6)
    remote: – Downloading twig/twig (v3.3.0)
    remote: – Downloading symfony/twig-bridge (v5.2.6)
    remote: – Downloading symfony/validator (v5.2.6)
    remote: – Downloading psr/link (1.0.0)
    remote: – Downloading symfony/web-link (v5.2.5)
    remote: – Downloading symfony/yaml (v5.2.5)
    remote: – Downloading symfony/twig-bundle (v5.2.4)
    remote: – Downloading twig/extra-bundle (v3.3.0)
    remote: – Installing composer/package-versions-deprecated (1.11.99.1): Extracting archive
    remote: – Installing symfony/flex (v1.12.2): Extracting archive
    remote: – Installing copadia/php-video-url-parser (v1.0.3): Extracting archive
    remote: – Installing doctrine/deprecations (v0.5.3): Extracting archive
    remote: – Installing symfony/polyfill-php80 (v1.22.1): Extracting archive
    remote: – Installing symfony/deprecation-contracts (v2.2.0): Extracting archive
    remote: – Installing symfony/routing (v5.2.6): Extracting archive
    remote: – Installing symfony/polyfill-mbstring (v1.22.1): Extracting archive
    remote: – Installing symfony/polyfill-php73 (v1.22.1): Extracting archive
    remote: – Installing symfony/http-foundation (v5.2.4): Extracting archive
    remote: – Installing symfony/http-client-contracts (v2.3.1): Extracting archive
    remote: – Installing psr/event-dispatcher (1.0.0): Extracting archive
    remote: – Installing symfony/event-dispatcher-contracts (v2.2.0): Extracting archive
    remote: – Installing symfony/event-dispatcher (v5.2.4): Extracting archive
    remote: – Installing symfony/var-dumper (v5.2.6): Extracting archive
    remote: – Installing psr/log (1.1.3): Extracting archive
    remote: – Installing symfony/error-handler (v5.2.6): Extracting archive
    remote: – Installing symfony/http-kernel (v5.2.6): Extracting archive
    remote: – Installing symfony/finder (v5.2.4): Extracting archive
    remote: – Installing symfony/filesystem (v5.2.6): Extracting archive
    remote: – Installing psr/container (1.1.1): Extracting archive
    remote: – Installing symfony/service-contracts (v2.2.0): Extracting archive
    remote: – Installing symfony/dependency-injection (v5.2.6): Extracting archive
    remote: – Installing symfony/config (v5.2.4): Extracting archive
    remote: – Installing symfony/var-exporter (v5.2.4): Extracting archive
    remote: – Installing psr/cache (1.0.1): Extracting archive
    remote: – Installing symfony/cache-contracts (v2.2.0): Extracting archive
    remote: – Installing symfony/cache (v5.2.6): Extracting archive
    remote: – Installing symfony/framework-bundle (v5.2.6): Extracting archive
    remote: – Installing symfony/stopwatch (v5.2.4): Extracting archive
    remote: – Installing symfony/polyfill-intl-normalizer (v1.22.1): Extracting archive
    remote: – Installing symfony/polyfill-intl-grapheme (v1.22.1): Extracting archive
    remote: – Installing symfony/string (v5.2.6): Extracting archive
    remote: – Installing symfony/console (v5.2.6): Extracting archive
    remote: – Installing laminas/laminas-zendframework-bridge (1.2.0): Extracting archive
    remote: – Installing laminas/laminas-eventmanager (3.3.1): Extracting archive
    remote: – Installing laminas/laminas-code (4.2.0): Extracting archive
    remote: – Installing friendsofphp/proxy-manager-lts (v1.0.3): Extracting archive
    remote: – Installing doctrine/event-manager (1.1.1): Extracting archive
    remote: – Installing doctrine/cache (1.10.2): Extracting archive
    remote: – Installing doctrine/dbal (2.13.0): Extracting archive
    remote: – Installing doctrine/migrations (3.1.1): Extracting archive
    remote: – Installing doctrine/collections (1.6.7): Extracting archive
    remote: – Installing doctrine/lexer (1.2.1): Extracting archive
    remote: – Installing doctrine/annotations (1.12.1): Extracting archive
    remote: – Installing doctrine/persistence (2.1.0): Extracting archive
    remote: – Installing symfony/doctrine-bridge (v5.2.6): Extracting archive
    remote: – Installing doctrine/sql-formatter (1.1.1): Extracting archive
    remote: – Installing doctrine/doctrine-bundle (2.3.1): Extracting archive
    remote: – Installing doctrine/doctrine-migrations-bundle (3.1.1): Extracting archive
    remote: – Installing doctrine/instantiator (1.4.0): Extracting archive
    remote: – Installing doctrine/inflector (2.0.3): Extracting archive
    remote: – Installing doctrine/common (3.1.2): Extracting archive
    remote: – Installing doctrine/orm (2.8.4): Extracting archive
    remote: – Installing webmozart/assert (1.10.0): Extracting archive
    remote: – Installing phpdocumentor/reflection-common (2.2.0): Extracting archive
    remote: – Installing phpdocumentor/type-resolver (1.4.0): Extracting archive
    remote: – Installing phpdocumentor/reflection-docblock (5.2.2): Extracting archive
    remote: – Installing sensio/framework-extra-bundle (v5.6.1): Extracting archive
    remote: – Installing symfony/apache-pack (v1.0.1): Extracting archive
    remote: – Installing symfony/asset (v5.2.4): Extracting archive
    remote: – Installing symfony/dotenv (v5.2.4): Extracting archive
    remote: – Installing symfony/expression-language (v5.2.4): Extracting archive
    remote: – Installing symfony/property-info (v5.2.4): Extracting archive
    remote: – Installing symfony/property-access (v5.2.4): Extracting archive
    remote: – Installing symfony/options-resolver (v5.2.4): Extracting archive
    remote: – Installing symfony/polyfill-intl-icu (v1.22.1): Extracting archive
    remote: – Installing symfony/intl (v5.2.4): Extracting archive
    remote: – Installing symfony/form (v5.2.6): Extracting archive
    remote: – Installing symfony/http-client (v5.2.6): Extracting archive
    remote: – Installing symfony/polyfill-intl-idn (v1.22.1): Extracting archive
    remote: – Installing symfony/mime (v5.2.6): Extracting archive
    remote: – Installing egulias/email-validator (3.1.1): Extracting archive
    remote: – Installing symfony/mailer (v5.2.6): Extracting archive
    remote: – Installing monolog/monolog (2.2.0): Extracting archive
    remote: – Installing symfony/monolog-bridge (v5.2.5): Extracting archive
    remote: – Installing symfony/monolog-bundle (v3.7.0): Extracting archive
    remote: – Installing symfony/notifier (v5.2.4): Extracting archive
    remote: – Installing symfony/process (v5.2.4): Extracting archive
    remote: – Installing symfony/proxy-manager-bridge (v5.2.4): Extracting archive
    remote: – Installing symfony/security-core (v5.2.6): Extracting archive
    remote: – Installing symfony/security-http (v5.2.6): Extracting archive
    remote: – Installing symfony/security-guard (v5.2.4): Extracting archive
    remote: – Installing symfony/security-csrf (v5.2.4): Extracting archive
    remote: – Installing symfony/security-bundle (v5.2.6): Extracting archive
    remote: – Installing symfony/serializer (v5.2.4): Extracting archive
    remote: – Installing symfony/translation-contracts (v2.3.0): Extracting archive
    remote: – Installing symfony/translation (v5.2.6): Extracting archive
    remote: – Installing twig/twig (v3.3.0): Extracting archive
    remote: – Installing symfony/twig-bridge (v5.2.6): Extracting archive
    remote: – Installing symfony/validator (v5.2.6): Extracting archive
    remote: – Installing psr/link (1.0.0): Extracting archive
    remote: – Installing symfony/web-link (v5.2.5): Extracting archive
    remote: – Installing symfony/yaml (v5.2.5): Extracting archive
    remote: – Installing symfony/twig-bundle (v5.2.4): Extracting archive
    remote: – Installing twig/extra-bundle (v3.3.0): Extracting archive
    remote: Generating optimized autoload files
    remote: composer/package-versions-deprecated: Generating version class…
    remote: composer/package-versions-deprecated: …done generating version class
    remote: 78 packages you are using are looking for funding.
    remote: Use the `composer fund` command to find out more!
    remote:
    remote: Run composer recipes at any time to see the status of your Symfony recipes.
    remote:
    remote: Executing script cache:clear [OK]
    remote: Executing script assets:install public [OK]
    remote:
    remote: —–> Running ‘composer compile’…
    remote: > php bin/console doctrine:migrations:migrate
    remote:
    remote: WARNING! You are about to execute a migration in database “d58i4nt2458s8m” that
    could result in schema changes and data loss. Are you sure you wish to continue? (yes/no) [yes]
    remote: >
    remote:
    remote: [OK] Already at the latest version (“DoctrineMigrations\Version20210418115744”)
    remote:
    remote: —–> Preparing runtime environment…
    remote: —–> Checking for additional extensions to install…
    remote: —–> Discovering process types
    remote:
    remote: ! Push failed: cannot parse Procfile.
    remote: ! Please try pushing again.
    remote: ! If the problem persists, see https://help.heroku.com/ and provide Request ID 1a264512-d98a-ccfa-af9e-63fc974b4429.
    remote:
    remote:
    remote: !
    remote: ! ## Warning – The same version of this code has already been built: dec9c31776465b681fba5c1b1bd3e34088329807
    remote: !
    remote: ! We have detected that you have triggered a build from source code with version dec9c31776465b681fba5c1b1bd3e34088329807
    remote: ! at least twice. One common cause of this behavior is attempting to deploy code from a different branch.
    remote: !
    remote: ! If you are developing on a branch and deploying via git you must run:
    remote: !
    remote: ! git push heroku :main
    remote: !
    remote: ! This article goes into details on the behavior:
    remote: ! https://devcenter.heroku.com/articles/duplicate-build-version
    remote:
    remote: Verifying deploy…
    remote:
    remote: ! Push rejected to floating-plateau-23436.
    remote:
    To https://git.heroku.com/floating-plateau-23436.git
    ! [remote rejected] master -> master (pre-receive hook declined)
    error: failed to push some refs to ‘https://git.heroku.com/floating-plateau-23436.git’

    Je remarque deux problemes:
    1-Au niveau de Procfile qui n’arrive pas à etre pushé—>Push failed: cannot parse Procfile
    2-Le non accès au lien ‘https://git.heroku.com/floating-plateau-23436.git’ meme via un crique pourtant
    j’arrive à accéder à mon projet hiroku ‘floating-plateau-23436’ est créer et j’y accède
    le probleme semble se situé au niveau du depot git heroku ‘https://git.heroku.com/floating-plateau-23436.git’
    Je n’arrive pas trouver de solution via Google, youtube et forums.
    Certainement ces problemes sont à l’origine de l’échec du push
    —>error: failed to push some refs to ‘https://git.heroku.com/floating-plateau-23436.git’

    J’ai besions de vos aides
    Merci

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.