欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  php教程

Laravel 4 on Google AppEngine for PHP by Gilles Me

程序员文章站 2022-04-25 12:11:49
...

FROM:http://blog.neoxia.com/laravel-4-on-google-appengine-for-php/ While Google App Engine opens to the PHP world and that the 4th version of the Laravel framework is officialy launched, we wanted at Neoxia test together these two promisin

Laravel 4 on Google AppEngine for PHP by Gilles Me

FROM:http://blog.neoxia.com/laravel-4-on-google-appengine-for-php/

While Google App Engine opens to the PHP world and that the 4th version of the Laravel framework is officialy launched, we wanted at Neoxia test together these two promising technologies.

This blog post is the result of our testing whose goal was to have up and running a standard Laravel 4 application on the Google App Engine PHP runtime.
Given that an application without a database is not very useful, we also tested the Google Cloud SQL service which is the Google flavour of the MySQL database in the cloud.

This blog is not a tutorial nor for?Google AppEngine, nor for?Laravel 4, and we invite you to consult if needed their respective documentation.

Install App Engine for PHP and Laravel 4

To download and install App Engine and the Laravel 4 framework, please check the following documentation.

  • Install Google App Engine for PHP,
  • Install Laravel 4.

With these two components, you will be able to follow the different steps of this blog post and to run tests on your local environment.

First attempts

At first, we will create a new Laravel 4 application.

composer create-project laravel/laravel

To allow an application to run on App Engine, we have to add an?app.yaml?file in the root directory of the application.

app.yaml

application: gae-laravel4-demo
version: 1
runtime: php
api_version: 1
handlers:
- url: /favicon\.ico
  static_files: public/favicon.ico
  upload: public/favicon\.ico
- url: /.*
  script: public/index.php

In our case, the application name is?gae-laravel4-demo, but you need to change it by the one you have chosen for your application before uploading it.

After this first configuration step, we can launch the application by using the Web server included in the App Engine SDK. You can test the application at the url?http://localhost:8080.
In our environment, the command to launch the application is given below. You need to adapt it to your own environement.

../google_appengine/dev_appserver.py --php_executable_path=/usr/local/opt/php54/bin/php-cgi .

At this stage, the application seems running perfectly !
Actually, we can see the Laravel 4 default page … take note that the famous “Hello world !” message has disappeared !

Laravel 4 on Google AppEngine for PHP by Gilles Me

When we got this first result, we have been quite impressed by the ease with which a framework such Laravel could run on App Engine with little change.
Unfortunately, like the rest of this blog will show, this was just an optical illusion.

First upload to Google App Engine

If you don’t have done it before, we invite you to create an App Engine application (https://appengine.google.com/) and to subscribe to the App Engine for PHP beta program (https://gaeforphp.appspot.com/) in order to allow the upload of a PHP application to your App Engine instance. Indeed, the PHP runtime that has been announced at the last Google I/O conference is still in beta and Google authorize progressively its roll out.

We then upload the application to App Engine using the following command that you need to adapt to your environment.

../google_appengine/appcfg.py update -R --runtime=php ./

When we try to access the application through the?gae-laravel4-demo.appspot.com?url, an error 500 is returned.
An analysis of the App Engine logs gives us the cause of the error. The PHP?gethostname()?function is unknown.
This error is unexpected because the?gethostname()?function is available since PHP 5.3 and the PHP runtime of App Engine is based on version 5.4. In addition, we haven’t found anything in the App Engine for PHP documentation indicating that this function had been disabled.

Never mind, to work around this error, it is simply needed to provide an implementation of the?gethostname()?function, what we have done by editing?app/bootstrap/start.php.

The logs analysis gives us another information concerning the?php_sapi_name()?function which is not allowed by default.

In order to authorize this function, as well as other PHP functions that would be disabled by default in the App Engine PHP runtime, you need to add a?php.ini?file in the root directory of your application in which you list the functions to be activated. Take note that we also activate the?php_uname()?function which is used in our implementation of the?gethostname()function.

php.ini

; enable function that are disabled by default in the App Engine PHP runtime
google_app_engine.enable_functions = "php_sapi_name, php_uname"

The mcrypt PHP extension

After these first changes, we have uploaded our application to App Engine and have tried to access the application url.
This time, the error 500 has disappeared, but we got a web page with the following message :

“Laravel requires the Mcrypt PHP extension.”

In fact, the Laravel 4 encryption module is based on the?mcrypt?PHP extension which is not available in the App Engine PHP runtime and when the Laravel 4 framework starts, it checks the presence of the?mcrypt?extension and dies if it is not available.

A solution is to replace the?Illuminate\Encryption?package which uses the?mcrypt?extension by the?neoxia\laravel-openssl-encryption?package, created by Neoxia, and which uses the?openssl?PHP extension which is available in the App Engine PHP runtime.

Here is the installation process of this package.

You need to add the?neoxia\laravel-openssl-encryption?package to the?composer.json?file located in the root directory of your application.

"require": {
    "laravel/framework": "4.0.*",
    "neoxia/laravel-openssl-encryption": "1.0.*"
},

Then, you need to execute again the?composer update?command.

You also need to update the?app/config/app.php?file as shown below.

'providers' => array(
    ...
    //'Illuminate\Encryption\EncryptionServiceProvider',
    'Neoxia\LaravelOpensslEncryption\LaravelOpensslEncryptionServiceProvider',
    ...

Finally, it is needed to remove the test which is performed by Laravel about the availability of the?mcrypt?extension.
Unfortunately, this test is performed at the heart of the framework startup process and it is needed to slightly update thestart.php?file located in the?vendor\laravel\framework\src\Illuminate\Foundation directory.

/*
|--------------------------------------------------------------------------
| Check Extensions
|--------------------------------------------------------------------------
|
| Laravel requires a few extensions to function. Here we will check the
| loaded extensions to make sure they are present. If not we'll just
| bail from here. Otherwise, Composer will crazily fall back code.
|
*/
if ( ! ( extension_loaded('mcrypt') or extension_loaded('openssl') ) )
{
    die('Laravel requires one of the Mcrypt or Openssl PHP extension.'.PHP_EOL);
    exit(1);
}

Note : during an update of the Laravel framework by using the?composer update?command, the modified?start.php?file will be reset to its default content. Thus, it will be necessary to update again the?start.php?file after any framework update and before any upload to App Engine.

After these last updates, we have uploaded the application to App Engine and have tried to access the application url.
The error relative to lack of the?mcrypt?extension has disappeared, but an exception has been thrown that indicates that it is forbidden to write on the App Engine file system.

The Laravel 4 logger

Laravel 4 uses the?Monolog?package to log the errors and the other user messages.
By default, the Monolog?RotatingFileHandler?handler is used to create daily log files on the file system. However, on App Engine, it is forbidden to write on the file system and we have to use instead the?syslog()?PHP function.

Here,?Monolog?is going to be a great help, because it includes the?SyslogHandler?handler that we will use by updating theapp/start/global.php?file as follow.

app/start/global.php

/*
|--------------------------------------------------------------------------
| Application Error Logger
|--------------------------------------------------------------------------
|
| Here we will configure the error logger setup for the application which
| is built on top of the wonderful Monolog library. By default we will
| build a rotating log file setup which creates a new file each day.
|
*/
// we comment the default file logger
//$logFile = 'log-'.php_sapi_name().'.txt';
//Log::useDailyFiles(storage_path().'/logs/'.$logFile);
/*
    Replace the default Log file handler by the syslog handler to be 
used in the google appengine environment
*/
$monolog = Log::getMonolog();
$monolog->pushHandler(new SyslogHandler('intranet', 'user', Logger::DEBUG, false, LOG_PID));

Laravel 4 session and cache managers

By default, Laravel 4 records the values in session by writing them in files, which is forbidden by App Engine.
To fix this issue, you need to use the session manager based on?Memcached?included in the Laravel 4 framework.
To do this, just update the?app/config/session.php?file as follow.

app/config/session.php

/*
|--------------------------------------------------------------------------
| Default Session Driver
|--------------------------------------------------------------------------
|
| This option controls the default session "driver" that will be used on
| requests. By default, we will use the lightweight native driver but
| you may specify any of the other wonderful drivers provided here.
|
| Supported: "native", "cookie", "database", "apc",
|            "memcached", "redis", "array"
|
*/
'driver' => 'memcached',

The same way, the default Laravel 4 cache manager uses the file system to record the values stored in the cache.
Again, it is needed to use the cache manager based on?Memcached?included in the Laravel 4 framework.
To do this, just update the?app/config/cache.php?file as follow.

app/config/cache.php

/*
|--------------------------------------------------------------------------
| Default Cache Driver
|--------------------------------------------------------------------------
|
| This option controls the default cache "driver" that will be used when
| using the Caching library. Of course, you may use other drivers any
| time you wish. This is the default when another is not specified.
|
| Supported: "file", "database", "apc", "memcached", "redis", "array"
|
*/
'driver' => 'memcached',

The bootstrap/compiled.php file

This file is generated by the Laravel 4 framework after its first installation and after any update. It collects within a single file the most used classes of the framework in order to load them as fast as possible.
Take note that this file remains an option and that the application can run without it.

After the updates we made to the Laravel framework configuration, we need to regenerate the?bootstrap/compiled.php?file by using the following command.

composer optimize

End of the first stage

At this stage, we just need to upload again the application to App Engine and to access the application url in order to finally get the expected message.

Laravel 4 on Google AppEngine for PHP by Gilles Me

And now, Google Cloud SQL !

We are now going to add to our application a connection to a Google Cloud SQL database.

Before to do this, you need to create a Google Cloud SQL instance from the Google APIs web console (https://code.google.com/apis/console) and associate your newly created instance to your App Engine application.
Note : the App Engine application and the Google Cloud SQL instance should belong to the same region (US or EU).

Then, you need to create your database by using the SQL command?‘CREATE DATABASE dbname;’?where?dbname?is the name of your database. To do this, you can use the Google Cloud SQL web console or let your application create the database programmatically.

Once the MySQL instance is created, associated to the application, and that your database has been created, you need to configure the Laravel 4 framework to access the database. To do this, you need to update the?app/config/database.php?file in the following manner, taking care to replace in the code below the values?my-project-name:my-cloud-instance?anddbname?by the values corresponding to your newly created database.

...
'mysql' => array(
    'driver'    => 'mysql',
    'unix_socket' => '/cloudsql/my-project-name:my-cloudsql-instance',
    'host'      => '',
    'database'  => 'dbname',
    'username'  => 'root',
'password'  => '',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
),
...

In order to test our application, we have created a table with few data.

CREATE TABLE gaelaravel4demo.people (id INT, first_name VARCHAR(50), last_name VARCHAR(50));
INSERT gaelaravel4demo.people VALUES (1, ‘John’, ‘Doe’), (2, ‘Paul’, ‘Smith’);

We have also added the?Person?Model in the?app/models?directory.

app/models/Person.php

And finally, we have modified the?app/routes.php?and?app/views/hello.php?files in the following manner.

app/routes.php

...
Route::get('/', function()
{
    $people = Person::all();
    return View::make('hello', array('people' => $people));
});
...

app/views/hello.php

...
    = "{$person->id} - {$person->first_name} {$person->last_name}" ?>
    
...

unix_socket

Once that the last updates had been done, we have uploaded our application to App Engine and tried to access the application url.

The application returned an exception that indicates that the connection to the database has not succeeded for the following reason.

exception 'PDOException' with message 'SQLSTATE[HY000] [2002] Unable to find the socket transport "unix" - did you forget to enable it when you configured PHP?

From our analysis, it seems there is a bug in the?Illuminate\Database\Connectors\MySqlConnector?class of the Laravel 4 framework.

We propose a corrected version of this class that you will find in the gist?https://gist.github.com/gmergoil/5693102?by which you must replace the content of thevendor/laravel/framework/src/Illuminate/Database/Connectors/MySqlConnector.php?file.

Note : during an update of the Laravel framework by using the?composer update?command, the modifiedMySqlConnector.php?file will be reset to its default content. Thus, it will be necessary to update again theMySqlConnector.php?file after any framework update and before any upload to App Engine. As it seems to be a bug in the framework, we will submit a fix to the Laravel team in order the bug to be fixed in the future releases.

You can now upload your application to Google App Engine and you should get the following result.

Laravel 4 on Google AppEngine for PHP by Gilles Me

Sumary of the experimentation

This experimentation allowed us to deploy a Laravel 4 standard application to the Google App Engine PHP runtime.

In order to succeed, we have had to modify the default configuration of App Engine and Laravel, and even update some Laravel internal components.

Here is the different steps we have followed :

  • add the?app.yaml?file,
  • add the?gethostname()?function,
  • authorize the?php_sapi_name()?and?php_uname()?functions in the php.ini file,
  • replace the?Illuminate\Encryption?Laravel package which uses the?mcrypt?PHP extension unavailable in the App Engine PHP runtime by the?neoxia\laravel-openssl-encryption?package which uses the?openssl?PHP extension,
  • replace the Laravel 4 default log manager by?SyslogHandler?handler included in the?Monolog?package,
  • activate the Laravel 4 session and cache manager based on?Memcached,
  • regenerate the?compiled.php?file,
  • configure a connection to a Google Cloud SQL database,
  • replace the?Illuminate\Database\Connectors\MySqlConnector?class to fix a bug in the framework.

Conclusions

The main conclusion we can make from this experimentation is that, used together, Google App Engine for PHP and Laravel 4 present a strong potential.

Laravel 4 is certainly the PHP framework that progress the most in the moment, given its ease of use and the quality of its architecture and its code.

Google App Engine is one of the most powerful and accessible platforms PaaS, however with some restrictions. The support of the PHP language, announced at Google I/O 2013 is probably going to strongly increase the adoption of this platform.

Combine the strength of Laravel 4 to those of Google App Engine gives a very effective solution to quickly produce high-level web applications and highly scalable.

Nevertheless, there are some steps before that the integration of these two technologies be at the level expected for a real production grade platform.

Firstly, the PHP support on the App Engine platform must improve and be aligned with standards concerning the available PHP extensions. During this testing, we have faced the lack of support of the PHP mcrypt extension for which we have found a work around. It has to be known that the App Engine PHP runtime does not support either the PHP mbstring extension which is widely used in PHP applications.
In the case of the Laravel 4 framework, the lack of the mbstring extension does not prevent the execution of the application because the framework substitutes its own PHP implementation of the mbstring functions, but their performance are far below the one of the native functions.

Secondly, we have succeeded in configure and slightly modify the Laravel 4 framework in order it could run on the App Engine PHP runtime. Nevertheless, a lot of side functions of the framework cannot be used at this time. For instance, it is the case of the migrations that have to be done by hand and without the use of the artisan tool. Also, it would be desirable if the Google App Engine platform meets success with the Laravel developers, that the community provides a version of its test and development tools that are tailored for the App Engine platform.

As a conclusion, we invite you to continue experimenting with these two promising technologies, but we advise you to wait a couple of month before to consider using them for critical applications in production environment. In the meantime, Google App Engine will be out of his beta and will have moved towards more compliance with the PHP standards and Laravel could be equipped with tools specific to the App Engine platform … the Neoxia team is already working on it !

We would be very interested in your own experiments with Google App Engine for PHP and Laravel. Let us known through a comment of this blog.

References

  • Google App Engine,
  • Laravel 4,
  • Google Cloud SQL,
  • Google I/O 2013 :?“A new language for App Engine”,
  • Laravel 4 encryption package based on openssl :?neoxia/laravel-openssl-encryption,
  • A corrected version of the?MySqlConnector.php?file for the Laravel 4 framework.