Stefan Bauer
Developer and Creator of PingPing.io, a simple website monitoring.
Blog Building PingPing Newsletter About
"Building PingPing" was an open-source project. There have been several reasons why I discontinued creating it in public. PingPing.io has now a commercial version. If you have any questions about PingPing, its techniques, architecture or anything else, let me know. I might do a post about it. You can find the related sources for the old posts on GitHub.

#002: Let's get the ball rolling

Published on January 20, 2018

Presumptions

This series is not intended to be for complete beginners. Basically, I assume that you are familiar with your personal development environment, you can setup a new Laravel project and get the project running in the browser.

You should have an environment that works right now. I personally work on an Apple MacBook. Due to other projects and special configurations, I rely on an installation and configuration of my software by brew, a package manager for macOS. But feel free to use Laravel Valet or anything else, you are comfortable with.

Due to my configuration, I'm gonna always refer to http://local.pingping.io:8080. You might have something different. For instance http://pingping.test or so.

A side note: These are the services I'm currently using at the time of writing this post.

➜ services list
Name            Status  User         Plist
redis           started stefan.bauer /Users/stefan.bauer/Library/LaunchAgents/homebrew.mxcl.redis.plist
memcached       started stefan.bauer /Users/stefan.bauer/Library/LaunchAgents/homebrew.mxcl.memcached.plist
php71           started stefan.bauer /Users/stefan.bauer/Library/LaunchAgents/homebrew.mxcl.php71.plist
nginx           started stefan.bauer /Users/stefan.bauer/Library/LaunchAgents/homebrew.mxcl.nginx.plist
mysql           started stefan.bauer /Users/stefan.bauer/Library/LaunchAgents/homebrew.mxcl.mysql.plist
blackfire-agent started stefan.bauer /Users/stefan.bauer/Library/LaunchAgents/homebrew.mxcl.blackfire-agent.plist
supervisor      started stefan.bauer /Users/stefan.bauer/Library/LaunchAgents/homebrew.mxcl.supervisor.plist

It's not necessary, to use these. I just wanted to mention it for the sake of completeness. For now, we only need PHP >= 7.0, a webserver (nginx or apache for instance) and MySQL as the database server. I also assume that you have the package manager composer already installed and are used to use it. It should also be in your path, so you can use it from everywhere in your file system.

Creating a new project

I create my new project in my home directory within a folder called Code as Valet does it. So let's create that directory, if it doesn't exist and cd into it from the terminal. And oh, I use of course iTerm2 for that. I prefer using the Laravel Installer. If you haven't it, just download the installer using composer.

composer global require "laravel/installer"

Make sure, the composer's vendor bin directory is in your $PATH so the Laravel executable can be located. The cool thing about the installer is, that you can just use now laravel new to create a fresh Laravel installation within the specified directory. So in our case:

laravel new pingping

Alternatively you may also install Laravel using composer directly via

composer create-project --prefer-dist laravel/laravel pingping

At the time of writing this post, Laravel is at version 5.5.32.

Pushing it up to GitHub

As I told you, I build this project in public. Therefore I created an empty repository on GitHub, where you can follow the entire development process, collaborate with pull requests or just use the issues to track todos, ideas or bugs. You can find the repository at https://github.com/stefanbauer/pingping.

If you want to code along with me, you can use your own repository. The first thing I always do after installing a new project, I create a brand new local repository, commit the naked current state and push it to the remote repository to have a clean reference point. Actually I use always git-flow, as I am a big fan of it. But in this case I'm gonna stick with a simple master branch for now. Let's cd into our pingping project directory.

git init
git add .
git commit

Now I enter as the commit message something like initial commit with naked Laravel 5.5.32 or so.

Oh and by the way. In the future I'm gonna to use my personal git aliases. If you're interested in, have a look at this post here. To make getting started easier, I show you these details only in this post. In upcoming posts, I will just refer to things like pushing, committing or rebasing.

Then let's push it up to the remote. First we have to add the remote. Usually this is called origin.

git remote add origin git@github.com:stefanbauer/pingping.git

After I have done that, we have to use for the very first time of pushing it up

git push -u origin master

instead of a simple git push. git push -u is the equivalent to git push --set-upstream. This is necessary to tell git, that you'd like to push to the remote and enable tracking for this branch. Finally you have to add the remote name, where the branch should be pushed to and of course the name of the branch, which should be pushed.

That's it. We are done with git. Congratulations!

By the way: You can of course clone this project directly, if you don't like to work along with me. But please don't forget to install all the composer and yarn/npm dependencies.

composer install
yarn install

Let's do some basic setup

Open the new project by using your editor of choice und let's get started to do some basic setup.

PHP Coding Standards Fixer

For a couple of reasons, I use in every single project the PHP Coding Standards Fixer which is a great tool. It fixes the code to the given standards. But one step at a time.

Short excursion: As soon as several team members are working on a project, I think it makes sense to use something like this. This ensures the same coding standard and code always looks identical. At least structurally. From my many years of experience I can confirm that such a tool is worth in any case.

I suggest you to install it globally via composer, like the Laravel Installer. So let's do it.

composer global require friendsofphp/php-cs-fixer

You still have to make sure, same as with the Laravel Installer, that your Composer's binaries directory is in your $PATH. But I guess, it should be meanwhile though. Anyways. If we type php-cs-fixer in the terminal, you should get information about the usage. If that happens, everything went well. If it doesn't work, there is a big chance, that you have to restart your terminal session, if you added the Composer's binary directory now and you forgot to source your bashrc/zshrc, or whatever shell you're using.

If that works for you, it's time to create a little configuration file, that defines what our cs-fixer should take care about, which paths should be under control and what it needs to fix. Most people use as the main configuration rule the PSR-2 standard. For me personally, i'll go a little bit further and use the Symfony standard. It's on top of the PSR-2 with some more restrictions and some more settings that I find useful. Additionally to that default configuration, it is possible to override each option, which is set by the default setting. One of these setting I always change is the ordered_imports to the sortAlgorithm to length. What this does is, it orders the use statements by length and not by alphabet. But this comes down to your personal preference. It's up to you, if you like that or not. All that code should go into a .php_cs.dist in your root directory.

--- /dev/null
+++ b/.php_cs.dist
@@ -0,0 +1,23 @@
+<?php
+
+namespace PhpCsFixer;
+
+$finder = Finder::create()
+    ->name('*.php')
+    ->in(__DIR__.DIRECTORY_SEPARATOR.'app')
+    ->in(__DIR__.DIRECTORY_SEPARATOR.'tests')
+;
+
+return Config::create()
+    ->setUsingCache(false)
+    ->setRiskyAllowed(true)
+    ->setRules([
+        '@Symfony' => true,
+        'strict_param' => true,
+        'array_syntax' => ['syntax' => 'short'],
+        'ordered_imports' => ['sortAlgorithm' => 'length'],
+        'phpdoc_order' => true,
+        'phpdoc_annotation_without_dot' => false,
+    ])
+    ->setFinder($finder)
+;

In my environment setup, the cs-fixer runs immediatelly, when I save a file. So it can never ever happen, that I commit something, that does not fit the coding standards. Later, we're gonna to use a tool like StyleCI. This tool reads our cs-fixer configuration and applies the changeset automatically via pull request. But one step at a time.

Customizing the .gitignore

For me, I don't like the default .gitignore much for several reasons.

  • Environment-specific files should not be ignored per project. The developer is responsible for this. Imagine you have a team of 10 developers and each developer is working with a different IDE. Should every developer ignore their IDE-dependent folders/files? This is the problem of the developer, not the project. In the worst case, you'll end up with a ignore file that holds more IDE related entries than really project related entries.
  • I'm not a fan of defining what to ignore. I do always the opposite. Something like "Please ignore everything by default, unless I tell you explicitly that something should not be ignored!".

For now, let's use the following .gitignore.

--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,13 @@
+.env
+!composer.lock
+!phpunit.xml
 /node_modules
-/public/hot
-/public/storage
+
+/public/*
+!/public/images
+!/public/index.php
+!/public/favicon.ico
+!/public/robots.txt
+
 /storage/*.key
 /vendor
-/.idea
-/.vagrant
-Homestead.json
-Homestead.yaml
-npm-debug.log
-yarn-error.log
-.env

You might ask yourself, why the hell I ignore /public/*. The thing is, that we're using Laravel Mix and we really don't need anything in the public folder, but the index.php, the favicon.ico and the robots.txt for now. Everything else, will be copied over during our deployment process using Laravel Mix. Even the images are not necessary in my opinion. But let's keep it there for now and see where we're getting.

A quick side note: I exclude composer.lock and phpunit.xml.

The reason for the composer.lock is, that when developing libraries, it's not necessarily recommended to commit the lock file. So I have the this file in my global gitignore. The reason for excluding the phpunit.xml is, that in general I think something like this and it might be, that we change that later together:

For a predefined phpunit.xml I would rename it to phpunit.xml.dist, like the .env.example (I would call it also .env.dist by the way). With that, you got always distribution files. You can of course work with exactly these files on your machine. Don't worries. But if you would like to have a different local configuration than your team mates, you can create your personal phpunit.xml and the phpunit.xml.dist will remain untouched. With that in mind, it is possible that every single team mate could have it's own phpunit configuration without any hassle.

But you know what? Let's do it now.

Renaming phpunit.xml

Here is nothing much to say. I will rename the phpunit.xml to phpunit.xml.dist behind the scenes and we're good to go. We're gonna customize this file later, if we need to. But the cool thing is now, that if in this distribution file is used mysql for instance, you can create your own local version with in-memoery sqlite database, without taking care if you are safe to to push that phpunit.xml(.dist) file or not.

Renaming .env.example

So that everything is done right away, we also rename the .env.example to .env.dist. Cool!

Pushing up the changes

What we forgot is, that we've to remove the app.js and app.css which are located in the public folder, because these compiled assets are generated by npm.

git rm --cached public/css/app.css
git rm --cached public/js/app/js

--cached in this case means that we remove the files from the index, but keep a copy in the working tree. This is exactly what we want, cause locally we need these files.

Now that we've changed some files and modified the .gitignore, there are also some new files to track. Add it, commit it and push it.

git add .
git commit
git push

What's next?

For today we're done. Actually, to be honest, my plan was to integrate TailwindCSS in this episode and start with the the first frontend topic - the Login. Just because I think there's nothing better than seeing immediate results.

Anyways, now I told you not only what I did and copied some code, I also told you why I did things like I did it and what my experience is in different situations. So if you have any questions about that, let me know on Twitter or shoot me a mail. In the next episode we will really start to integrate TailwindCSS and the Login. Keep on coding!

If you enjoy my posts or you like what I'am talking/twittering about, you should sign up. I will show you everything I know about development and UI/UX.

Imprint Cookie Policy Privacy Policy
Proudly hosted with Vultr