PHP Web Services with File I/O
Building and using a PHP JSON API
Q: What is the one thing that PHP does well that JavaScript isn't well known for?
File processing
Q: From the client perspective, what is an advantage of JSON over plain text?
Easier to parse structured data, less error prone than using/managing plain text
Recall: What are the functions to do PHP file I/O?
function name(s) | category |
---|---|
file, file_get_contents, file_put_contents | reading/writing entire files |
basename, file_exists, filesize, fileperms, filemtime, is_dir, is_readable, is_writable, disk_free_space | asking for information |
copy, rename, unlink, chmod, chgrp, chown, mkdir, rmdir | manipulating files and directories |
glob, scandir | reading directories |
For our Points of Interest API on Wednesday (pointsofinterest.php
), we had the goal of supporting 3 different GET requests:
Each requires a way to associate city names and their Points of Interest. We use 2 methods to create these associative arrays:
get_list()
hard-code the $attractions
array.get_list_from_file()
used file processing to read cities.txt and create the $attractions
array.get_list()
)function get_list() {
$attractions = array("Seattle" => "Space Needle",
"New York" => "Ellis Island",
"Boston" => "Boston Harbor",
"Philadelphia" => "Valley Forge",
"Detroit" => "The Henry Ford Museum",
"Paris" => "Eiffel Tower",
"Vancouver BC" => "Stanley Park",
"Tokyo" => "Mt. Fuji",
"Beijing" => "Great Wall",
"London" => "Big Ben");
return $attractions;
}
PHP
get_list_from_file()
)
We used file processing to generalize our get_list()
function
to generate the associative array based on the contents in our cities.txt
:
Seattle, Space Needle
New York, Ellis Island
Boston, Boston Harbor
Philadelphia, Valley Forge
Detroit, The Henry Ford Museum
Paris, Eiffel Tower
...
Beijing, Great Wall
London, Big Ben
cities.txt
function get_list_from_file() {
$contents = file("cities.txt", FILE_IGNORE_NEW_LINES);
$attractions = array();
foreach ($contents as $line) {
$parts = explode(",", $line);
$city = $parts[0];
$attraction = $parts[1];
# could also do:
# list($city, $attraction) = explode(",", $line);
# e.g. { "Seattle" => "Space Needle" }
$attractions[$city] = $attraction;
}
return $attractions;
}
PHP
city={cityname}
(text)http://example.com/pointsofinterest.php?city=Seattle
GET request
The best place to visit in Seattle is Space Needle.
Output
city=all
(JSON){
"Seattle": " Space Needle",
"New York": " Ellis Island",
"Boston": " Boston Harbor",
"Philadelphia": " Valley Forge",
"Detroit": " The Henry Ford Museum",
"Paris": " Eiffel Tower",
"Vancouver BC": " Stanley Park",
"Tokyo": " Mt. Fuji",
"San Francisco": " Fisherman's Terminal",
"Beijing": " Great Wall",
"London": " Big Ben"
}
JSON
For both solutions, we left off with each value of the array being the name of the site. But how can we add more information for each site?
Recall that for each POI in a city, we eventually wanted:
A general (improved) JSON format of the pointsofinterest.php?city=all
request:
This information is much more nicely structured with JSON! But we don't have the image/review information from cities.txt...
{
"cities" : [
{
"name": "Seattle",
"sites": [
{
"name": "Space Needle",
"image": "....",
"review": ".... "
}
]
},
{
"name": "New York",
"sites": [
{
"name": "Ellis Island",
"image": "....",
"review": ".... "
},
{
"name": "Statue of Liberty",
"image": "....",
"review": ".... "
}
]
}
...
]
}
JSON
From Yesterday: What are the PHP functions that can get information from directories on the server?
Suppose we store information about each Point of Interest in a file in a city subdirectory.
The name of the file is the name of the Point of Interest (e.g. "Space_Needle.txt")
Each file contains 2 lines:
glob
vs. scandir
Exercise: City NamesHow would you get an array of all city directory names?
$all_folders = scandir("cities/");
$cities = array_diff($all_folders, array(".", ".."));
Or alternatively...
$full_paths = glob("cities/*");
$cities = array();
foreach ($full_paths as $path) {
array_push($cities, basename($path));
}
PHP
How could you get the name, image url, and review (as an associative array) for a path to a POI file?
Example: for "cities/Seattle/Space_Needle"
, return
{"name":"Space Needle", "image":"...", "review":"..." }
(abbreviated)
function get_info_from_file($file_path) {
# Remember you can use list to assign variables quickly when you know
# how many parts there are in an array (each POI file has two lines)
list($image, $review) = file($file_path, FILE_IGNORE_NEW_LINES);
# e.g. get "Space Needle" from
# "cities/Seattle/Space_Needle" POI file path
$name = str_replace("_", " ", basename($file_path));
return array("name" => $name,
"image" => $image,
"review" => $review);
}
PHP
function get_all_data() {
/* Get all of the cities in the cities directory */
$cities = glob("cities/*");
$output = array();
foreach ($cities as $city) {
// Now get the POIs for each city (here, $city still has the full file path)
$poi_files = glob($city . "/*");
$pois = array();
foreach ($poi_files as $poi_file) {
// From the previous slide!
$poi_data = get_info_from_file($poi_file);
array_push($pois, $poi_data);
}
// Create the associative array for the city with the city name and its POI sites.
$city_info = array();
$city_info["name"] = str_replace("_", " ", basename($city));
$city_info["sites"] = $pois;
// Add this city data to our output array
array_push($output, $city_info);
}
/* Final step!!! Don't forget the last association for our JSON!!! */
return array("cities" => $output);
}
PHP
This version gives us the JSON we wanted!
poi-v3.php
A complete pointsofinterest.zip example, including our front-end using the web service previewed on Wednesday!