This is a starter app from Symfony4 for easy forking for new starters.
- Install Virtualbox
- Install Vagrant
- Run
vagrant plugin install vagrant-hostsupdater
- Run
vagrant up
You now have a web server running on http://symfony.local.
You can edit the code directly in this directory to make changes.
You can ssh into the vagrant box with vagrant ssh
.
Get to the code with cd /srv/www/app/current
.
Once inside the vagrant box you can run Symfony commands, here are some useful ones:
# Clear the Symfony cache
$ bin/console cache:clear
- Create a new Controller with an index action
- Create a route in
routes.yaml
for the index action at the/
path - Create a new twig template in
templates/
- Make the twig template extend
base.html.twig
- Make the index action render the new template
- Pass some variables through to the twig template and render them
- Play with adding new variables and removing them
- Create a hello action in your Controller
- Create a route for the action, give the route a path parameter of
{name}
- Add
Request $request
andstring $name
as parameters to the action - Get the
lastName
parameter from the$request
with a suitable default value if it doesn't exist - Create a new twig template and pass the two names through to it
- Make the twig template render the names
- Play with the path and request parameters
- Create your database schema
$ ./bin/console doctrine:database:create
- Create a
Post
entity inEntity/
- Give it the following attributes:
- string id
- string slug
- string title
- string text
- \DateTimeImmutable $createdAt
- \DateTimeImmutable $updatedAt
- Import
Doctrine\ORM\Mapping as ORM
, these are the Doctrine annotations you'll use to define the schema - Add the
@ORM\Entity
annotation to the class - Add the
@ORM\Column(type=<your type>)
annotation to each property- Choose which type you want from the Doctrine docs
- Add the following annotations to the
id
field to make MySQL automatically generate it:/** * @ORM\Id * @ORM\GeneratedValue(strategy="UUID") */
- Check the SQL that Doctrine wants to run to update the database
$ ./bin/console doctrine:schema:update --dump-sql
- If the SQL makes sense, execute it
$ ./bin/console doctrine:schema:update --force
- Get the details to log into the database from the
.env
fileDATABASE_URL=mysql://<username>:<password>@127.0.0.1:3306/<db name>
- Log into the database
$ mysql -u <username> -p <db name>
- Have a play, here are some fun SQL commands
show tables; describe post; select * from post;
- Create a
PostType
class inForm/
that extendsAbstractType
- Implement the
buildForm(FormBuilderInterface $builder, array $options)
function - Add a few fields to the form with
$bulider->add()
that exist in thePost
entity, eg.$builder->add('title')
- The second argument to the
add()
function allows you to change the type of the form field that's rendered$builder->add('text', TextareaType::class);
- Add a submit button to your form
$builder->add('sumbit', SubmitType::class)
- Create a new Controller action and route for
createPost
(remember to inject theRequest
) - In your controller, create a new
Post
, bind it to the form and handle the requsett$post = new Post(); $form = $this->createForm(PostType::class, $post); $form->handleRequest($request)
- Now create a new twig template 'create-post.html.twig' to render your form, you can render a form with:
{{ form(form) }}
- If the form hasn't been submitted, you need to render your new twig file
if (false === $form->isSubmitted() || false === $form->isValid()) { return $this->>render('create-post.html.twig', ['form' => $form->createView()]); }
- Now you can load your page and look at the form, have a play with the
PostType
class to see what you can change - In order to save your
Post
to the database when the form is submitted, you need to use theEntityManager
, so you inject it into the constructor of your Controller/** @var EntityManagerInterface **/ private $entityManager; public function __construct(EntityManagerInterface $entityManager) { $this->entityManager = $entityManagerInterface; }
- Now you can save your
Post
to the database, but only if the form has been submitted and is valid$this->entityManager->persist($post); $this->entityManager->flush();
- It's best practice to do a redirect after a form is successfully submitted because it prevents the user from
accidentally submitting the form twice
return $this->redirect('create');
- Submit your form a few times, log into the database like we did in the previous task and check our your posts
- Create a new twig template that iterates through a list of Posts and prints their title
<ul> {% for post in posts %} <li>{{ post.title }}</li> {% endfor %} </ul>
- Create a new Controller action
- Get a list of all the Posts and pass them through to your twig template
$posts = $this->entityManager->findAll(Post::class);
- Load the page, you should see a list of all the Posts in your database
- Inject the
Request
into your action and get the'title'
parameter from it (with a sensible default value of''
) - Create a
QueryBuilder
in order to search the database for specific Posts$posts = $this->entityManager->createQueryBuilder() ->select('post') ->from(Post:class, 'post') ->where('post.title = :title') ->setParameter('title', $title) ->getQuery() ->getResult() ;
- Now you can search for Posts by title!
- Have a play, try and the QueryBuilder doing a wildcard search with an SQL like