FileMaker® API for PHP Tutorial

Contents

Introduction
Lesson 1
Lesson 2
Lesson 3
Lesson 4
Lesson 5
Lesson 6

Introduction

Welcome to the FileMaker API for PHP Tutorial

This tutorial demonstrates key functionality of the FileMaker API for PHP. The tutorial consists of 6 lessons designed to teach you how to use the API to integrate a FileMaker Pro database with a PHP web application. Each lesson introduces a particular capability of the API, explaining how the code is written and how it works.

The tutorial database is a FileMaker questionnaire system (questionnaire.fp7). Each questionnaire record can have multiple related questions. Each question can have multiple related answers. Only one questionnaire is selected to be the active questionnaire. The active questionnaire is the one users are invited to take when using the PHP web application. When a user completes an online questionnaire, the system adds a respondent record for the user and adds the user's answers as related records.

The tutorial completes a PHP web application gradually, each lesson building upon the previous lesson as follows:

This tutorial doesn't cover all of the API. However, after you complete these lessons, you will have a good foundation. To discover more about the API, see the FileMaker API for PHP documentation.

To view the FileMaker API for PHP documentation, go to the FileMaker Server Admin Console Start Page and click "PHP Site Assistant and XSLT Site Assistant Tools." On the Web Publishing Tools page, click "FileMaker API for PHP Documentation." Use the documentation as a reference while you complete this tutorial. This reference will help you discover how to use the FileMaker API for PHP more completely.

You should also become familiar with the questionnaire.fp7 database. Discover how it works and how questionnaires are built by creating questions with multiple answers. Your knowledge of the questionnaire.fp7 design will be an integral part of understanding how the tutorial PHP application uses the API.

Getting Started

Setup and Installation

You must have FileMaker Server 9 installed and it must host the questionnaire.fp7 database. The tutorial folder must be hosted on the web server machine that is part of your FileMaker Server deployment.

For more information on the installation and deployment of FileMaker Server 9, see the FileMaker Server Getting Started Guide. For more information about the FileMaker API for PHP, see FileMaker Server Custom Web Publishing with PHP.

Suggested Knowledge and Skills

You should be familiar with HTML programming. This includes HTML declarations, headers, and element tags. If you need more information on programming web pages with HTML, see the XHTML Tutorial at W3Schools.

You should be familiar with PHP programming. This includes standard output, variables, arrays, conditional loops, objects, methods, and functions. For more information on programming with PHP, see the PHP Tutorial at W3Schools.

You should be comfortable using a text editor with HTML and PHP. This tutorial requires the use of a text editor to view and modify HTML and PHP code.

You should have a working knowledge of FileMaker Pro database design. This includes fields, relationships, layouts, portals, and containers. For more information on designing databases with FileMaker Pro, see the FileMaker Pro documentation.

Best Practices

When editing records in FileMaker Pro, remember to exit or commit the record in order for changes to take effect. Web pages do not reflect changes entered into the database until the record has been exited.

To view the PHP pages of each lesson in your web browser, you must supply the fully qualified URL in order for the PHP code to execute. For example, if the files are hosted on your local machine, point your browser to a URL that starts with "http://localhost/...". Do not use the local file path which may start with "file:///Volumes/...". Using a "file://" URL results in the display of PHP code, not the execution of PHP code. Always make sure the URL begins with "http", or "https" if you have set up SSL on your web server.

Lesson 1

Objective

Lesson 1 details the essentials for using the FileMaker API for PHP in two PHP files: home.php and dbaccess.php. The home.php file serves as a web browser starting point, and the dbaccess.php file sets up a FileMaker object that represents the database. These pages show the basic steps for instantiating the FileMaker database object, setting its key properties, and performing a find on the questionnaire.fp7 database.

Start

To view the tutorial example, direct your web browser to home.php located inside the Lesson1 folder. This page displays the welcome screen for the FileMaker Questionnaire System. When the page loads, a connection occurs behind the scenes between PHP and the Web Publishing Engine, resulting in a found record from the questionnaire.p7 database.

Using your text editor, open the file home.php inside the Lesson1 folder. Locate the following code just after the body tag.

<?php include ("dbaccess.php"); ?>

This PHP statement includes, or loads, the dbaccess.php file. The dbaccess.php file contains functions which set up the FileMaker database object and prepare it for database operations. Consequently, API methods in home.php will not work without it. Although the methods in dbaccess.php could have been written in the home.php file, they have been separated for easier debugging and maintenance.

Set up the FileMaker Database Object

The dbaccess.php file contains code for setting up the FileMaker database object. It plays a fundamental role in building the questionnaire application. Follow these steps to set up the FileMaker object:

  1. Load the FileMaker API for PHP
  2. Assign an instance of the FileMaker database class to a variable
  3. Set key properties for the new FileMaker instance

Using your text editor, open the file dbaccess.php located in the Lesson1 folder and follow the description of each step below.

1. Load the FileMaker API for PHP

To use the FileMaker API, it must first be loaded into PHP memory. This is done with the require statement.

require_once ('FileMaker.php');

Once loaded, you can create instances of the FileMaker database class, using them for database connections in your web application. An attempt to use the API without loading it first will result in an error.

2. Assign an instance of the FileMaker database class to a variable

An instance of the FileMaker database class must be created before it can be used. It must also be assigned to a variable to refer to it in the code.

$fm = new FileMaker();

The above code creates an instance of the FileMaker database object. It is referred to as the variable $fm.

3. Set key properties for the new FileMaker instance

The FileMaker database object has a set of properties which can be set at any time. Some properties, however, must be set before database operations can occur. Here is the code which sets the properties required for this tutorial.

$fm->setProperty('database', 'questionnaire');
$fm->setProperty('username', 'web');
$fm->setProperty('password', 'web');

Note - The database name questionnaire does not need the fp7 extension added in the parameter.

Note - See the FileMaker API for PHP documentation for a list of the FileMaker database class properties and their descriptions.

The dbaccess.php file contains very little code, but it effectively prepares the Filemaker object for use. After the file is loaded, the FileMaker object is useable as the variable $fm and key properties are set to their required values. The dbaccess.php file enables the home.php file to communicate with the questionnaire.fp7 database.

Perform Find, Perform Find All

The home.php file performs two database operations: Find All (Show All Records) and Find. To view the code for these operations, open the home.php file in your text editor. To view the database for these operations, open the questionnaire.fp7 file that you hosted on FileMaker Server.

1. Find All (Show All Records)

The questionnaire.fp7 database contains a layout called Active Questionnaire. This layout serves as an interface; it contains only one record in the table. On this layout, users select which questionnaire is the active questionnaire. The web application needs to retrieve the ID of this active questionnaire.

The active questionnaire ID is retrieved by performing a Find All (Show All Records) on the layout Active Questionnaire. This operation uses the command object FileMaker_Command_FindAll.

Note - See the FileMaker API for PHP documentation for a list of command objects and their methods.

An instance of the FileMaker_Command_FindAll object is created by having the $fm (FileMaker database instance) execute its newFindAllCommand() method, specifying (in parenthesis) the name of the layout Active Questionnaire. The layout determines which table occurrence is used (context) and which fields are returned (results).

The FileMaker_Command_FindAll instance must be assigned to a variable as the following example shows.

$findCommand = $fm->newFindAllCommand('Active Questionnaire');

The above code assigns a new FileMaker_Command_FindAll object to the variable $findCommand. The Find All command is performed with the execute() method. The find results must be assigned to a variable.

$result = $findCommand->execute();

It is possible, after executing a command, that an error will occur. If an error does occur (or no matching records are found), the $result variable is assigned a FileMaker_Error object. Use the following code to check for the FileMaker_Error object. The error message is displayed by using the getMessage() method.

if (FileMaker::isError($result)) {
    echo "<p>Error: " . $result->getMessage() . "</p>";
    exit;
}

If no error has occurred, the variable $result contains an array of FileMaker_Record objects, one for every record in the found set. Use the $result variable to retrieve the first record in the Find All result. Because PHP arrays are indexed numerically by default, you can get the first record by using the following code.

$record = $records[0];

This code assigns a FileMaker_Record object containing the first record in the found set to the variable $record. You can retrieve the contents of the questionnaire_id from this record by using the getField() method. The results of the getField() method must be assigned to a variable.

$active_questionnaire_id = $record->getField('questionnaire_id');

This variable now contains the ID of the active questionnaire. The next step uses this variable as a parameter in the next find.

Note - See the FileMaker API for PHP documentation for a list of objects and their methods.

2. Find

Now that you have the ID of the active questionnaire, you can use it to Find the questionnaire record. The code for performing this operation is located near the bottom of the home.php file. The operation uses the command object FileMaker_Command_Find.

An instance of the FileMaker_Command_Find is created by having the $fm (FileMaker database instance) execute its newFindCommand() method, specifying (in parenthesis) the name of the layout Active Questionnaire. The layout determines which table occurrence is used in the find and which fields are returned in the results.

The FileMaker_Command_Find instance must be assigned to a variable as the following example shows.

$findCommand =& $fm->newFindCommand('questionnaire');

To add criteria to the find, use the addFindCriterion() method. The addFindCriterion() method takes two parameters: fieldName and searchParameter. Pass the "Questionnaire ID" field name (as defined in FileMaker Pro) and the variable $active_questionnaire_id as parameters.

$findCommand->addFindCriterion('Questionnaire ID', $active_questionnaire_id);

Note - The addFindCriterion() method can be called multiple times, simulating the logical AND which occurs when entering multiple find criteria into a single find request within FileMaker Pro.

After the find criteria have been added, the execute() method is used to perform the find. The results of the execute() method must be assigned to a variable.

$result = $findCommand->execute();

The $result variable now contains an array of FileMaker_Record objects. Because the find was performed on the layout questionnaire, each record in $result contains the values for every field on the questionnaire layout.

The final code in this page uses PHP echo statements and the getField() method to output the Questionnaire Name and Description fields on the home.php page.

Lesson 2

Objective

Lesson 2 covers the code required to display FileMaker Pro container images on the web. If you store web-compatible images in a FileMaker Pro database, you can use the FileMaker API for PHP to retrieve those images and display them on your web site.

Start

Open the FileMaker API Tutorial database questionnaire.fp7 and make sure that the active questionnaire has a web compatible image in the container field. Next, view the PHP tutorial example by opening the Lesson2 home.php file in your web browser. Notice the page displays the image of the active questionnaire. Try changing the container image in the FileMaker database. Make sure you exit the record when you are done. Refresh your browser and watch the website update with the new image.

Display Container Image

To see how the API is used for this operation, open the file home.php in the folder Lesson2. View the last PHP statements in the file, paying particular attention to the <img> (image) tag and its src (source) attribute.

Please note the following points regarding this technique.

  1. The container field Graphic is on the layout questionnaire (which is the layout of the previous find). Remember, only values from fields on the layout used for the find are returned to the API.
  2. The value of the Graphic field returned is not an image, but a special URL which requests the image from the Web Publishing Engine.

echo '<img src="ContainerBridge.php?path=' . urlencode($record->getField('Graphic')) . '">';

Because an HTML <img> (image) tag must have a file path as its src (source) attribute, this lesson uses a separate file to actually retrieve the image. The file that retrieves the container image is called ContainerBridge.php, and its filename appears inside the src (source) attribute of the <img> (image) tag.

The ContainerBridge.php file does not know which image you want displayed. To specify the image, you must append the Graphic field value to the end of the src (source) URL. In HTML, this is called the GET method.

Using a name/value pair, and starting with a question mark, concatenate the desired string. The name is set to "path" and the value is set to the getField() method result, passing the name of the container field (Graphic) in parenthesis.

Note - The getField() result is passed to the PHP urlencode() function to ensure that special characters are correctly encoded for a URL.

Using ContainerBridge.php

Using your text editor, open the file ContainerBridge.php in the Lesson2 folder. This simple script uses the getContainerData() FileMaker_Record method to retrieve the actual image.

For getContainerData() to work, you must pass the field results from getField() (of a container field) to the getContainerData() method in parenthesis. In home.php, the result from getField() for the Graphic field was passed through the URL. In ContainerBridge.php, the result is retrieved from the URL via the path element of the $_GET array and passed to the getContainerData() method.

echo $fm->getContainerData($_GET['path']);

The ContainerBridge.php file simple retrieves the path of the specified image from the FileMaker Pro database so that the home.php file can use it in the <img> tag to display the image in the web browser.

Note - See the FileMaker API for PHP documentation for a list of FileMaker_Record object methods.

Lesson 3

Objective

Lesson 3 covers the code required to create a dynamic web form using FileMaker layout objects. It also discusses the code required for adding a new FileMaker record from a web form submission. This lesson uses two additional PHP files: Respondent.php and handle_form.php. The Repondent.php file serves to dynamically generate a web form, while the handle_form.php file is used to validate form entries and enter them into the questionnaire.fp7 database as a new record.

Start

Open the questionnaire web site by pointing your browser to the home.php file in the Lesson3 folder. This version of the page displays a Continue button for you to start the questionnaire application. When you click the Continue button, you are redirected to the Respondent.php file. Enter your information into the web form and click Submit; retry if you did not enter enough information. When your form validates, you see the Thank You message and the information you entered is added to the questionnaire.fp7 database as a new record.

Retrieve Value List Items

To view how this application works, open the Respondent.php page in your text editor. Note that the dbaccess.php file is included near the top. As discussed in Lesson 1, this include statement ensures that you have an instance of the FileMaker database class, and that the instance can be used as the variable $fm.

Notice the Respondent.php radio button form element called "prefix". This element derives its values from the questionnaire.fp7 FileMaker Pro database by using its value list of the same name. This technique allows you to build a dynamic form element based on a value list defined in the FileMaker database. In this way, you don't have to update your PHP code every time the value list changes in the database. This technique is implemented in the following steps:

  1. Retrieve a layout object via the getLayout() method (passing the layout name in parenthesis)
  2. Retrieve the value list values via the getValueList() method
  3. Loop through the array of values and output each as a radio button
When using this technique, remember that the layout specified must contain a field which is formatted by the value list specified. If a value list is requested with the getValueList() method, and the value list has not been formatted to any field on the layout specified with getLayout(), an error will result. Here is the code which is used to display the dynamic radio buttons.

$layout =& $fm->getLayout('Respondent');
$values = $layout->getValueList('prefixes');
foreach($values as $value){
      echo '<input type= "radio" name= "prefix" value= "'. $value .'">' . $value . ' ';
}

Note - See the FileMaker API for PHP documentation for a list of FileMaker_Layout object methods.

Note - The form in Respondent.php also contains several hidden form elements. One named "active_questionnaire_id" contains the questionnaire ID from home.php. This form passes the ID into handle_form.php where it will be used in Lesson 4.

Add New Record

When the Respondent.php form has submitted the data, values are passed to the action page handle_form.php via the POST method. Using your text editor, open the handle_form.php file located in the Lesson3 folder.

Notice that the user-submitted data is assembled into an array and assigned to the variable $respondent_data. In this associative array, the Key for each element is the exact name of the FileMaker field that the data is to be posted to. The Value of each element corresponds to the values submitted from the HTML form element within the $_POST array. This $respondent_data array is used by the FileMaker object when creating the database record.

After assembling the data array, the PHP code performs some simple validation checks. These validation methods use PHP code explicitly; there is no validation performed by FileMaker Server during this operation.

After the user data passes validation, a new record can be created in two simple steps:

  1. Create a new FileMaker_Command_Add object, passing two parameters:
    • layout name (the layout must have the necessary fields on it)
    • data array ($respondent_data)
  2. Add the record with the execute() method

$newRequest =& $fm->newAddCommand('Respondent', $respondent_data);
$result = $newRequest->execute();

Remember, when creating a new FileMaker_Command_Add object, you must specify the name of the layout. The layout name determines which table occurrence is used (context) and which fields are returned (results). The fields used to enter data must be on the layout.

In Lesson 4, the handle_form.php page will be augmented to use the added record and display the first question.

Lesson 4

Objective

Lesson 4 covers the code required to retrieve a FileMaker record by its ID and retrieve related records from a portal. Portals are powerful controls used in FileMaker Pro solutions. The FileMaker API for PHP has special methods designed to work with portal data. This lesson introduces some of that functionality.

Start

Open the FileMaker Pro questionnaire.fp7 database which is hosted on FileMaker Server. Click the Edit Questionnaire button and make sure the active questionnaire has at least one record in the Question portal. Then open the Lesson4 home.php file in your web browser. Select the Continue button and enter your respondent information.

Next you are prompted with the first question of the active questionnaire. Open the FileMaker Pro questionnaire.fp7 database again. Locate the first question of the active questionnaire. Try changing the first question type. Click the Edit Answers button and add possible answers. Refresh your web browser to see the updated question.

This lesson introduces two new tasks you can perform: get a record by its ID and retrieve a set of related records from a portal.

Find Record by ID

With your text editor, open the handle_form.php file located inside the Lesson4 folder. Scroll down a third of the file to where the handle_form.php file ended in Lesson 3. Notice that this lesson adds code that requests the record object of the new respondent record. This request is necessary because the Respondent ID field is defined with the Auto Enter Serial Number option in FileMaker Pro and you need to retrieve the Auto Enter number.

As with Find functions in Lesson 1, a new record can be retrieved by using the getRecord() and getField() methods.

$records = $result->getRecords();
$record = $records[0];
$respondent_recid = $record->getField('Respondent ID');

The next task is to retrieve the active questionnaire name. To accomplish this, use the getRecordById() method of the FileMaker instance ($fm).

When using getRecordById(), pass the internal FileMaker record ID and the name of the layout. The layout determines which table occurrence (context) is used and which field values (results) are returned. The code in this page passes the active_questionnaire_id of the $_POST array sent to this file from the respondent form of Respondent.php.

$active_questionnaire_id = $_POST['active_questionnaire_id'];
$active_questionnaire = $fm->getRecordById('questionnaire',$active_questionnaire_id);
$questionnaire_name = $active_questionnaire->getField('Questionnaire Name');

Note - Every record object returned from an API operation contains the internal FileMaker record ID which can be retrieved with the getRecordId() method.

The next task is to retrieve the questionnaire records and display the first question. Search for all questions which match the active questionnaire ID. This find is performed against the Questions layout.

$findCommand =& $fm->newFindCommand('Questions');
$findCommand->addFindCriterion('Questionnaire ID', $active_questionnaire_id);
$result = $findCommand->execute();
$records = $result->getRecords();
$question = $records[0];

Get Related Set

The questionnaire database is designed so that each question has a specific type (for example, text, radio, and checkbox). If the type is for a multiple choice answer, each question can have multiple answer choices. The layout Questions contains a portal which displays the possible answers. If a question has one or more answers, the following code displays the answer choices using the "type" specified.

To explain this code, assume that the question is of type radio. Scroll down the handle_form.php document until you see the else if condition which checks for radio or ranking question types.

else if ($question_type =="radio" || $question_type =="ranking")

If the condition is true, the following code retrieves the related answer choices and displays them as radio button form elements. Answer records from the portal can be retrieved by using the getRelatedSet() method of the FileMaker_Record object.

When calling the getRelatedSet() method, the name of the related table must be passed in parenthesis and the portal defined with this relationship must be on the layout used when retrieving the $question record.

$relatedSet = $question->getRelatedSet('question_answers');

The variable $relatedSet now contains an array of record objects from the related portal. Loop through the array and output the field values for each record found.

foreach ($relatedSet as $relatedRow)
{
    $possible_answer = $relatedRow->getField('question_answers::answer');
    echo '<input type= "radio" name= "radio_answer" value= "'. $possible_answer .'">' . $possible_answer . '<br/>';
}

You could have retrieved the related records by performing a find, but it is much easier to use getRelatedSet() using a portal that already contained the related set.

Lesson 5

Objective

Lesson 5 covers the code necessary to add related records. If you have a portal defined on a layout which allows creation of related records, you can use the FileMaker API for PHP to add related records from the web.

Start

Open your web browser to the home.php page being hosted in the Lesson5 directory. Click the Continue button and complete the online survey. Open the FileMaker questionnaire.fp7 database which is hosted on FileMaker Server. From the Active Questionnaire select the Review Responses button and navigate to the last record in the table. This record contains the respondent information you entered. Each answer is saved as a record in the Responses portal.

Add Related Record (Portal Rows)

Adding portal rows with the FileMaker API for PHP can be done in four steps:

  1. Start with a valid record object
  2. Create a new blank related record
  3. Add data to the fields of the new record (optional)
  4. Commit the new record

Start with a Valid Record Object

With your text editor, open the handle_form.php file located in the Lesson5 tutorial folder. Scroll down and look for the code which retrieves the respondent record:

$respondent_rec = getRespondentRecordFromRespondentID($respondent_recid);

This code uses a function which has been added to the dbaccess.php file. If you open the dbaccess.php in your text editor, you can see this function's definition near the bottom. Inside the function definition notice that the newFindCommand() method uses the Respondent layout for its context .

$find = $fm->newFindCommand('Respondent');

This function assigns the respondent record object to the $respondent_rec variable. The variable is referenced to the layout Respondent because that layout was the context of the find command. Therefore any methods used by the $respondent_rec variable start from the context of the Respondent layout.

Create a New Blank Related Record

Going back to the handle_form.php file, the next line of code begins to create the new related record.

$new_response = $respondent_rec->newRelatedRecord('Responses');

When this line executes, the variable $new_response is assigned a blank record object (a new record has not yet been created in the FileMaker database).

It is important to understand the context of this operation. This code starts from the layout of the calling record object (Responses) and specified the relationship of a portal on that layout. Then the code passes the related table name to the newRelatedRecord() method.

Add Data to the Fields of the Blank Record (optional)

After you have a new blank record and know which portal context that the record belongs to, you can begin entering data with the setField() method. This method takes two parameters: field name and field value. Because this is a related record, the field name must be expressed with the relationship name and the field name separated by two colons.

$new_response->setField('Responses::Question ID', $cur_question);
$new_response->setField('Responses::Response', $translatedAnswer);

After you have created the new related record and have added data to the appropriate fields, you are ready to commit the entry.

Note - It is not necessary to set field data before committing a new blank record.

Commit the New Record

No new record objects are created in the FileMaker database until they have been committed. The commit() method inserts the FileMaker_Record object into the questionnaire.fp7 FileMaker database.

$result = $new_response->commit();

The $result variable is now assigned the FileMaker_Record object of the new record, and the new record has been created in the FileMaker database. If an error occurs, the variable $result contains a FileMaker_Error object. It is good practice to check for errors after executing the commit() method.

Lesson 6

Objective

Lesson 6 reviews the code necessary for displaying related fields from a portal. It also introduces the basic instructions for using Cascading Style Sheets (CSS) to modify the appearance of your web application.

Start

Open your web browser to the home.php page hosted in the Lesson6 directory. Notice the new look of the site. This formatting comes from a separate CSS page. CSS styles can be used to format HTML code used in your web application and are discussed at the end of this lesson.

Click the Continue button and complete the online survey. Notice that the thankyou.php page displays a summary of the questions you answered. These questions and responses are from a portal on the Respondent layout in the questionnaire.fp7 database. If a FileMaker layout contains portal data, it can be displayed on the web using the FileMaker API for PHP.

Get Related Sets

Using your text editor, open the thankyou.php page which is located in the Lesson6 directory. Scroll to the end of the file and locate the last HTML table.

Notice the code above the table which retrieves the respondent record.

$respondent_record = getRespondentRecordFromRespondentID($respondent_recid);

The getRespondentRecordFromRespondentID() function is defined in the dbaccess.php page. Its context is the Respondent layout in the questionnaire.fp7 database.

Looking inside the HTML table, note that the $respondent_record variable is used to retrieve the set of related records. This is accomplished by using the getRelatedSet() method. To use the getRelatedSet() method, you must specify the related table name of the desired portal and the desired portal must be on the Respondent layout.

$response_related_set = $respondent_record->getRelatedSet('Responses');

The above code assigns an array which contains the records from the portal Responses to the variable $response_related_set. Each response is a FileMaker_Record object. This code uses the getField() method of the FileMaker_Record object to output the portal rows in an HTML table. Remember to use the full name of the related table and field name separated by two colons when you output related fields.

Here is the loop which displays the related set in HTML.

foreach ($response_related_set as $response_related_row)

{

     $question = $response_related_row->getField('Questions 2::question');

     $answer = $response_related_row->getField('Responses::Response');
     //converts any line returns in the answer to commas
     $answer = str_replace("\n",", ",$answer);
     echo '<tr><td>' . $question . '</td>';
     echo '<td>' . $answer . '</td></tr>';

}

Formatting with CSS

You can format your web applications using Cascading Style Sheets (CSS). With your text editor, open the style.css file located inside the Lesson6 folder and review the styles defined for some of the HTML tags. CSS styles can be applied to any HTML tag, allowing you to format multiple items on multiple pages from a single definition.

To apply formatting to a specific HTML tag, you must declare the tag name. Following the tag name, you must state the style attributes enclosed in curly braces. As in PHP, each statement must be terminated by a semi-colon.

body {
    background-color: #333333;
    padding: 20px;
    color: #ffffff;
    font-family:Verdana, Arial, Helvetica, sans-serif;
}

After you have created a CSS file, you can apply it to any HTML or PHP document. To apply external styles, you must include or link the style sheet to your document: use the <link> (link) tag in the header of your HTML output.

With your text editor, open the thankyou.php file located in the Lesson6 folder. Inside the header tags, notice the <link> (link) tag which tells the web browser to apply the style.css formatting. When using the <link> tag, be sure to supply the correct path or href to your CSS page.

<link rel="stylesheet" type="text/css" href="style.css" />

Style sheets can be used in multiple applications and each application can use multiple style sheets. For more information on CSS styles and their attributes visit the CSS2 reference at W3Schools.