Preparation and Environment Setup
Before we can begin integrating the Google Photos API, we need to complete some necessary preparatory work, including installing dependencies and configuring authentication information.
Install google-api-php-client
google-api-php-client is a PHP client library officially provided by Google. It encapsulates the details of interacting with various Google APIs, greatly simplifying the development process. This library can be installed using Composer, a PHP dependency management tool that allows for easy management of project dependencies.
Open a terminal, navigate to your project directory, and execute the following command to install the google-api-php-client:
composer require google/apiclient:^2.15
This command will download and install the latest version of the google-api-php-client library and its dependencies from the Composer repository. After installation, Composer will automatically generate a vendordirectory containing all the installed library files, as well as a vendor/autoload.phpfile for automatically loading these libraries.
Obtain OAuth 2.0 credentials
To use the Google Photos API, we need to authenticate via OAuth 2.0. OAuth 2.0 is an industry-standard authorization protocol that allows third-party applications to access a user’s resources without obtaining the user’s account password. Below are the steps to obtain OAuth 2.0 credentials:
- Visit the Google Cloud Console . If you don’t have a Google Cloud account yet, please register and create a new project.
- In the project dashboard, click “APIs & Services” > “Credentials”.
- Click “Create Credentials” > “OAuth client ID”。
- Select “Web application” as the application type and enter a name (e.g., “Google Photos PHP App”).
- In the “Authorized redirect URIs” section, add your application’s redirect URI, for example
http://localhost:8080/callback.php. This URI will be used later in the authentication process; it’s the page Google will redirect to after the user authorizes the application. - Click “Create”, download the credential JSON file (usually named
client_secret_*.json), and save it to the project directory. It is recommended to rename it forcredentials.jsoneasy reference later.
The official documentation provides a more detailed explanation of the authentication process; you can refer to docs/auth.md for more information.
Authentication process implementation
Authentication is the first step in using the Google Photos API. Only after successful authentication can our application gain permission to access users’ Google Photos resources. Below, we will implement the complete OAuth 2.0 authentication process.
Initialize client
First, we need to create a Google Client instance and configure the authentication information. The code is as follows:
require __DIR__ . '/vendor/autoload.php';
$client = new Google\Client();
$client->setAuthConfig('credentials.json');
$client->setRedirectUri('http://localhost:8080/callback.php');
$client->addScope("https://www.googleapis.com/auth/photoslibrary");
$client->addScope("https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata");
In this code, we first require __DIR__ . '/vendor/autoload.php'load the autoload file automatically generated by Composer, allowing us to use classes from the google-api-php-client library. Then, we create an Google\Clientinstance and setAuthConfigset the path to the previously downloaded credential file using a method. setRedirectUriThe method sets the redirect URI, which must match the one configured in the Google Cloud Console. addScopeThe method adds the necessary permissions to access the Google Photos API, https://www.googleapis.com/auth/photoslibraryallowing reading and writing to the user’s media library and https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddatareading data created by the application.
Generate authentication URL
Next, we need to generate an authentication URL that users access to authorize our application to access their Google Photos resources. The code is as follows:
if (!isset($_SESSION['access_token'])) {
$authUrl = $client->createAuthUrl();
echo '<a href="' . filter_var($authUrl, FILTER_SANITIZE_URL) . '">授权访问Google Photos</a>';
}
In this code, we first check if an access token exists in the session. access_tokenIf it does not exist, we call createAuthUrla method to generate an authentication URL and output a link. When the user clicks this link, they will be redirected to Google’s authorization page.
Handling authorization callbacks
After the user agrees to authorization on the authorization page, Google will redirect the user to the redirect URI we set earlier, attaching an authorization code to the URL. We need to process this authorization code on the page corresponding to the redirect URI and exchange it for an access token. The code is as follows callback.php:
require __DIR__ . '/vendor/autoload.php';
session_start();
$client = new Google\Client();
$client->setAuthConfig('credentials.json');
$client->setRedirectUri('http://localhost:8080/callback.php');
$client->addScope("https://www.googleapis.com/auth/photoslibrary");
$client->addScope("https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata");
if (!isset($_GET['code'])) {
// If no authorization code is found, redirect to the authentication page
header('Location: index.php');
exit;
}
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
$client->setAccessToken($token);
// Store the access token in the session
$_SESSION['access_token'] = $token;
// Redirect back to the application homepage
header('Location: index.php');
exit;
In this code snippet, we first start a session session_start()to store the access token. Then, we create an Google\Clientinstance and configure it as before. Next, we check if an authorization code ( codeparameter) exists in the URL; if not, we redirect the user to the application’s home page. If an authorization code exists, we call fetchAccessTokenWithAuthCodea method to exchange it for an access token. After obtaining the access token, we call setAccessTokena method to set the access token and store it in the session. Finally, we redirect the user back to the application’s home page.
Media file upload
After authentication, we can use the Google Photos API to manage users’ media libraries. Below, we’ll first implement the media file upload functionality, including simple file uploads and large file chunk uploads.
Simple file upload
For smaller media files (typically less than 5MB), we can use a simple upload method. Below is a sample code for a simple file upload:
session_start();
require __DIR__ . '/vendor/autoload.php';
$client = new Google\Client();
$client->setAuthConfig('credentials.json');
$client->setAccessToken($_SESSION['access_token']);
$service = new Google\Service\PhotosLibrary($client);
$filePath = 'test.jpg';
$fileName = 'My Photo.jpg';
$media = new Google\Service\PhotosLibrary\NewMediaItem();
$simpleMediaItem = new Google\Service\PhotosLibrary\SimpleMediaItem();
$uploadToken = new Google\Service\PhotosLibrary\UploadToken();
// Read file content and perform Base64 encoding
$fileContent = file_get_contents($filePath);
$uploadToken->setUploadToken(base64_encode($fileContent));
$simpleMediaItem->setUploadToken($uploadToken);
$simpleMediaItem->setFileName($fileName);
$media->setSimpleMediaItem($simpleMediaItem);
$newMediaItems = new Google\Service\PhotosLibrary\NewMediaItems();
$newMediaItems->setNewMediaItems([$media]);
try {
$response = $service->mediaItems->batchCreate($newMediaItems);
echo 'File upload successful, media item ID:' . $response->getNewMediaItemResults()[0]->getMediaItem()->getId();
} catch (Exception $e) {
echo 'Upload failed:' . $e->getMessage();
}
In this code snippet, we first start a session, load the autoload file, create and configure a Google Client instance, and set the access token in the session. Then, we create an Google\Service\PhotosLibraryinstance that will interact with the Google Photos API. Next, we specify the file path and filename to upload. Then, we create ` <file> NewMediaItem`, `<memory>`, SimpleMediaItemand UploadToken`<file>` objects to construct the upload request. We read the file content, Base64 encode it, and set it into UploadTokenthe `<file>` object. We UploadTokenset the `<memory>` object into SimpleMediaItemthe `<memory>` object, and then SimpleMediaItemset the `<memory>` object into NewMediaItemthe `<memory>` object. We create NewMediaItemsthe `<memory>` object and add the media items to be uploaded to it. Finally, we call mediaItems->batchCreatethe method to upload the file and process the response.
It’s important to note that the Google Photos API’s simple upload method requires file content to be Base64 encoded, which may differ from some other APIs.
Large file chunked upload
For large media files (greater than 5MB), using the simple upload method may encounter network problems or server limitations. In this case, we can use the chunked upload method. Chunked upload divides the large file into multiple smaller chunks, uploads them one by one, and then merges these smaller chunks into a complete file after the upload is complete.
The google-api-php-client library provides Google\Http\MediaFileUploadclasses to simplify the implementation of chunked uploads. Although these classes are primarily designed for the Drive API, they can also be used for chunked uploads with the Google Photos API. Below is sample code for a large file chunked upload; you can refer to the implementation ideas in examples/large-file-upload.php :
session_start();
require __DIR__ . '/vendor/autoload.php';
$client = new Google\Client();
$client->setAuthConfig('credentials.json');
$client->setAccessToken($_SESSION['access_token']);
$client->setDefer(true);
$service = new Google\Service\PhotosLibrary($client);
$filePath = 'large_video.mp4';
$chunkSizeBytes = 5 * 1024 * 1024; // 5MB per chunk
$file = new Google\Service\PhotosLibrary\NewMediaItem();
$simpleMediaItem = new Google\Service\PhotosLibrary\SimpleMediaItem();
$uploadToken = new Google\Service\PhotosLibrary\UploadToken();
// Here we need to get the upload session URL first, please refer to the Google Photos API documentation for details
// The following is a general process of chunked upload, the actual implementation needs to be adjusted according to the API documentation
$handle = fopen($filePath, 'rb');
$media = new Google\Http\MediaFileUpload(
$client,
$request, // This needs to be a request to create an upload session
'video/mp4',
null,
true,
$chunkSizeBytes
);
$media->setFileSize(filesize($filePath));
$status = false;
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
if ($status) {
$uploadToken->setUploadToken($status->getUploadToken());
$simpleMediaItem->setUploadToken($uploadToken);
$file->setSimpleMediaItem($simpleMediaItem);
$newMediaItems = new Google\Service\PhotosLibrary\NewMediaItems();
$newMediaItems->setNewMediaItems([$file]);
$response = $service->mediaItems->batchCreate($newMediaItems);
echo 'Large file uploaded successfully, media item ID:' . $response->getNewMediaItemResults()[0]->getMediaItem()->getId();
}
It’s important to note that the chunked upload process of the Google Photos API is relatively complex. It requires first creating an upload session, obtaining the upload URL, then uploading the file content in chunks, and finally submitting the upload session. The code above is just a general example of the process; for actual implementation, please refer to the official Google Photos API documentation .
Get media library content
Besides uploading files, we often need to retrieve content from the user’s media library, such as the album list or media item list. Below, we’ll implement these functions.
Get Media Item List
To retrieve a list of media items in a user’s media library, we can use mediaItems->searchthe following method: The code is as follows:
session_start();
require __DIR__ . '/vendor/autoload.php';
$client = new Google\Client();
$client->setAuthConfig('credentials.json');
$client->setAccessToken($_SESSION['access_token']);
$service = new Google\Service\PhotosLibrary($client);
$searchParams = new Google\Service\PhotosLibrary\SearchMediaItemsRequest();
$searchParams->setPageSize(10); // Return 10 media items per page
try {
$response = $service->mediaItems->search($searchParams);
$mediaItems = $response->getMediaItems();
if (!empty($mediaItems)) {
echo '<h2>Media item list</h2>';
echo '<ul>';
foreach ($mediaItems as $item) {
echo '<li>';
echo 'ID: ' . $item->getId() . '<br>';
echo 'Name: ' . $item->getFilename() . '<br>';
echo 'URL: <img src="' . $item->getBaseUrl() . '=w200" alt="' . $item->getFilename() . '">';
echo '</li>';
}
echo '</ul>';
} else {
echo 'No media item in the media library.';
}
} catch (Exception $e) {
echo 'Failed to retrieve media item:' . $e->getMessage();
}
In this code, we first create an SearchMediaItemsRequestobject and set the number of media items returned per page setPageSize(10). Then, we call mediaItems->searcha method to get the list of media items. If there are media items in the returned result, we iterate through and output the ID, name, and thumbnail URL of each media item. getBaseUrl()The method returns the base URL of the media item, and we can add parameters to the URL to specify the size of the thumbnail, for example, =w200to indicate a width of 200 pixels.
Get album list
To retrieve a user’s photo album list, you can use albums->listAlbumsthe following method. The code is as follows:
$albums = $service->albums->listAlbums(['pageSize' => 10]);
if (!empty($albums->getAlbums())) {
echo '<h2>Album List</h2>';
echo '<ul>';
foreach ($albums->getAlbums() as $album) {
echo '<li>';
echo 'Album Name: ' . $album->getTitle() . '<br>';
echo 'Number of Media Items: ' . $album->getMediaItemsCount() . '<br>';
if ($album->getCoverPhotoBaseUrl()) {
echo 'Cover Image: <img src="' . $album->getCoverPhotoBaseUrl() . '=w200" alt="' . $album->getTitle() . '">';
}
echo '</li>';
}
echo '</ul>';
} else {
echo 'No album found.';
}
In this code, we call albums->listAlbumsa method to get a list of albums, ['pageSize' => 10]specifying that 10 albums should be returned per page. Then we iterate through the album list and output the name, number of media items, and cover image (if any) for each album.
Error handling and best practices
When interacting with the Google Photos API, you may encounter various errors, such as network errors, authentication errors, and insufficient permissions. Good error handling can improve application stability and user experience. At the same time, following best practices can make our applications more efficient and reliable.
Error handling
The google-api-php-client library throws various exceptions. We can use try-catch blocks to catch these exceptions and handle them accordingly. For example:
try {
// Code to call the Google Photos API
} catch (Google\Service\Exception $e) {
// Handle API errors, such as outputting error codes and error messages
echo 'API Error: ' . $e->getCode() . ' - ' . $e->getMessage();
// Different handling can be performed based on the error code, for example, 401 indicates unauthorized, requiring re-authentication
if ($e->getCode() == 401) {
unset($_SESSION['access_token']);
header('Location: index.php');
exit;
}
} catch (Google\Exception $e) {
// Handle client errors
echo 'Client Error: ' . $e->getMessage();
} catch (Exception $e) {
// Handle other general errors
echo 'Error: ' . $e->getMessage();
}
In this code, we use multiple catch blocks to catch different types of exceptions. Google\Service\ExceptionThe first is an exception thrown when an API call returns an error; we can getCodeget the error code and getMessagethe error message through the `getError` method. For example, when the error code is 401, it means the access token is invalid or expired. In this case, we can clear the access token in the session and redirect to the authentication page, requiring the user to re-authorize. The Google\Exceptionsecond is an error on the client side, such as a configuration error. The last catch block is used to catch other unforeseen exceptions.
Best Practices
- Caching Access Tokens : Access tokens typically expire after 3600 seconds (1 hour). Before they expire, we can cache them to avoid frequent authentication processes. The google-api-php-client library provides token storage functionality, allowing you to store tokens in a session, file, or database. For example, storing tokens in a file:
$client->setAccessToken(file_get_contents('token.json'));
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents('token.json', json_encode($client->getAccessToken()));
}
- Limiting Request Frequency : The Google Photos API has a request frequency limit. To avoid triggering this limit, we should reasonably control the frequency of API requests. This can be
sleepachieved using a delay (function) or by implementing a request queue. - Handling large file uploads : For large file uploads, it is essential to use the chunked upload method and implement the resume function to cope with network interruptions.
- Use appropriate permission scopes : Only request the permissions necessary for your application, following the principle of least privilege. For example, if your application only needs to read the media library, it should only request
https://www.googleapis.com/auth/photoslibrary.readonlythe required permissions. - Monitor API usage : You can monitor API usage in the Google Cloud Console, including the number of requests, error rate, etc. Monitoring allows you to identify problems and optimize them in a timely manner.