Ein Symfony 5 Cheatsheet
Ein unvollständiges Symfony 5 Codeschnipsel-Sammelsurium
21. Jul. 2020
Hier gibt's einige Codeschnipsel, die ich regelmäßig in irgendeiner Art und Weise brauche wenn ich mich mit Symfony beschäftige. Da ich super-vergesslich bin, hilft mir dieser Eintrag hoffentlich nicht mehr alle möglichen Projekte und Dateien durchzusuchen, wenn ich was brauche :)
Dieses Cheatsheet basiert auf Symfony 5
Controller
Routen
Benamte Route die ein Twig-Template zurück gibt:
/**
* @Route("/project", name="index")
*/
public function index()
{
return $this->render('project/index.html.twig', [
'controller_name' => 'ProjectController',
]);
}
Eine API-Route die JSON zurück gibt. Die Route ist nur gültig für POST-Requests:
/**
* @Route("/project/toggle", name="project_toggle", methods={"POST"})
*/
public function index()
{
return $this->json(['value' => rand(0, 10)]);
// or:
// return new JsonResponse(['value' => rand(0, 10)]);
}
Route mit Requirements an Parameter
/**
* @Route("/project/{id}", requirements={"id"="\d+"}, name="project_show")
*/
public function show($id)
{
return new Response("Test $id");
}
Auch möglich: Requirements direkt nach Parameter innerhalb von < > notieren:
/**
* @Route("/project/{id<\d+>}", name="project_show")
*/
Parameter-Konverter
Der Parameter-Konverter macht automatisch Entitäts-Objekte aus Routen-Parametern.
In diesem Beispiel wird automatisch ein BlogPost Objekt erzeugt sofern der
Parameter slug
einem Post zugeordnet werden kann:
/**
* @Route("/blog/{slug}", name="blog_show")
*/
public function show(BlogPost $post)
{
// $post is the object whose slug matches the routing parameter
// ...
}
Es genügt einen Type Hint beim Parameter anzugeben. Gibt es keinen Post, wird automatisch eine 404-Seite erzeugt.
Hier ein Bsp. wenn man mehrere Parameter hat, die konvertiert werden sollen. Einer muss speziell ausgezeichnet werden:
/**
* @Route("/blog/{id}/comments/{comment_id}")
* @Entity("comment", expr="repository.find(comment_id)")
*/
public function show(Post $post, Comment $comment)
{
// ...
}
Mehr Infos zum Parameterkonverter gibt es hier.
Redirects
// ...
public function index()
{
// redirects to the "homepage" route
return $this->redirectToRoute('homepage');
// redirectToRoute is a shortcut for:
// return new RedirectResponse($this->generateUrl('homepage'));
// does a permanent - 301 redirect
return $this->redirectToRoute('homepage', [], 301);
// redirect to a route with parameters
return $this->redirectToRoute('app_lucky_number', ['max' => 10]);
// redirects to a route and maintains the original query string parameters
return $this->redirectToRoute('blog_show', $request->query->all());
// redirects externally
return $this->redirect('http://symfony.com/doc');
}
Flash messages
Offizielle Doku zu Flash-Messages
Flash-Messages dienen zum einmaligen Anzeigen von Meldungen.
Message erstellen
use Symfony\Component\HttpFoundation\Request;
public function update(Request $request)
{
$this->addFlash('notice', 'Your changes were saved!');
// $this->addFlash() is equivalent to $request->getSession()->getFlashBag()->add()
}
Message anzeigen
{# read and display just one flash message type #}
{% for message in app.flashes('notice') %}
<div class="flash-notice">
{{ message }}
</div>
{% endfor %}
{# read and display several types of flash messages #}
{% for label, messages in app.flashes(['success', 'warning']) %}
{% for message in messages %}
<div class="flash-{{ label }}">
{{ message }}
</div>
{% endfor %}
{% endfor %}
{# read and display all flash messages #}
{% for label, messages in app.flashes %}
{% for message in messages %}
<div class="flash-{{ label }}">
{{ message }}
</div>
{% endfor %}
{% endfor %}
Assets
Im Ordner public
gespeichertes Dateien referenzieren
Folgender Schnipsel referenziert <symfony_root>/public/css/app.css
.
<link rel="stylesheet" type="text/css" href="{{ asset('css/app.css') }}">
Mit webpack-encore erzeugte Dateien referenzieren
Offizielle webpack-encore Doku
Die webpack.config.js
sollte Zeilen wie diese enthalten:
.addEntry('app', './assets/js/app.js')
.addEntry('plot', './assets/js/plot.js')
.addEntry('scene', './assets/js/scene.js')
In Twig können die Resourcen mittels dem folgenden Code inkludiert werden:
{{ encore_entry_script_tags('app') }} {# Creates script tags #}
{{ encore_entry_link_tags('app') }} {# Creates CSS (link) tags #}
URLs
<a href="{{ path('index') }}">Index</a>
<a href="{{ path('project_show', {id: 2}) }}">Show project</a>
Twig
Blöcke erweitern aus Child-Template:
{% block javascripts %}
{{ parent() }}
<script>
...
</sctipt>
{% endblock %}
Datenbank und Doctrine
Objekte holen
$repository = $this->getDoctrine()->getRepository(Product::class);
// look for a single Product by its primary key (usually "id")
$product = $repository->find($id);
// look for a single Product by name
$product = $repository->findOneBy(['name' => 'Keyboard']);
// or find by name and price
$product = $repository->findOneBy([
'name' => 'Keyboard',
'price' => 1999,
]);
// look for multiple Product objects matching the name, ordered by price
$products = $repository->findBy(
['name' => 'Keyboard'],
['price' => 'ASC']
);
// look for *all* Product objects
$products = $repository->findAll();
Objekte speichern
/**
* @Route("/project/store", name="project_store", methods={"POST"})
*/
public function store()
{
$project = new Project();
$project->setName('test');
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($project);
$entityManager->flush();
return $this->render('project/index.html.twig', [
'controller_name' => 'ProjectController',
]);
}
Objekte ändern
/**
* @Route("/product/edit/{id}")
*/
public function update($id)
{
$product = $entityManager->getRepository(Product::class)->find($id);
if (!$product) {
throw $this->createNotFoundException(
'No product found for id '.$id
);
}
$entityManager = $this->getDoctrine()->getManager();
$product->setName('New product name!');
$entityManager->flush();
return $this->redirectToRoute('product_show', [
'id' => $product->getId()
]);
}
Objekte löschen
$entityManager->remove($product);
$entityManager->flush();