Published on

Doctrine教程1---项目设置

原创文章,转载时需取得本人同意并注明来源
Authors
  • Doctrine教程1---项目设置
    Name
    langziyang
    Twitter

Doctrine教程1---项目设置

模板使用tailwindcss

1、entity

App\Entity\Category.php

<?php

namespace App\Entity;

use App\Repository\CategoryRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: CategoryRepository::class)]
class Category
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $name = null;

    #[ORM\Column(length: 20)]
    private ?string $iconKey = null;

    #[ORM\OneToMany(mappedBy: 'category', targetEntity: FortuneCookie::class)]
    private Collection $fortuneCookies;

    public function __construct()
    {
        $this->fortuneCookies = new ArrayCollection();
    }

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

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getIconKey(): ?string
    {
        return $this->iconKey;
    }

    public function setIconKey(string $iconKey): self
    {
        $this->iconKey = $iconKey;

        return $this;
    }

    /**
     * @return Collection<int, FortuneCookie>
     */
    public function getFortuneCookies(): Collection
    {
        return $this->fortuneCookies;
    }

    public function addFortuneCookie(FortuneCookie $fortuneCookie): self
    {
        if (!$this->fortuneCookies->contains($fortuneCookie)) {
            $this->fortuneCookies->add($fortuneCookie);
            $fortuneCookie->setCategory($this);
        }

        return $this;
    }

    public function removeFortuneCookie(FortuneCookie $fortuneCookie): self
    {
        if ($this->fortuneCookies->removeElement($fortuneCookie)) {
            // set the owning side to null (unless already changed)
            if ($fortuneCookie->getCategory() === $this) {
                $fortuneCookie->setCategory(null);
            }
        }

        return $this;
    }
}

App\Entity\FortuneCookie.php

<?php

namespace App\Entity;

use App\Repository\FortuneCookieRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: FortuneCookieRepository::class)]
class FortuneCookie
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $fortune = null;

    #[ORM\Column]
    private ?int $numberPrinted = null;

    #[ORM\Column]
    private bool $discontinued = false;

    #[ORM\Column]
    private \DateTimeImmutable $createdAt;

    #[ORM\ManyToOne(inversedBy: 'fortuneCookies')]
    #[ORM\JoinColumn(nullable: false)]
    private ?Category $category = null;

    /**
     * @param \DateTimeImmutable|null $createdAt
     */
    public function __construct()
    {
        $this->createdAt = new \DateTimeImmutable();
    }

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

    public function getFortune(): ?string
    {
        return $this->fortune;
    }

    public function setFortune(string $fortune): self
    {
        $this->fortune = $fortune;

        return $this;
    }

    public function getNumberPrinted(): ?int
    {
        return $this->numberPrinted;
    }

    public function setNumberPrinted(int $numberPrinted): self
    {
        $this->numberPrinted = $numberPrinted;

        return $this;
    }

    public function isDiscontinued(): bool
    {
        return $this->discontinued;
    }

    public function setDiscontinued(bool $discontinued): self
    {
        $this->discontinued = $discontinued;

        return $this;
    }

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

    public function setCreatedAt(\DateTimeImmutable $createdAt): self
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    public function getCategory(): ?Category
    {
        return $this->category;
    }

    public function setCategory(Category $category): self
    {
        $this->category = $category;

        return $this;
    }
}

2、控制器

App\Controller\FortuneController.php

<?php

namespace App\Controller;

use App\Entity\Category;
use App\Repository\CategoryRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class FortuneController extends AbstractController
{
    #[Route('/', name: 'app_homepage')]
    public function index(CategoryRepository $categoryRepository): Response
    {
        $categories = $categoryRepository->findAll();

        return $this->render('fortune/homepage.html.twig',[
            'categories' => $categories
        ]);
    }

    #[Route('/category/{id}', name: 'app_category_show')]
    public function showCategory(Category $category): Response
    {
        return $this->render('fortune/showCategory.html.twig',[
            'category' => $category
        ]);
    }
}

3、模板 templates\base.html.twig

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>{% block title %}Fortune Queries{% endblock %}</title>
    {# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
    {% block stylesheets %}
    {{ encore_entry_link_tags('app') }}
    {% endblock %}

    {% block javascripts %}
    {{ encore_entry_script_tags('app') }}
    {% endblock %}
</head>
<body class="flex flex-col min-h-screen">
<nav class="border-gray-200 px-4 py-5 bg-gray-900">
    <div class="container flex flex-wrap items-center justify-between mx-auto">
        <a href="{{ path('app_homepage') }}" class="flex items-center">
            <span class="self-center text-xl font-semibold whitespace-nowrap text-white">Fortune Queries</span>
        </a>
        <div class="flex">
            <div class="relative">
                <form action="{{ path('app_homepage') }}">
                    <div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
                        <button>搜索</button>
                    </div>
                    <input type="text" id="search-navbar" name="q" value="{{ app.request.query.get('q') }}" placeholder="Search..." class="block w-full p-2 pl-10 text-sm border rounded-lg bg-gray-700 border-gray-600 placeholder-gray-400 text-white focus:ring-blue-500 focus:border-blue-500">
                </form>
            </div>
        </div>
    </div>
</nav>
{% block body %}{% endblock %}
<footer class="mt-auto bg-slate-100">
    <div class="p-5 flex justify-between">
        <p>Brought to you with <i class="fas fa-heart text-red-600"></i> from <a class="underline hover:text-blue-600" href="https://symfonycasts.com/">SymfonyCasts</a></p>
        <div class="text-lg">
            <a class="text-gray-700 hover:text-gray-900" href="https://twitter.com/SymfonyCasts"><i class="fa-brands fa-twitter"></i></a>
            <a class="text-gray-700 hover:text-gray-900" href="https://www.facebook.com/SymfonyCasts"><i class="fa-brands fa-facebook"></i></a>
            <a class="text-gray-700 hover:text-gray-900" href="https://github.com/SymfonyCasts"><i class="fa-brands fa-github"></i></a>
        </div>
    </div>
</footer>
</body>
</html>

templates\fortune\homepage.html.twig

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

{% block body %}

    <h1 class="text-center my-8 text-2xl text-slate-800 font-bold">Query for your Fortune</h1>
    <p class="text-center">Review categories for available cookie fortunes</p>
    <div class="xl:container xl:mx-auto grid grid-cols-2 gap-6 px-10 mt-8 mb-10">
        {% for category in categories %}
            <a class="bg-orange-400 hover:bg-orange-500 text-white text-center rounded-full p-4" href="{{ path('app_category_show', {'id':  category.id}) }}">
                <span class="fa {{ category.iconKey }}"></span> <span class="font-bold text-lg">{{ category.name }}</span>  ({{ category.fortuneCookies|length }})
            </a>
        {% else %}
            <h3>Hmm... there don't seem to be any fortunes</h3>
        {% endfor %}
    </div>
{% endblock %}

templates\fortune\showCategory.html.twig

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

{% block body %}


    <h1 class="text-3xl p-5 text-center my-4 font-semibold"><span class="fa {{ category.iconKey }}"></span> {{ category.name }} Fortunes</h1>
    <div class="flex justify-center mb-16 px-4">
        <div>
            <table class="table-auto border mb-6">
                <thead class="bg-slate-500 text-white">
                <tr>
                    <th class="border p-4">
                        Fortunes
                    </th>
                    <th class="border p-4">
                        Print History
                    </th>
                </tr>
                </thead>
                <tbody>
                {% for fortuneCookie in category.fortuneCookies %}
                    <tr class="hover:bg-slate-200">
                        <td class="border p-4">
                            {{ fortuneCookie.fortune }}
                        </td>
                        <td class="border p-4">
                            {{ fortuneCookie.numberPrinted }} printed since {{ fortuneCookie.createdAt|date('M jS Y') }}
                        </td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
            <a class="text-slate-700 hover:text-slate-900 font-semibold" href="{{ path('app_homepage') }}"><i class="fa fa-angle-double-left"></i> Back to Fortune Categories</a>
        </div>
    </div>
{% endblock %}