|
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