This is a starter pack for quickly developing a modern PHP project locally with Vagrant, which is then easily deployed live with Ansible. It installs and configures everything you need to enjoy a self-contained and disposable server VM:
- Ubuntu 18.04
- PHP 7.3 and Composer
- Nginx for static files with catch-all proxy to PHP-FPM
- MySQL database and user
- Ansible playbook with configuration for both local development and production
- Easily add Ansible Galaxy roles for additional infrastructure with
ansible/requirements.yml
- Automatically installs PHP dependencies from
composer.json
- Minimal "no-framework"
index.php
with routing, templating, and exception handling (see below)
make db
- run db.sql to create project tablesmake start/restart/stop
- start/restart/stop Nginx & PHP-FPMmake provision-dev
- run ansible playbook for localhost/devmake provision-prod
- run ansible playbook for production groupmake install-galaxy-roles
- install galaxy roles fromansible/requirements.yml
-
You'll need VM software like VirtualBox (Mac/PC) or Parallels (Mac)
-
Install Vagrant for automating VMs.
-
Clone this repo as your project name: (This is important, the project folder name will be used for initial configuration of database name, hostname, etc.)
git clone git@github.com:paste/php-starter-pack.git my-project-name
-
Build your Vagrant VM:
vagrant up
-
Modify your computer's local
/etc/hosts
:192.168.33.73 my-project-name.local
-
Visit your app:
http://my-project-name.local
-
Log into the VM via SSH and run db.sql to create example data:
vagrant ssh cd my-project-name make db
-
Visit example page with DB query results:
http://my-project-name.local/example/results
-
Profit ✔️
-
You'll need a remote user with
sudo
privileges for Ansible provisioning – don't useroot
. -
Edit the
prod
group inansible/inventory.yml
and set theansible_user
andansible_host
. This is the SSH user and host to connect to. See here for more details: https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html -
Set the production
host_name
inansible/group_vars/prod.yml
. This is the domain that Nginx will use. -
It's handy to provision from within your Vagrant VM since it already has Ansible installed. Log into the VM and run the Ansible playbook for the production group:
vagrant ssh cd my-project-name make provision-prod
-
Profit ✔️
The public/index.php
file contains a minimal "no-framework" approach which uses PSR standards and popular 3rd-party libraries to accomplish much of what a larger framework provides. All of the libraries can be easily swapped using dependency injection. Here's a list of features and how they are implemented:
- URL Routing is provided by FastRoute. Nginx is configured with a catch-all rule to forward requests to index.php if there is no matching static file.
- Templating uses the Twig template engine to enforce separation of PHP logic and frontend HTML. It is easy to use, well documented, and allows for convenient template inheritance.
- Configuration is handled by zend-config. This small library supports multiple file formats and provides an OO interface for site configuration.
- Database Access uses the standard built-in PDO library for its consistent API and data handling. A singular PDO connection is automatically provided to each controller.
- Request/Response objects are provided to each controller for convenience in handling HTTP headers, redirects, etc. These Symfony HTTP Components are fully featured and well documented. It is easy to add the Session component if needed.
- Custom Exception Handling allows for a better user and developer experience. It is a clean way to return proper 4XX/5XX HTTP error messages to the browser.
The public/index.php
file will automatically route requests to your custom "controller" classes using the following naming convention:
/mycontroller/mymethod === MyController->mymethod()
The default method is index()
, so you can omit it in the URL:
/mycontroller === MyController->index()
Controller methods that are protected
, private
, or static
will not be accessible to the router. You can also write explicit routes and use named parameters, see public/index.php
and the FastRoute documentation for examples.
Check out src/controllers/ExampleController.php
to see examples of querying the database and rendering templates using the provided PDO
and Twig
instances. The abstract BaseController
class provides a few convenience methods like render()
and query()/queryAll()
which should be enough to get started.