Deploying and Developing PHP Apps

Page last updated:

Welcome to Pivotal Web Services, powered by Cloud Foundry!

This document is intended to guide you through the process of deploying PHP applications to Pivotal Web Services (PWS). If you experience a problem with deploying PHP apps, check the Troubleshooting section below.

Getting Started

Prerequisites

A First PHP Application

$ mkdir my-php-app
$cd my-php-app
$ cat << EOF > index.php
<?php
  phpinfo();
?> 
EOF
$ cf push my-php-app -m 128M

Change “my-php-app” to a unique name, otherwise you get an error and the push fails.

The example above creates and pushes a test application, “my-php-app”, to Cloud Foundry.

Here is a breakdown of what happens when you run the example above:

  • On your workstation…
    • It creates a new directory and one PHP file, which calls phpinfo()
    • Run cf push to push your application. This will create a new application with a memory limit of 128M and upload our test file.
  • On Cloud Foundry…
    • The buildpack detects that your app is a php app
    • The buildpack is executed.
      • Application files are copied to the htdocs folder.
    • Apache HTTPD & PHP are downloaded, configured with the buildpack defaults, and run.
    • Your application is accessible at the default route. Use cf app my-php-app to view the url of your new app.

Folder Structure

The easiest way to use the buildpack is to put your assets and PHP files into a directory and push it to PWS. This way, the buildpack will take your files and automatically move them into the WEBDIR (defaults to htdocs) folder, which is the directory where your chosen web server looks for the files.

URL Rewriting

If you select Apache as your web server, you can include .htaccess files with your application.

Alternatively, you can provide your own Apache or Nginx configurations.

Prevent Access To PHP Files

The buildpack will put all of your files into a publicly accessible directory. In some cases, you might want to have PHP files that are not publicly accessible but are on the include_path. To do that, create a lib directory in your project folder and place your protected files there.

For example:

$ ls -lRh
total 0
-rw-r--r--  1 daniel  staff     0B Feb 27 21:40 images
-rw-r--r--  1 daniel  staff     0B Feb 27 21:39 index.php
drwxr-xr-x  3 daniel  staff   102B Feb 27 21:40 lib

./lib:
total 0
-rw-r--r--  1 daniel  staff     0B Feb 27 21:40 my.class.php  <-- not public, http://app.cfapps.io/lib/my.class.php == 404

This comes with a catch. If your project legitimately has a lib directory, these files will not be publicly available because the buildpack does not copy a top-level lib directory into the WEBDIR folder. If your project has a lib directory that needs to be publicly available, then you have two options as follows:

Option #1

In your project folder, create an htdocs folder (or whatever you’ve set for WEBDIR). Then move any files that should be publicly accessible into this directory. In the example below, the lib/controller.php file is publicly accessible.

Example:

$ ls -lRh
total 0
drwxr-xr-x  7 daniel  staff   238B Feb 27 21:48 htdocs

./htdocs:  <--  create the htdocs directory and put your files there
total 0
-rw-r--r--  1 daniel  staff     0B Feb 27 21:40 images
-rw-r--r--  1 daniel  staff     0B Feb 27 21:39 index.php
drwxr-xr-x  3 daniel  staff   102B Feb 27 21:48 lib

./htdocs/lib:   <--  anything under htdocs is public, including a lib directory
total 0
-rw-r--r--  1 daniel  staff     0B Feb 27 21:48 controller.php

Given this setup, it is possible to have both a public lib directory and a protected lib directory. The following example demonstrates this setup:

Example:

$ ls -lRh
total 0
drwxr-xr-x  7 daniel  staff   238B Feb 27 21:48 htdocs
drwxr-xr-x  3 daniel  staff   102B Feb 27 21:51 lib

./htdocs:
total 0
-rw-r--r--  1 daniel  staff     0B Feb 27 21:40 images
-rw-r--r--  1 daniel  staff     0B Feb 27 21:39 index.php
drwxr-xr-x  3 daniel  staff   102B Feb 27 21:48 lib

./htdocs/lib:  <-- public lib directory
total 0
-rw-r--r--  1 daniel  staff     0B Feb 27 21:48 controller.php

./lib: <-- protected lib directory
total 0
-rw-r--r--  1 daniel  staff     0B Feb 27 21:51 my.class.php

Option #2

The second option is to pick a different name for the LIBDIR. This is a configuration option that you can set (it defaults to lib). Thus if you set it to something else such as include, your application’s lib directory would no longer be treated as a special directory and it would be placed into WEBDIR (i.e. become public).

Other Folders

Beyond the WEBDIR and LIBDIR directories, the buildpack also supports a .bp-config directory and a .extensions directory.

The .bp-config directory should exist at the root of your project directory and it is the location of application-specific configuration files. Application-specific configuration files override the default settings used by the buildpack. This link explains application configuration files in depth.

The .extensions directory should also exist at the root of your project directory and it is the location of application-specific custom extensions. Application-specific custom extensions allow you, the developer, to override or enhance the behavior of the buildpack. This link explains extensions in more detail.

Troubleshooting

There are a couple of easy ways to debug the buildpack:

  1. Check the output from the buildpack. It writes some basic information to stdout, like the files that are being downloaded. It writes information should something fail, specifically, stack traces.

  2. Check the logs from the buildpack. The buildpack writes logs to disk. Retrieve them with the command, as the following example shows:

    Diego release

    $ cf ssh APP
    $ cat app/.bp/logs/bp.log
    

This log is more detailed than the stdout output, but is still terse.

Set the BP_DEBUG environment variable to true for more verbose logging. This instructs the buildpack to set its log level to DEBUG and it writes to stdout. Follow Environment Variables documentation to set BP_DEBUG.

Create a pull request or raise an issue on the source for this page in GitHub