Skip to content

aoxborrow/php-starter-pack

Repository files navigation

PHP Starter Pack

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

Features

  • 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)

Makefile Shortcuts

  • make db - run db.sql to create project tables
  • make start/restart/stop - start/restart/stop Nginx & PHP-FPM
  • make provision-dev - run ansible playbook for localhost/dev
  • make provision-prod - run ansible playbook for production group
  • make install-galaxy-roles - install galaxy roles from ansible/requirements.yml

Local Development

  1. You'll need VM software like VirtualBox (Mac/PC) or Parallels (Mac)

  2. Install Vagrant for automating VMs.

  3. 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
  4. Build your Vagrant VM:

    vagrant up
  5. Modify your computer's local /etc/hosts:

    192.168.33.73   my-project-name.local
    
  6. Visit your app:

    http://my-project-name.local
    
  7. Log into the VM via SSH and run db.sql to create example data:

    vagrant ssh
    cd my-project-name
    make db
  8. Visit example page with DB query results:

    http://my-project-name.local/example/results
    
  9. Profit ✔️


Production

  1. You'll need a remote user with sudo privileges for Ansible provisioning – don't use root.

  2. Edit the prod group in ansible/inventory.yml and set the ansible_user and ansible_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

  3. Set the production host_name in ansible/group_vars/prod.yml. This is the domain that Nginx will use.

  4. 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
  5. Profit ✔️


"No-Framework" PHP

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.

Writing Controllers

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.