Setup and a Basic Wallpaper Gallery
In this video we make a start on the implementation of our wallpaper / desktop background website. This is a gentle introduction, primarily involved with:
- downloading Symfony
- setting up Bootstrap and some basic styles
- creating our Gallery controller
- creating the Gallery view / Twig template
- displaying some content in the gallery
Rather than dive in and start setting up Doctrine entities and creating fixtures and all that jazz, we are going to start with the simple stuff, and work our way up.
With this in mind, we are going to start with a single image that we can find via Google image search (or wherever), and then use this image in a 'hardcoded' fashion. This is good enough to prove our basic setup works, gives us a quick and easy win, and also forms the basis for making the whole thing dynamic.
Before we can do any of this, we need to download Symfony.
As has been mentioned in the introduction to this course, I'm not going to go into as much depth with concepts that we have already covered before. Installing Symfony was covered in this video, so I'm going to assume you either know how to do this, or ask that you please view this video first.
In my case, I'm going to have my project be called "wallpaper" - so imaginative am I - and as we are on Symfony v3.2.8 at the time of recording, my output looks like this:
➜ ~/Development symfony wallpaper
Downloading Symfony...
5.5 MiB/5.5 MiB ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 100%
Preparing project...
✔ Symfony 3.2.8 was successfully installed. Now you can:
* Change your current directory to /home/chris/Development/wallpaper
* Configure your application in app/config/parameters.yml file.
* Run your application:
1. Execute the php bin/console server:start command.
2. Browse to the http://localhost:8000 URL.
* Read the documentation at http://symfony.com/doc
I will then cd
(change directory) into the wallpaper
directory and immediately do a composer update
. It's surprising how many of the dependencies will have some new patches to apply.
cd wallpaper
composer update
With the project downloaded and updated, I would then follow the instructions further and ensure to start up the local webserver:
php bin/console server:start
At this point a URL - http://localhost:8000
should be visible in your terminal, clicking on which should take you to a browser showing the basic Symfony start point.
Make sure to open the project in your editor / IDE of choice here.
Next, we need to make some initial tweaks to the templates that Symfony provides. We're going to add in Bootstrap's CSS files via the CDN links provided on getbootstrap.com, and our own CSS file for any overrides / local tweaks we want to add in:
<!DOCTYPE html>
<!-- /app/Resources/views/base.html.twig -->
<html>
<head>
<meta charset="UTF-8" />
<title>{% block title %}Welcome!{% endblock %}</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<link rel="stylesheet" href="{{ asset('css/styles.css') }}" />
{% block stylesheets %}{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>
As you can see, we've added in the entry from getbootstrap.com, and also an entry that we've passed as a parameter to the asset
function. Our publicly accessibly path will be our web
directory, so our next step is to create a new directory inside the web
directory, into which we need to add a single file - styles.css
.
You are free to skip this step, of course.
cd web
mkdir css
touch css/styles.css
cd ..
Feel free to do this via your editor, via a file explorer, or the console. There's no difference.
We don't need to add any entries into the css/styles.css
file right now, but it gets that task out of the way all the same. One thing to note here, there is reasoning for the way in which the styles are listed inside the head
tag.
First comes the Bootstrap CSS. This is the most generic stylesheet that we are applying to this project.
Next comes our custom styles.css
file. Any changes we make in here will take precedence over any CSS defined in the Bootstrap sheet. In other words, if we had .img
inside the Bootstrap stylesheet, and we declared .img
again inside our styles.css
file, then ours would "win" when it came time to display.
Lastly we have the inclusion of {% block stylesheets %}{% endblock %}
. Now, I'd recommend you don't use this. Stick with the styles.css
file. But it's there because you may wish to use it, or as I infrequently do, use it for debugging. Honestly though, you could get rid of this.
Adding a Wallpaper
To as quickly as possible make things that bit more interesting, we're now going to add in a basic gallery layout.
We don't need to worry about creating the image upload capability just yet. Instead, we're going to do this manually, and then use some hardcoded data to display one (or several) images on the page.
The nice thing about this is not only does it provide a very quick proof of concept, but it also is very similar to how our site will work once we involve images coming from the database.
First up, we are going to need a picture.
If you have a selection of wallpapers already then cool, feel free to use one of those.
If you don't then head over to Google Images, and use some generic term - "summer", "winter", "autumn", "cars" - that sort of thing to find an image to use. You could also use the images from the code repository for this project.
Once inside Google Image search you can click "Tools" then in the pop up menu, select "Size" and put in some exact dimensions to get just those that meet your requirements. For the purposes of my demo, I chose to use 1920x1080, aka 1080p, as I thought this was a popular resolution. It turns out that 1366x768 is by far the most popular resolution used on modern desktop computers (at the time of writing), so if you plan to put this site live then factor this in to your downloading.
One other thing to note: if you are going to put your site online then be sure to filter images by those that are allowed for reuse.
If all of that seems like to much hard work then feel free to use the one I used in the video.
The important part here is not the image that you use, but rather the location in which you save it.
Save the image inside your projects web
directory. It doesn't matter too much where inside this directory that this file goes, but in my case I'm putting this under web/images/my-image-file-name.jpg
. The reason we must put the image inside (or some subfolder of) the web
directory is that this is our web root. In other words, this directory will be publicly accessible - and we want our users to be able to see our images. You can read a little more about this on the official Symfony docs.
Gallery Controller
To actually see this image on our site we must start writing a little code. Hoorah, finally!
I'm going to start by renaming the provided DefaultController.php
file to GalleryController.php
, and I'm going to change the contents accordingly:
<?php
// /src/AppBundle/Controller/GalleryController.php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class GalleryController extends Controller
{
/**
* @Route("/gallery", name="gallery")
*/
public function indexAction()
{
return $this->render('gallery/index.html.twig', [
'images' => [
'summer-morning-in-fort-collins.jpg',
]
]);
}
}
If any of this is new to you then I would again point you towards this video where we have covered basic controller actions in more detail.
Essentially we have a Route
annotation that makes the /gallery
route available on our website.
When we load the /gallery
route this indexAction
will be called.
This in turn will return
the output of render
ing our gallery/index.html.twig
file. This file does not yet exist. We will create it momentarily.
Inside this template we will expect to have access to an array, in which there will be a key called images
. This key of images
will be expected to contain an array of strings, each one representing an image filename.
Ok, so it's not the most robust system, but it should be good enough.
Let's look at the template:
<!-- /app/Resources/views/gallery/index.html.twig -->
{% extends 'base.html.twig' %}
{% block body %}
<div class="row">
{% for image in images %}
<div class="col-sm-6 col-md-4">
<a href="#" class="thumbnail">
<img src="/images/{{ image }}" alt="...">
</a>
</div>
{% endfor %}
</div>
{% endblock %}
We can see a for
loop that will loop through all the images
that we passed in from the controller. Each image
(singular) will be an element from the images
(plural) array. In our case that means each image
will be a string - summer-morning-in-fort-collins.jpg
.
When we expand on this a little later on, we will work with objects, but the general principles are the same.
Here we're saying that for every element in our images
array we want to render the markup inside the {% for ... %}
block:
<div class="col-sm-6 col-md-4">
<a href="#" class="thumbnail">
<img src="/images/{{ image }}" alt="...">
</a>
</div>
In other words, each element will get put in a div
that contains an img
wrapped in a link. For now the link doesn't really work (href="#"
) but we will fix this as we continue on.
The image itself will expect to be found by looking in the web root - in other words our web
directory, then inside the images
directory, and whatever string we gave (in full, including the extension) should be the file name.
Providing you gave the right file name when adding your entry to the images
array inside the controller, and that the path is correct (e.g. web/images/
) then you should be able to visit your /gallery
page and see a 'thumbnail' of your picture.
One thing to note here is that this isn't really a thumbnail. It's the full size image that Bootstrap has shrunk nicely for us. This is important as it means we're still really loading the huge full size image. We will need to address this problem as we go through the project, as otherwise, we will not only burn more bandwidth than we need too, but more importantly the UX will be awful for those on slow connections.
And that pretty much gets us where we need to be for the moment. In the next video we will add in pagination, still keeping our setup as simple as possible. The cool thing is we can switch from using arrays to database-backed objects without much change here, so we aren't doing a bunch of work for nothing. Which is nice :)