|
1 | 1 | ## Run Symfony on App Engine Standard for PHP 7.2
|
2 | 2 |
|
3 |
| -This tutorial will walk you through how to create and deploy a Symfony project |
4 |
| -to App Engine Standard for PHP 7.2. You will learn how to: |
| 3 | +See the [Community Tutorial](https://cloud.google.com/community/tutorials/run-symfony-on-appengine-standard) for complete instructions. |
5 | 4 |
|
6 |
| -1. Create a [Symfony][symfony] project |
7 |
| -1. Configure it to run in the App Engine environment |
8 |
| -1. Deploy it to App Engine |
9 |
| -1. Set up a [Cloud SQL][cloud-sql] database |
10 |
| -1. Configure Doctrine to communicate with Cloud SQL |
11 |
| - |
12 |
| -> **Note**: This repository is just a tutorial and is not a Symfony project in |
13 |
| - and of itself. The steps will require you to set up a new Symfony project in a |
14 |
| - separate directory. |
15 |
| - |
16 |
| -## Prerequisites |
17 |
| - |
18 |
| -1. [Create a project][create-project] in the Google Cloud Platform Console |
19 |
| - and make note of your project ID. |
20 |
| -1. [Enable billing][enable-billing] for your project. |
21 |
| -1. Install the [Google Cloud SDK](https://cloud.google.com/sdk/). |
22 |
| - |
23 |
| -## Install |
24 |
| - |
25 |
| -This tutorial uses the [Symfony Demo][symfony-demo] application. Run the |
26 |
| -following command to install it: |
27 |
| - |
28 |
| -```sh |
29 |
| -PROJECT_DIR='symfony-on-appengine' |
30 |
| -composer create-project symfony/symfony-demo:^1.2 $PROJECT_DIR |
31 |
| -``` |
32 |
| - |
33 |
| -## Run |
34 |
| - |
35 |
| -1. Run the app with the following command: |
36 |
| - |
37 |
| - php bin/console server:run |
38 |
| - |
39 |
| -1. Visit [http://localhost:8000](http://localhost:8000) to see the Symfony |
40 |
| - Welcome page. |
41 |
| - |
42 |
| -## Deploy |
43 |
| - |
44 |
| -1. Remove the `scripts` section from `composer.json` in the root of your |
45 |
| - project. You can do this manually, or by running the following line of code |
46 |
| - below in the root of your Symfony project: |
47 |
| - |
48 |
| - ```sh |
49 |
| - php -r "file_put_contents('composer.json', json_encode(array_diff_key(json_decode(file_get_contents('composer.json'), true), ['scripts' => 1]), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));" |
50 |
| - ``` |
51 |
| - |
52 |
| - > **Note**: The composer scripts run on the [Cloud Build][cloud-build] server. |
53 |
| - This is a temporary fix to prevent errors prior to deployment. |
54 |
| - |
55 |
| -1. Copy the [`app.yaml`](app.yaml) file from this repository into the root of |
56 |
| - your project and replace `YOUR_APP_SECRET` with a new secret or the generated |
57 |
| - secret in `.env`: |
58 |
| - |
59 |
| - ```yaml |
60 |
| - runtime: php72 |
61 |
| - |
62 |
| - env_variables: |
63 |
| - APP_ENV: prod |
64 |
| - APP_SECRET: YOUR_APP_SECRET |
65 |
| - |
66 |
| - # URL handlers |
67 |
| - # ... |
68 |
| - ``` |
69 |
| - |
70 |
| - > **NOTE** Read more about the [env][symfony-env] and [secret][symfony-secret] |
71 |
| - parameters in Symfony's documentation. |
72 |
| - |
73 |
| -1. [Override the cache and log directories][symfony-override-cache] so that |
74 |
| - they use `/tmp` in production. This is done by modifying the functions |
75 |
| - `getCacheDir` and `getLogDir` to the following in `src/Kernel.php`: |
76 |
| - |
77 |
| - |
78 |
| - ```php |
79 |
| - class Kernel extends BaseKernel |
80 |
| - { |
81 |
| - //... |
82 |
| -
|
83 |
| - public function getCacheDir() |
84 |
| - { |
85 |
| - if ($this->environment === 'prod') { |
86 |
| - return sys_get_temp_dir(); |
87 |
| - } |
88 |
| - return $this->getProjectDir() . '/var/cache/' . $this->environment; |
89 |
| - } |
90 |
| -
|
91 |
| - public function getLogDir() |
92 |
| - { |
93 |
| - if ($this->environment === 'prod') { |
94 |
| - return sys_get_temp_dir(); |
95 |
| - } |
96 |
| - return $this->getProjectDir() . '/var/log'; |
97 |
| - } |
98 |
| -
|
99 |
| - // ... |
100 |
| - } |
101 |
| - ``` |
102 |
| - |
103 |
| - > **NOTE**: This is required because App Engine's file system is **read-only**. |
104 |
| - |
105 |
| -1. Deploy your application to App Engine: |
106 |
| - |
107 |
| - gcloud app deploy |
108 |
| - |
109 |
| -1. Visit `http://YOUR_PROJECT_ID.appspot.com` to see the Symfony demo landing |
110 |
| - page. |
111 |
| - |
112 |
| -The homepage will load when you view your application, but browsing to any of |
113 |
| -the other demo pages will result in a **500** error. This is because you haven't |
114 |
| -set up a database yet. Let's do that now! |
115 |
| - |
116 |
| -## Connect to Cloud SQL with Doctrine |
117 |
| - |
118 |
| -Next, connect your Symfony demo application with a [Cloud SQL][cloud-sql] |
119 |
| -database. This tutorial uses the database name `symfonydb` and the username |
120 |
| -`root`, but you can use whatever you like. |
121 |
| - |
122 |
| -### Setup |
123 |
| - |
124 |
| -1. Follow the instructions to set up a |
125 |
| - [Google Cloud SQL Second Generation instance for MySQL][cloud-sql-create]. |
126 |
| - |
127 |
| -1. Create a database for your Symfony application. Replace `INSTANCE_NAME` |
128 |
| - with the name of your instance: |
129 |
| - |
130 |
| - gcloud sql databases create symfonydb --instance=INSTANCE_NAME |
131 |
| - |
132 |
| -1. Enable the [Cloud SQL APIs][cloud-sql-apis] in your project. |
133 |
| - |
134 |
| -1. Follow the instructions to |
135 |
| - [install and run the Cloud SQL proxy client on your local machine][cloud-sql-install]. |
136 |
| - The Cloud SQL proxy is used to connect to your Cloud SQL instance when |
137 |
| - running locally. This is so you can run database migrations locally to set up |
138 |
| - your production database. |
139 |
| - |
140 |
| - * Use the [Cloud SDK][cloud-sdk] from the command line to run the following |
141 |
| - command. Copy the `connectionName` value for the next step. Replace |
142 |
| - `INSTANCE_NAME` with the name of your instance: |
143 |
| - |
144 |
| - gcloud sql instances describe INSTANCE_NAME |
145 |
| - |
146 |
| - * Start the Cloud SQL proxy and replace `INSTANCE_CONNECTION_NAME` with |
147 |
| - the connection name you retrieved in the previous step: |
148 |
| - |
149 |
| - cloud_sql_proxy -instances=INSTANCE_CONNECTION_NAME=tcp:3306 & |
150 |
| - |
151 |
| - **Note:** Include the `-credential_file` option when using the proxy, or |
152 |
| - authenticate with `gcloud`, to ensure proper authentication. |
153 |
| - |
154 |
| -### Configure |
155 |
| - |
156 |
| -1. Modify your Doctrine configuration in `config/packages/doctrine.yml` and |
157 |
| - change the parameters under `doctrine.dbal` to be the following: |
158 |
| - |
159 |
| - ```yaml |
160 |
| - # Doctrine Configuration |
161 |
| - doctrine: |
162 |
| - dbal: |
163 |
| - driver: pdo_mysql |
164 |
| - url: '%env(resolve:DATABASE_URL)%' |
165 |
| -
|
166 |
| - # ORM configuration |
167 |
| - # ... |
168 |
| - ``` |
169 |
| - |
170 |
| -1. Use the Symfony CLI to connect to your instance and create a database for |
171 |
| - the application. Be sure to replace `DB_PASSWORD` with the root password you |
172 |
| - configured: |
173 |
| - |
174 |
| - # create the database using doctrine |
175 |
| - DATABASE_URL="mysql://root:[email protected]:3306/symfonydb" \ |
176 |
| - bin/console doctrine:schema:create |
177 |
| - |
178 |
| -1. Modify your `app.yaml` file with the following contents. Be sure to replace |
179 |
| - `DB_PASSWORD` and `INSTANCE_CONNECTION_NAME` with the values you created for |
180 |
| - your Cloud SQL instance: |
181 |
| - |
182 |
| - ```yaml |
183 |
| - runtime: php72 |
184 |
| -
|
185 |
| - env_variables: |
186 |
| - APP_ENV: prod |
187 |
| - APP_SECRET: YOUR_APP_SECRET |
188 |
| -
|
189 |
| - # Add the DATABASE_URL environment variable |
190 |
| - DATABASE_URL: mysql://root:DB_PASSWORD@localhost?unix_socket=/cloudsql/INSTANCE_CONNECTION_NAME;dbname=symfonydb |
191 |
| -
|
192 |
| - # URL handlers |
193 |
| - # ... |
194 |
| - ``` |
195 |
| - |
196 |
| -### Run |
197 |
| - |
198 |
| -1. Now you can run locally and verify the connection works as expected. |
199 |
| - |
200 |
| - DB_HOST="127.0.0.1" DB_DATABASE=symfony DB_USERNAME=root DB_PASSWORD=YOUR_DB_PASSWORD \ |
201 |
| - php bin/console server:run |
202 |
| - |
203 |
| -1. Reward all your hard work by running the following command and deploying |
204 |
| - your application to App Engine: |
205 |
| - |
206 |
| - gcloud app deploy |
207 |
| - |
208 |
| -## Set up Stackdriver Logging and Error Reporting |
209 |
| - |
210 |
| -Install the Google Cloud libraries for Stackdriver integration: |
211 |
| - |
212 |
| -```sh |
213 |
| -# Set the environment variable below to the local path to your symfony project |
214 |
| -SYMFONY_PROJECT_PATH="/path/to/my-symfony-project" |
215 |
| -cd $SYMFONY_PROJECT_PATH |
216 |
| -composer require google/cloud-logging google/cloud-error-reporting |
217 |
| -``` |
218 |
| - |
219 |
| -### Copy over App Engine files |
220 |
| - |
221 |
| -For your Symfony application to integrate with Stackdriver Logging and Error Handling, |
222 |
| -you will need to copy over the `monolog.yaml` config file and the `ExceptionSubscriber.php` |
223 |
| -Exception Subscriber: |
224 |
| - |
225 |
| -```sh |
226 |
| -# clone the Google Cloud Platform PHP samples repo somewhere |
227 |
| -cd /path/to/php-samples |
228 |
| -git clone https://github.com/GoogleCloudPlatform/php-docs-samples |
229 |
| -
|
230 |
| -# enter the directory for the symfony framework sample |
231 |
| -cd appengine/php72/symfony-framework/ |
232 |
| -
|
233 |
| -# copy monolog.yaml into your Symfony project |
234 |
| -cp config/packages/prod/monolog.yaml \ |
235 |
| - $SYMFONY_PROJECT_PATH/config/packages/prod/ |
236 |
| -
|
237 |
| -# copy ExceptionSubscriber.php into your Symfony project |
238 |
| -cp src/EventSubscriber/ExceptionSubscriber.php \ |
239 |
| - $SYMFONY_PROJECT_PATH/src/EventSubscriber |
240 |
| -``` |
241 |
| - |
242 |
| -The two files needed are as follows: |
243 |
| - |
244 |
| - 1. [`config/packages/prod/monolog.yaml`](app/config/packages/prod/monolog.yaml) - Adds Stackdriver Logging to your Monolog configuration. |
245 |
| - 1. [`src/EventSubscriber/ExceptionSubscriber.php`](src/EventSubscriber/ExceptionSubscriber.php) - Event subscriber which sends exceptions to Stackdriver Error Reporting. |
246 |
| - |
247 |
| -If you'd like to test the logging and error reporting, you can also copy over `LoggingController.php`, which |
248 |
| -exposes the routes `/en/logging/notice` and `/en/logging/exception` for ensuring your logs are being sent to |
249 |
| -Stackdriver: |
250 |
| - |
251 |
| -``` |
252 |
| -# copy LoggingController.php into your Symfony project |
253 |
| -cp src/Controller/LoggingController.php \ |
254 |
| - $SYMFONY_PROJECT_PATH/src/Controller |
255 |
| -``` |
256 |
| - |
257 |
| - 1. [`src/Controller/LoggingController.php`](src/Controller/LoggingController.php) - Controller for testing logging and exceptions. |
258 |
| - |
259 |
| -### View application logs and errors |
260 |
| - |
261 |
| -Once you've redeployed your application using `gcloud app deploy`, you'll be able to view |
262 |
| -Application logs in the [Stackdriver Logging UI][stackdriver-logging-ui], and errors in |
263 |
| -the [Stackdriver Error Reporting UI][stackdriver-errorreporting-ui]! If you copied over the |
264 |
| -`LoggingController.php` file, you can test this by pointing your browser to |
265 |
| -`https://YOUR_PROJECT_ID.appspot.com/en/logging/notice` and |
266 |
| -`https://YOUR_PROJECT_ID.appspot.com/en/logging/exception` |
267 |
| - |
268 |
| -## Send emails |
269 |
| - |
270 |
| -The recommended way to send emails is to use a third-party mail provider such as [Sendgrid][sendgrid], [Mailgun][mailgun] or [Mailjet][mailjet]. |
271 |
| -Hosting your application on GAE, most of these providers will offer you up to 30,000 emails per month and you will be charged only if you send more. |
272 |
| -You will have the possibility to track your email delivery and benefit from all the feature of a real email broadcasting system. |
273 |
| - |
274 |
| -### Install |
275 |
| - |
276 |
| -First you need to install the mailer component: |
277 |
| - |
278 |
| -``` |
279 |
| -composer require symfony/mailer |
280 |
| -``` |
281 |
| - |
282 |
| -For this example, we will use `Mailgun`. To use a different mail provider, see the [Symfony mailer documentation][symfony-mailer]. |
283 |
| - |
284 |
| -``` |
285 |
| -composer require symfony/mailgun-mailer |
286 |
| -``` |
287 |
| -
|
288 |
| -This recipe will automatically add the following ENV variable to your .env file: |
289 |
| -
|
290 |
| -``` |
291 |
| -# Will be provided by mailgun once your account will be created |
292 |
| -MAILGUN_KEY= xxxxxx |
293 |
| -# Should be your Mailgun MX record |
294 |
| -MAILGUN_DOMAIN= mg.yourdomain.com |
295 |
| -# Region is mandatory if you chose server outside the US otherwise your domain will not be found |
296 |
| -MAILER_DSN=mailgun://$MAILGUN_KEY:$MAILGUN_DOMAIN@default?region=eu |
297 |
| -``` |
298 |
| -
|
299 |
| -From that point, you just need to create your account and first domain adding all the DNS Records. |
300 |
| -[Mailgun documentation][mailgun-add-domain] will lead you through these steps. |
301 |
| -
|
302 |
| -You can now send emails in Controller and Service as usual: |
303 |
| -``` |
304 |
| -// src/Controller/MailerController.php |
305 |
| -namespace App\Controller; |
306 |
| - |
307 |
| -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
308 |
| -use Symfony\Component\Mailer\MailerInterface; |
309 |
| -use Symfony\Component\Mime\Email; |
310 |
| - |
311 |
| -class ExampleController extends AbstractController |
312 |
| -{ |
313 |
| - /** |
314 |
| - * @Route("/email") |
315 |
| - */ |
316 |
| - public function sendEmail(MailerInterface $mailer) |
317 |
| - { |
318 |
| - $email = (new Email()) |
319 |
| - |
320 |
| - |
321 |
| - ->subject('Time for Symfony Mailer!') |
322 |
| - ->text('Sending emails is fun again!'); |
323 |
| - |
324 |
| - $mailer->send($email); |
325 |
| - } |
326 |
| -} |
327 |
| -``` |
328 |
| -
|
329 |
| -[cloud-sdk]: https://cloud.google.com/sdk/ |
330 |
| -[cloud-build]: https://cloud.google.com/cloud-build/ |
331 |
| -[cloud-sql]: https://cloud.google.com/sql/docs/ |
332 |
| -[cloud-sql-create]: https://cloud.google.com/sql/docs/mysql/create-instance |
333 |
| -[cloud-sql-install]: https://cloud.google.com/sql/docs/mysql/connect-external-app#install |
334 |
| -[cloud-sql-apis]: https://console.cloud.google.com/apis/library/sqladmin.googleapis.com/?pro |
335 |
| -[cloud-migration]: https://cloud.google.com/appengine/docs/standard/php7/php-differences?hl=en#migrating_from_the_app_engine_php_sdk |
336 |
| -[create-project]: https://cloud.google.com/resource-manager/docs/creating-managing-projects |
337 |
| -[enable-billing]: https://support.google.com/cloud/answer/6293499?hl=en |
338 |
| -[symfony]: http://symfony.com |
339 |
| -[symfony-install]: http://symfony.com/doc/current/setup.html |
340 |
| -[symfony-welcome]: https://symfony.com/doc/current/_images/welcome.png |
341 |
| -[symfony-demo]: https://github.com/symfony/demo |
342 |
| -[symfony-secret]: http://symfony.com/doc/current/reference/configuration/framework.html#secret |
343 |
| -[symfony-env]: https://symfony.com/doc/current/configuration/environments.html#executing-an-application-in-different-environments |
344 |
| -[symfony-override-cache]: https://symfony.com/doc/current/configuration/override_dir_structure.html#override-the-cache-directory |
345 |
| -[symfony-mailer]: https://symfony.com/doc/current/mailer.html |
346 |
| -[stackdriver-logging-ui]: https://console.cloud.google.com/logs |
347 |
| -[stackdriver-errorreporting-ui]: https://console.cloud.google.com/errors |
348 |
| -[sendgrid]: https://sendgrid.com/ |
349 |
| -[mailgun]: https://www.mailgun.com/ |
350 |
| -[mailjet]: https://www.mailjet.com/ |
351 |
| -[mailgun-add-domain]: https://help.mailgun.com/hc/en-us/articles/203637190-How-Do-I-Add-or-Delete-a-Domain- |
| 5 | +To file issues or contribute changes, see [the GitHub repository](https://github.com/GoogleCloudPlatform/community/blob/master/tutorials/run-symfony-on-appengine-standard/index.md). |
0 commit comments