0

I am trying to get the Google Cloud Translation API's PHP implementation to work on a Raspberry Pi 3 B+ running Stretch and Nginx with PHP7-FPM.

I have created an account at Google and received the API key as a .json file. I have also setup composer and the Google client libraries.

According to Google's instructions here one has to set an environment variable like this (I did this in the terminal and logged in as user pi):

export GOOGLE_APPLICATION_CREDENTIALS="/var/www/html/test/google-key.json"

In my case this does not work or make any difference. My PHP script will not find the API key file and therefore not execute. However if I enter this same line to the end of the /etc/profile (and reboot) the Python implementation starts working but PHP still doesn't.

Error message when executing the PHP script:

Fatal error: Uncaught Google\Cloud\Core\Exception\ServiceException: { "error": { "code": 403, "message": "The request is missing a valid API key.", "errors": [ { "message": "The request is missing a valid API key.", "domain": "global", "reason": "forbidden" } ], "status": "PERMISSION_DENIED" } } in /var/www/html/test/vendor/google/cloud-core/src/RequestWrapper.php:336 Stack trace: #0 /var/www/html/test/vendor/google/cloud-core/src/RequestWrapper.php(189): Google\Cloud\Core\RequestWrapper->convertToGoogleException(Object(GuzzleHttp\Exception\ClientException)) #1 /var/www/html/test/vendor/google/cloud-core/src/RestTrait.php(95): Google\Cloud\Core\RequestWrapper->send(Object(GuzzleHttp\Psr7\Request), Array) #2 /var/www/html/test/vendor/google/cloud-translate/src/Connection/Rest.php(78): Google\Cloud\Translate\Connection\Rest->send('translations', 'translate', Array) #3 /var/www/html/test/vendor/google/cloud-translate/src/TranslateClient.php(246): Google\Cloud\ in /var/www/html/test/vendor/google/cloud-core/src/RequestWrapper.php on line 336

If I then insert the environment variable directly into the PHP script like this:

putenv('GOOGLE_APPLICATION_CREDENTIALS="/var/www/html/test/google-key.json"');

Error becomes:

Fatal error: Uncaught DomainException: Unable to read the credential file specified by GOOGLE_APPLICATION_CREDENTIALS: file "/var/www/html/test/google-key.json" does not exist in /var/www/html/test/vendor/google/auth/src/CredentialsLoader.php:74 Stack trace: #0 /var/www/html/test/vendor/google/cloud-core/src/ClientTrait.php(151): Google\Auth\CredentialsLoader::fromEnv() #1 /var/www/html/test/vendor/google/cloud-core/src/ClientTrait.php(99): Google\Cloud\Translate\TranslateClient->getKeyFile(Array) #2 /var/www/html/test/vendor/google/cloud-translate/src/TranslateClient.php(129): Google\Cloud\Translate\TranslateClient->configureAuthentication(Array) #3 /var/www/html/test/test.php(20): Google\Cloud\Translate\TranslateClient->__construct(Array) #4 {main} thrown in /var/www/html/test/vendor/google/auth/src/CredentialsLoader.php on line 74

Now PHP can apparently find the file but still not access it.

Composer and Google's scripts refer to DIR so I wanted to make sure that it is at least ok. To confirm things:

echo __DIR__;
Gives this as answer:
/var/www/html/test

This path seems to be ok at least.

Also the vendor directory with all the Google scripts resides inside this directory.

I believe the directory and file permissions are ok and I have even tested by making them chmod 777.

I am confused and wonder where the problem is.

  1. Why does not PHP see the environment variable?
  2. Why does the putenv line in the code still produce an error?
  3. Why does the Python implementation work?

My PHP script is basically the same that Google has in their quick start tutorial:

<?php
// Optional putenv line I added (best if not needed)
putenv('GOOGLE_APPLICATION_CREDENTIALS="/var/www/html/test/google-key.json"');
// Error reporting for for debugging
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// Optional check
//echo __DIR__;

require __DIR__ . '/vendor/autoload.php';

use Google\Cloud\Translate\TranslateClient;

$projectId = 'my-project-123456';

$translate = new TranslateClient([
  'projectId' => $projectId
]);

// I don't know if the code works beyond this point as it exits with errors before 

$text = 'Fish';
$target = 'es';

$translation = $translate->translate($text, [
  'target' => $target,
]);

echo 'Text: ' . $text . 'Translation: ' . $translation['text'];

?>

I hope to get this working and to avoid having to make a workaround in which a Python script is called from a PHP script...

  • 1
    I don't see the problem with Raspberry Pi. This is a general programming question. – Ingo Jan 27 at 21:37
  • My apologies but I wasn't sure if this was a Raspbian related issue. – Wasabi5000 Jan 28 at 0:03
1

1. Why does not PHP see the environment variable?

It seams that PHP-FPM cleans the environment variables for security reasons. You can check that by running the phpinfo(); command and searching the environment variables.

First find your PHP-FPM pool config file. Try /etc/php/7.0/fpm/pool.d/www.conf but yours could be in other place or have a different name.

Find this line and uncomment it (remove the ‘;’):

;clear_env = no

Source tomahock's article Passing system environment variables to PHP-FPM when using NGINX


2. Why does the putenv line in the code still produce an error?

This can be easily missed but the " (quotes) cause the problem.

Try printing it

echo getenv('GOOGLE_APPLICATION_CREDENTIALS');

this will be printed (with the quotes)

"/var/www/html/test/google-key.json"

So the correct way to declare it would be

putenv('GOOGLE_APPLICATION_CREDENTIALS=/var/www/html/test/google-key.json');

3. Why does the Python implementation work?

I think now you can answer this yourself now. (because it can access the environment variable, which, by the way, does not have inside the string quotes)


Tip: Sometimes the best way to debug something is to print it and see what is wrong with it.

  • Thank you so much for your clear and structured answer! I modified the PHP-FPM conf file and removed quotes from the putenv line. My script works now. Fantastic! Google's own code example uses quotes and that threw me off. I will do more tests but both PHP and Python implementations are fine now. Thanks again. – Wasabi5000 Jan 28 at 0:37

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.