- Published on
Doctrine教程1---项目设置
原创文章,转载时需取得本人同意并注明来源
- Authors
-
-
- Name
- langziyang
-
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 %}