Skip to content

Instantly share code, notes, and snippets.

@tattali
Last active April 30, 2019 13:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tattali/95c0e05f3f941a41e33e39fce0e43504 to your computer and use it in GitHub Desktop.
Save tattali/95c0e05f3f941a41e33e39fce0e43504 to your computer and use it in GitHub Desktop.

Symfony 4 CRUD best practices

Step by step

Two shots CRUD packages installation

composer require --dev sec-checker profiler server
composer require annotations twig asset translator form doctrine validator

# Optionnal
composer require --dev doctrine/doctrine-fixtures-bundle

Launch the project

Start server on http://localhost:8000

php bin/console server:start

A bit of configuration

In .env file, configure the database

- DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
+ DATABASE_URL=mysql://root:root@127.0.0.1:3306/sf4

Standards

Respect PSR and Symfony Coding Standards

Start coding

Create an Article entity in src/Entity/Article.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 */
class Article
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=30)
     */
    private $title;

    /**
     * @ORM\Column(type="string", length=1500)
     */
    private $content;

    /**
     * @ORM\Column(type="datetime")
     */
    private $createdAt;


    public function __construct()
    {
        $this->createdAt = new \DateTime();
    }

    public function getId()
    {
        return $this->id;
    }

    public function getTitle()
    {
        return $this->title;
    }

    public function setTitle($title)
    {
        $this->title = $title;
    }

    public function getContent()
    {
        return $this->content;
    }

    public function setContent($content)
    {
        $this->content = $content;
    }

    public function getCreatedAt()
    {
        return $this->createdAt;
    }
}

Create the ArticleController in src/Controller/ArticleController.php and add the index function

<?php

namespace App\Controller;

use App\Entity\Article;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;

/**
 * @Route("/article", name="article_")
 */
class ArticleController extends Controller
{
    /**
     * @Route("s/", name="index")
     */
    public function index()
    {
        $em = $this->getDoctrine()->getManager();
        $articles = $em->getRepository(Article::class)->findAll();

        return $this->render('article/index.html.twig', [
            'articles' => $articles,
        ]);
    }
}
<?php

namespace App\DataFixtures;

use App\Entity\Article;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;

class ArticleFixtures extends Fixture
{
    public function load(ObjectManager $manager)
    {
        $objects = array(
            'article_1' => array(
                'title' => "Se diligendi unam ferri quibus",
                'content' => "Vide, quantum, inquam, fallare, Torquate. oratio me istius philosophi non offendit; nam et complectitur verbis, quod vult, et dicit plane, quod intellegam; et tamen ego a philosopho, si afferat eloquentiam, non asperner, si non habeat, non admodum flagitem. re mihi non aeque satisfacit, et quidem locis pluribus. sed quot homines, tot sententiae; falli igitur possumus.\n\nPost haec Gallus Hierapolim profecturus ut expeditioni specie tenus adesset, Antiochensi plebi suppliciter obsecranti ut inediae dispelleret metum, quae per multas difficilisque causas adfore iam sperabatur, non ut mos est principibus, quorum diffusa potestas localibus subinde medetur aerumnis, disponi quicquam statuit vel ex provinciis alimenta transferri conterminis, sed consularem Syriae Theophilum prope adstantem ultima metuenti multitudini dedit id adsidue replicando quod invito rectore nullus egere poterit victu.\n\nUtque proeliorum periti rectores primo catervas densas opponunt et fortes, deinde leves armaturas, post iaculatores ultimasque subsidiales acies, si fors adegerit, iuvaturas, ita praepositis urbanae familiae suspensae digerentibus sollicite, quos insignes faciunt virgae dexteris aptatae velut tessera data castrensi iuxta vehiculi frontem omne textrinum incedit: huic atratum coquinae iungitur ministerium, dein totum promiscue servitium cum otiosis plebeiis de vicinitate coniunctis: postrema multitudo spadonum a senibus in pueros desinens, obluridi distortaque lineamentorum conpage deformes, ut quaqua incesserit quisquam cernens mutilorum hominum agmina detestetur memoriam Samiramidis reginae illius veteris, quae teneros mares castravit omnium prima velut vim iniectans naturae, eandemque ab instituto cursu retorquens, quae inter ipsa oriundi crepundia per primigenios seminis fontes tacita quodam modo lege vias propagandae posteritatis ostendit.",
            ),
            'article_2' => array(
                'title' => "Se diligendi unam ferri quibus",
                'content' => "Vide, quantum, inquam, fallare, Torquate. oratio me istius philosophi non offendit; nam et complectitur verbis, quod vult, et dicit plane, quod intellegam; et tamen ego a philosopho, si afferat eloquentiam, non asperner, si non habeat, non admodum flagitem. re mihi non aeque satisfacit, et quidem locis pluribus. sed quot homines, tot sententiae; falli igitur possumus.\n\nPost haec Gallus Hierapolim profecturus ut expeditioni specie tenus adesset, Antiochensi plebi suppliciter obsecranti ut inediae dispelleret metum, quae per multas difficilisque causas adfore iam sperabatur, non ut mos est principibus, quorum diffusa potestas localibus subinde medetur aerumnis, disponi quicquam statuit vel ex provinciis alimenta transferri conterminis, sed consularem Syriae Theophilum prope adstantem ultima metuenti multitudini dedit id adsidue replicando quod invito rectore nullus egere poterit victu.\n\nUtque proeliorum periti rectores primo catervas densas opponunt et fortes, deinde leves armaturas, post iaculatores ultimasque subsidiales acies, si fors adegerit, iuvaturas, ita praepositis urbanae familiae suspensae digerentibus sollicite, quos insignes faciunt virgae dexteris aptatae velut tessera data castrensi iuxta vehiculi frontem omne textrinum incedit: huic atratum coquinae iungitur ministerium, dein totum promiscue servitium cum otiosis plebeiis de vicinitate coniunctis: postrema multitudo spadonum a senibus in pueros desinens, obluridi distortaque lineamentorum conpage deformes, ut quaqua incesserit quisquam cernens mutilorum hominum agmina detestetur memoriam Samiramidis reginae illius veteris, quae teneros mares castravit omnium prima velut vim iniectans naturae, eandemque ab instituto cursu retorquens, quae inter ipsa oriundi crepundia per primigenios seminis fontes tacita quodam modo lege vias propagandae posteritatis ostendit.",
            ),
        );

        foreach ($objects as $key => $object) {
            $article = new Article();
            $article->setTitle($object['title']);
            $article->setContent($object['content']);

            $manager->persist($article);

            $this->addReference($key, $article);
        }

        $manager->flush();
    }
}
{% extends 'base.html.twig' %}

{% trans_default_domain 'app' %}

{% block title %}{{ 'title.article.index'|trans }} - {{ parent() }}{% endblock %}

{% block body %}
    <table id="articles" class="table">
        <thead>
            <tr>
                <th>{{ 'article.author'|trans }}</th>
                <th>{{ 'article.title'|trans }}</th>
                <th>{{ 'article.content'|trans }}</th>
                <th>{{ 'article.createdAt'|trans }}</th>
                <th>{{ 'article.updatedAt'|trans }}</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            {% for article in articles %}
                <tr>
                    <td>{{ article.author.username }}</td>
                    <td>{{ article.title }}</td>
                    <td>{{ article.content[:30] }}&#8230;</td>
                    <td>{{ article.createdAt|date('d/m/Y H:i') }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
{% endblock %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment