1. In the local development environment, the deployment based on Laravel Sail is already complete. Opening the URL http://weibo.test/ returns a 200 response. See Figure 1.

2. I registered a Heroku account using an @163.com email address, but it was not allowed. Finally, I successfully registered using an @gmail.com address. See Figure 2.

3. I clicked the link in the @gmail.com inbox to activate the account. See Figure 3.

4. Reference URL: https://devcenter.heroku.com/articles/heroku-cli . The Heroku Command Line Interface (CLI) makes it easy to create and manage Heroku apps directly from the terminal. This is an essential part of using Heroku.
5. In the Ubuntu system running inside WSL2, I ran the following command from the terminal. It returned an error: error: cannot communicate with server: Post http://localhost/v2/snaps/heroku: dial unix /run/snapd.socket: connect: no such file or directory. See Figure 4.

wangqiang@DESKTOP-QLPK8QM:/mnt/e/wwwroot/weibo$ sudo snap install --classic heroku
error: cannot communicate with server: Post http://localhost/v2/snaps/heroku: dial unix /run/snapd.socket: connect: no such file or directory
6. I finally decided to use the Windows software. I downloaded the appropriate installer for my Windows installation. See Figure 5.

7. During the installation, an error occurred: Error opening file for writing. See Figure 6.

Error opening file for writing:
D:\Program Files\heroku\client\bin\node.exe
Click Abort to stop the installation,
Retry to try again, or
Ignore to skip this file.
8. I reinstalled it by running it as an administrator, and the error no longer occurred.
9. To verify the installation, use the heroku –version command. The CLI has been successfully installed. See Figure 7.

PS C:\Users\Lenovo> heroku --version
» Warning: Our terms of service have changed: https://dashboard.heroku.com/terms-of-service
heroku/7.53.0 win32-x64 node-v12.21.0
PS C:\Users\Lenovo>
10. After installing the CLI, run the heroku login command. You will be prompted to press any key to go to your web browser to complete the login. The CLI will then log you in automatically. See Figure 8.

PS C:\Users\Lenovo> heroku login
heroku: Press any key to open up the browser to login or q to exit:
Opening browser to https://cli-auth.heroku.com/auth/cli/browser/056bdba3-dbeb-43ee-9ffc-9556ce91ee23?requestor=SFMyNTY.g2gDbQAAAA42Ni4xNzUuMjE2LjIzOW4GAMhVMuV9AWIAAVGA.7UEaCXMegvnax1AIZ5H_XignHykfVPEHFYcOP0NL2uI
Logging in... done
Logged in as shuijingwanwq@gmail.com
PS C:\Users\Lenovo>
11. Reference URL: https://devcenter.heroku.com/articles/getting-started-with-php . Because the documentation assumes that PHP and Composer are installed locally, and the PHP version in my local environment did not match the version in the Laravel Sail environment, I decided to upgrade the local PHP version to PHP 8.1 first. See Figures 9 and 10.


The version numbers in the local environment:
PS C:\Users\Lenovo> php -v
PHP 7.4.27 (cli) (built: Dec 14 2021 19:52:13) ( ZTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
PS C:\Users\Lenovo> composer -V
Composer version 2.1.14 2021-11-30 10:51:43
PS C:\Users\Lenovo>
The version numbers in the Laravel Sail environment:
# php -v
PHP 8.1.0 (cli) (built: Nov 25 2021 20:22:22) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.0, Copyright (c) Zend Technologies
with Zend OPcache v8.1.0, Copyright (c), by Zend Technologies
with Xdebug v3.1.1, Copyright (c) 2002-2021, by Derick Rethans
# composer -V
Composer version 2.1.14 2021-11-30 10:51:43
#
12. The upgraded local PHP version is now PHP 8.1.1.
PS C:\Users\Lenovo> php -v
PHP 8.1.1 (cli) (built: Dec 15 2021 10:31:43) (ZTS Visual C++ 2019 x64)
Copyright (c) The PHP Group
Zend Engine v4.1.1, Copyright (c) Zend Technologies
PS C:\Users\Lenovo>
13. I navigated to the project root directory and used the heroku create command to create a new app on Heroku. secret-stream-72395 is the default name Heroku randomly generated for the app; everyone gets a different name. The URL https://secret-stream-72395.herokuapp.com/ is the live address for the app. See Figure 11.

PS E:\wwwroot> cd .\weibo\
PS E:\wwwroot\weibo> heroku create
» Warning: heroku update available from 7.53.0 to 7.59.2.
Creating app... done, ⬢ secret-stream-72395
https://secret-stream-72395.herokuapp.com/ | https://git.heroku.com/secret-stream-72395.git
PS E:\wwwroot\weibo>
14. The Heroku platform supports multiple languages. When deploying an app, Heroku automatically detects which language the app’s code is written in, and then executes a series of operations specific to that language to prepare the runtime environment. A Laravel app includes a package.json file by default, but when Heroku detects this file, it assumes the app is written in Node.js. Therefore, we need to declare a buildpack for the app to tell Heroku that our app is written in PHP. See Figure 12.

PS E:\wwwroot\weibo> heroku buildpacks:set heroku/php
» Warning: heroku update available from 7.53.0 to 7.59.2.
Buildpack set. Next release on secret-stream-72395 will use heroku/php.
Run git push heroku main to create a new release using this buildpack.
PS E:\wwwroot\weibo>
15. Push the code and deploy it to Heroku. See Figure 13.

PS E:\wwwroot\weibo> git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged ..." to unstage)
modified: docker-compose.yml
PS E:\wwwroot\weibo> git push heroku main
Enumerating objects: 195, done.
Counting objects: 100% (195/195), done.
Delta compression using up to 4 threads
Compressing objects: 100% (169/169), done.
Writing objects: 100% (195/195), 651.34 KiB | 1.41 MiB/s, done.
Total 195 (delta 47), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpack: heroku/php
remote: -----> PHP app detected
remote: -----> Bootstrapping...
remote: -----> Installing platform packages...
remote: - php (8.1.1)
remote: - ext-mbstring (bundled with php)
remote: - composer (2.1.14)
remote: - apache (2.4.51)
remote: - nginx (1.20.2)
remote: -----> Installing dependencies...
remote: Composer version 2.1.14 2021-11-30 10:51:43
remote: Installing dependencies from lock file
remote: Verifying lock file contents can be installed on current platform.
remote: Package operations: 70 installs, 0 updates, 0 removals
remote: - Downloading doctrine/inflector (2.0.4)
remote: - Downloading doctrine/lexer (1.2.1)
remote: - Downloading symfony/polyfill-ctype (v1.23.0)
remote: - Downloading webmozart/assert (1.10.0)
remote: - Downloading dragonmantank/cron-expression (v3.1.0)
remote: - Downloading symfony/polyfill-php80 (v1.23.1)
remote: - Downloading symfony/polyfill-php73 (v1.23.0)
remote: - Downloading symfony/polyfill-mbstring (v1.23.1)
remote: - Downloading symfony/deprecation-contracts (v3.0.0)
remote: - Downloading symfony/http-foundation (v5.4.1)
remote: - Downloading psr/event-dispatcher (1.0.0)
remote: - Downloading symfony/event-dispatcher-contracts (v3.0.0)
remote: - Downloading symfony/event-dispatcher (v6.0.1)
remote: - Downloading symfony/var-dumper (v5.4.1)
remote: - Downloading psr/log (2.0.0)
remote: - Downloading symfony/error-handler (v5.4.1)
remote: - Downloading symfony/http-kernel (v5.4.1)
remote: - Downloading voku/portable-ascii (1.5.6)
remote: - Downloading phpoption/phpoption (1.8.1)
remote: - Downloading graham-campbell/result-type (v1.0.4)
remote: - Downloading vlucas/phpdotenv (v5.4.1)
remote: - Downloading symfony/css-selector (v6.0.1)
remote: - Downloading tijsverkoyen/css-to-inline-styles (2.2.4)
remote: - Downloading symfony/routing (v5.4.0)
remote: - Downloading symfony/process (v5.4.0)
remote: - Downloading symfony/polyfill-php72 (v1.23.0)
remote: - Downloading symfony/polyfill-intl-normalizer (v1.23.0)
remote: - Downloading symfony/polyfill-intl-idn (v1.23.0)
remote: - Downloading symfony/mime (v5.4.0)
remote: - Downloading symfony/finder (v5.4.0)
remote: - Downloading symfony/polyfill-intl-grapheme (v1.23.1)
remote: - Downloading symfony/string (v6.0.1)
remote: - Downloading psr/container (1.1.2)
remote: - Downloading symfony/service-contracts (v2.4.1)
remote: - Downloading symfony/console (v5.4.1)
remote: - Downloading symfony/polyfill-iconv (v1.23.0)
remote: - Downloading egulias/email-validator (2.1.25)
remote: - Downloading swiftmailer/swiftmailer (v6.3.0)
remote: - Downloading symfony/polyfill-php81 (v1.23.0)
remote: - Downloading ramsey/collection (1.2.2)
remote: - Downloading brick/math (0.9.3)
remote: - Downloading ramsey/uuid (4.2.3)
remote: - Downloading psr/simple-cache (1.0.1)
remote: - Downloading opis/closure (3.6.2)
remote: - Downloading symfony/translation-contracts (v3.0.0)
remote: - Downloading symfony/translation (v6.0.1)
remote: - Downloading nesbot/carbon (2.55.2)
remote: - Downloading monolog/monolog (2.3.5)
remote: - Downloading league/mime-type-detection (1.9.0)
remote: - Downloading league/flysystem (1.1.9)
remote: - Downloading nette/utils (v3.2.6)
remote: - Downloading nette/schema (v1.2.2)
remote: - Downloading dflydev/dot-access-data (v3.0.1)
remote: - Downloading league/config (v1.1.1)
remote: - Downloading league/commonmark (2.1.0)
remote: - Downloading laravel/serializable-closure (v1.0.5)
remote: - Downloading laravel/framework (v8.76.2)
remote: - Downloading asm89/stack-cors (v2.0.3)
remote: - Downloading fruitcake/laravel-cors (v2.0.4)
remote: - Downloading psr/http-message (1.0.1)
remote: - Downloading psr/http-client (1.0.1)
remote: - Downloading ralouphie/getallheaders (3.0.3)
remote: - Downloading psr/http-factory (1.0.1)
remote: - Downloading guzzlehttp/psr7 (2.1.0)
remote: - Downloading guzzlehttp/promises (1.5.1)
remote: - Downloading guzzlehttp/guzzle (7.4.1)
remote: - Downloading laravel/sanctum (v2.13.0)
remote: - Downloading nikic/php-parser (v4.13.2)
remote: - Downloading psy/psysh (v0.10.12)
remote: - Downloading laravel/tinker (v2.6.3)
remote: - Installing doctrine/inflector (2.0.4): Extracting archive
remote: - Installing doctrine/lexer (1.2.1): Extracting archive
remote: - Installing symfony/polyfill-ctype (v1.23.0): Extracting archive
remote: - Installing webmozart/assert (1.10.0): Extracting archive
remote: - Installing dragonmantank/cron-expression (v3.1.0): Extracting archive
remote: - Installing symfony/polyfill-php80 (v1.23.1): Extracting archive
remote: - Installing symfony/polyfill-php73 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-mbstring (v1.23.1): Extracting archive
remote: - Installing symfony/deprecation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/http-foundation (v5.4.1): Extracting archive
remote: - Installing psr/event-dispatcher (1.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher (v6.0.1): Extracting archive
remote: - Installing symfony/var-dumper (v5.4.1): Extracting archive
remote: - Installing psr/log (2.0.0): Extracting archive
remote: - Installing symfony/error-handler (v5.4.1): Extracting archive
remote: - Installing symfony/http-kernel (v5.4.1): Extracting archive
remote: - Installing voku/portable-ascii (1.5.6): Extracting archive
remote: - Installing phpoption/phpoption (1.8.1): Extracting archive
remote: - Installing graham-campbell/result-type (v1.0.4): Extracting archive
remote: - Installing vlucas/phpdotenv (v5.4.1): Extracting archive
remote: - Installing symfony/css-selector (v6.0.1): Extracting archive
remote: - Installing tijsverkoyen/css-to-inline-styles (2.2.4): Extracting archive
remote: - Installing symfony/routing (v5.4.0): Extracting archive
remote: - Installing symfony/process (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-php72 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-normalizer (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-idn (v1.23.0): Extracting archive
remote: - Installing symfony/mime (v5.4.0): Extracting archive
remote: - Installing symfony/finder (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-intl-grapheme (v1.23.1): Extracting archive
remote: - Installing symfony/string (v6.0.1): Extracting archive
remote: - Installing psr/container (1.1.2): Extracting archive
remote: - Installing symfony/service-contracts (v2.4.1): Extracting archive
remote: - Installing symfony/console (v5.4.1): Extracting archive
remote: - Installing symfony/polyfill-iconv (v1.23.0): Extracting archive
remote: - Installing egulias/email-validator (2.1.25): Extracting archive
remote: - Installing swiftmailer/swiftmailer (v6.3.0): Extracting archive
remote: - Installing symfony/polyfill-php81 (v1.23.0): Extracting archive
remote: - Installing ramsey/collection (1.2.2): Extracting archive
remote: - Installing brick/math (0.9.3): Extracting archive
remote: - Installing ramsey/uuid (4.2.3): Extracting archive
remote: - Installing psr/simple-cache (1.0.1): Extracting archive
remote: - Installing opis/closure (3.6.2): Extracting archive
remote: - Installing symfony/translation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/translation (v6.0.1): Extracting archive
remote: - Installing nesbot/carbon (2.55.2): Extracting archive
remote: - Installing monolog/monolog (2.3.5): Extracting archive
remote: - Installing league/mime-type-detection (1.9.0): Extracting archive
remote: - Installing league/flysystem (1.1.9): Extracting archive
remote: - Installing nette/utils (v3.2.6): Extracting archive
remote: - Installing nette/schema (v1.2.2): Extracting archive
remote: - Installing dflydev/dot-access-data (v3.0.1): Extracting archive
remote: - Installing league/config (v1.1.1): Extracting archive
remote: - Installing league/commonmark (2.1.0): Extracting archive
remote: - Installing laravel/serializable-closure (v1.0.5): Extracting archive
remote: - Installing laravel/framework (v8.76.2): Extracting archive
remote: - Installing asm89/stack-cors (v2.0.3): Extracting archive
remote: - Installing fruitcake/laravel-cors (v2.0.4): Extracting archive
remote: - Installing psr/http-message (1.0.1): Extracting archive
remote: - Installing psr/http-client (1.0.1): Extracting archive
remote: - Installing ralouphie/getallheaders (3.0.3): Extracting archive
remote: - Installing psr/http-factory (1.0.1): Extracting archive
remote: - Installing guzzlehttp/psr7 (2.1.0): Extracting archive
remote: - Installing guzzlehttp/promises (1.5.1): Extracting archive
remote: - Installing guzzlehttp/guzzle (7.4.1): Extracting archive
remote: - Installing laravel/sanctum (v2.13.0): Extracting archive
remote: - Installing nikic/php-parser (v4.13.2): Extracting archive
remote: - Installing psy/psysh (v0.10.12): Extracting archive
remote: - Installing laravel/tinker (v2.6.3): Extracting archive
remote: Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
remote: Generating optimized autoload files
remote: > Illuminate\Foundation\ComposerScripts::postAutoloadDump
remote: > @php artisan package:discover --ansi
remote: Discovered Package: fruitcake/laravel-cors
remote: Discovered Package: laravel/sanctum
remote: Discovered Package: laravel/tinker
remote: Discovered Package: nesbot/carbon
remote: Package manifest generated successfully.
remote: 49 packages you are using are looking for funding.
remote: Use the `composer fund` command to find out more!
remote: -----> Preparing runtime environment...
remote: NOTICE: No Procfile, using 'web: heroku-php-apache2'.
remote: -----> Checking for additional extensions to install...
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 19.8M
remote: -----> Launching...
remote: Released v3
remote: https://secret-stream-72395.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/secret-stream-72395.git
* [new branch] main -> main
PS E:\wwwroot\weibo>
16. The application is now deployed. Ensure that at least one app instance is running, and now access the app via the URL generated from the app name. As a convenient shortcut, you can open the website as follows. See Figure 14.

PS E:\wwwroot\weibo> heroku ps:scale web=1
» Warning: heroku update available from 7.53.0 to 7.59.2.
Scaling dynos... done, now running web at 1:Free
PS E:\wwwroot\weibo> heroku open
» Warning: heroku update available from 7.53.0 to 7.59.2.
PS E:\wwwroot\weibo>
17. However, when the website automatically opened in the browser at https://secret-stream-72395.herokuapp.com/ , it returned a 403 response. See Figure 15.

Forbidden
You don't have permission to access this resource.
18. Step 15 showed the prompt: No Procfile, using ‘web: heroku-php-apache2’. I created a new Procfile file in the Laravel project directory to tell Heroku what command to use to start the web server. I then needed to add this file to Git version control. It returned an error: Push failed: cannot parse Procfile. See Figure 16.

PS E:\wwwroot\weibo> echo web: vendor/bin/heroku-php-apache2 public/ > Procfile
PS E:\wwwroot\weibo> git add -A
PS E:\wwwroot\weibo> git commit -m "Procfile for Heroku"
[main 64256ed] Procfile for Heroku
2 files changed, 6 insertions(+), 6 deletions(-)
create mode 100644 Procfile
PS E:\wwwroot\weibo> git push heroku main
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 496 bytes | 496.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpack: heroku/php
remote: -----> PHP app detected
remote: -----> Bootstrapping...
remote: -----> Installing platform packages...
remote: - php (8.1.1)
remote: - ext-mbstring (bundled with php)
remote: - composer (2.1.14)
remote: - apache (2.4.51)
remote: - nginx (1.20.2)
remote: -----> Installing dependencies...
remote: Composer version 2.1.14 2021-11-30 10:51:43
remote: Installing dependencies from lock file
remote: Verifying lock file contents can be installed on current platform.
remote: Package operations: 70 installs, 0 updates, 0 removals
remote: - Installing doctrine/inflector (2.0.4): Extracting archive
remote: - Installing doctrine/lexer (1.2.1): Extracting archive
remote: - Installing symfony/polyfill-ctype (v1.23.0): Extracting archive
remote: - Installing webmozart/assert (1.10.0): Extracting archive
remote: - Installing dragonmantank/cron-expression (v3.1.0): Extracting archive
remote: - Installing symfony/polyfill-php80 (v1.23.1): Extracting archive
remote: - Installing symfony/polyfill-php73 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-mbstring (v1.23.1): Extracting archive
remote: - Installing symfony/deprecation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/http-foundation (v5.4.1): Extracting archive
remote: - Installing psr/event-dispatcher (1.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher (v6.0.1): Extracting archive
remote: - Installing symfony/var-dumper (v5.4.1): Extracting archive
remote: - Installing psr/log (2.0.0): Extracting archive
remote: - Installing symfony/error-handler (v5.4.1): Extracting archive
remote: - Installing symfony/http-kernel (v5.4.1): Extracting archive
remote: - Installing voku/portable-ascii (1.5.6): Extracting archive
remote: - Installing phpoption/phpoption (1.8.1): Extracting archive
remote: - Installing graham-campbell/result-type (v1.0.4): Extracting archive
remote: - Installing vlucas/phpdotenv (v5.4.1): Extracting archive
remote: - Installing symfony/css-selector (v6.0.1): Extracting archive
remote: - Installing tijsverkoyen/css-to-inline-styles (2.2.4): Extracting archive
remote: - Installing symfony/routing (v5.4.0): Extracting archive
remote: - Installing symfony/process (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-php72 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-normalizer (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-idn (v1.23.0): Extracting archive
remote: - Installing symfony/mime (v5.4.0): Extracting archive
remote: - Installing symfony/finder (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-intl-grapheme (v1.23.1): Extracting archive
remote: - Installing symfony/string (v6.0.1): Extracting archive
remote: - Installing psr/container (1.1.2): Extracting archive
remote: - Installing symfony/service-contracts (v2.4.1): Extracting archive
remote: - Installing symfony/console (v5.4.1): Extracting archive
remote: - Installing symfony/polyfill-iconv (v1.23.0): Extracting archive
remote: - Installing egulias/email-validator (2.1.25): Extracting archive
remote: - Installing swiftmailer/swiftmailer (v6.3.0): Extracting archive
remote: - Installing symfony/polyfill-php81 (v1.23.0): Extracting archive
remote: - Installing ramsey/collection (1.2.2): Extracting archive
remote: - Installing brick/math (0.9.3): Extracting archive
remote: - Installing ramsey/uuid (4.2.3): Extracting archive
remote: - Installing psr/simple-cache (1.0.1): Extracting archive
remote: - Installing opis/closure (3.6.2): Extracting archive
remote: - Installing symfony/translation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/translation (v6.0.1): Extracting archive
remote: - Installing nesbot/carbon (2.55.2): Extracting archive
remote: - Installing monolog/monolog (2.3.5): Extracting archive
remote: - Installing league/mime-type-detection (1.9.0): Extracting archive
remote: - Installing league/flysystem (1.1.9): Extracting archive
remote: - Installing nette/utils (v3.2.6): Extracting archive
remote: - Installing nette/schema (v1.2.2): Extracting archive
remote: - Installing dflydev/dot-access-data (v3.0.1): Extracting archive
remote: - Installing league/config (v1.1.1): Extracting archive
remote: - Installing league/commonmark (2.1.0): Extracting archive
remote: - Installing laravel/serializable-closure (v1.0.5): Extracting archive
remote: - Installing laravel/framework (v8.76.2): Extracting archive
remote: - Installing asm89/stack-cors (v2.0.3): Extracting archive
remote: - Installing fruitcake/laravel-cors (v2.0.4): Extracting archive
remote: - Installing psr/http-message (1.0.1): Extracting archive
remote: - Installing psr/http-client (1.0.1): Extracting archive
remote: - Installing ralouphie/getallheaders (3.0.3): Extracting archive
remote: - Installing psr/http-factory (1.0.1): Extracting archive
remote: - Installing guzzlehttp/psr7 (2.1.0): Extracting archive
remote: - Installing guzzlehttp/promises (1.5.1): Extracting archive
remote: - Installing guzzlehttp/guzzle (7.4.1): Extracting archive
remote: - Installing laravel/sanctum (v2.13.0): Extracting archive
remote: - Installing nikic/php-parser (v4.13.2): Extracting archive
remote: - Installing psy/psysh (v0.10.12): Extracting archive
remote: - Installing laravel/tinker (v2.6.3): Extracting archive
remote: Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
remote: Generating optimized autoload files
remote: > Illuminate\Foundation\ComposerScripts::postAutoloadDump
remote: > @php artisan package:discover --ansi
remote: Discovered Package: fruitcake/laravel-cors
remote: Discovered Package: laravel/sanctum
remote: Discovered Package: laravel/tinker
remote: Discovered Package: nesbot/carbon
remote: Package manifest generated successfully.
remote: 49 packages you are using are looking for funding.
remote: Use the `composer fund` command to find out more!
remote: -----> Preparing runtime environment...
remote: -----> Checking for additional extensions to install...
remote: -----> Discovering process types
remote:
remote: ! Push failed: cannot parse Procfile.
remote: ! Please try pushing again.
remote: ! If the problem persists, see https://help.heroku.com/ and provide Request ID f09b381f-8217-327d-d121-119f1e8d0c31.
remote:
remote:
remote: Verifying deploy...
remote:
remote: ! Push rejected to secret-stream-72395.
remote:
To https://git.heroku.com/secret-stream-72395.git
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/secret-stream-72395.git'
PS E:\wwwroot\weibo>
19. I checked the contents of the Procfile. See Figure 17.

web:
vendor/bin/heroku-php-apache2
public/
20. I referred to Getting Started with Laravel on Heroku: https://devcenter.heroku.com/articles/getting-started-with-laravel . I checked the contents of the Procfile. See Figure 18.

PS E:\wwwroot\weibo> echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile
PS E:\wwwroot\weibo> git add .
PS E:\wwwroot\weibo> git commit -m "Procfile for Heroku"
[main a30f3dd] Procfile for Heroku
1 file changed, 0 insertions(+), 0 deletions(-)
21. I set the Laravel encryption key by using Laravel’s built-in artisan command to generate an App Key. See Figure 19.

PS E:\wwwroot\weibo> php artisan key:generate --show
base64:qtlcYLZF38gHDz/XhCE/cc0Q+BwByRygnVpfWwtRipA=
PS E:\wwwroot\weibo>
22. Based on the generated App Key, I ran the command line to complete the configuration. See Figure 20.

PS E:\wwwroot\weibo> heroku config:set APP_KEY=base64:qtlcYLZF38gHDz/XhCE/cc0Q+BwByRygnVpfWwtRipA=
» Warning: heroku update available from 7.53.0 to 7.59.2.
Setting APP_KEY and restarting ⬢ secret-stream-72395... done, v4
APP_KEY: base64:qtlcYLZF38gHDz/XhCE/cc0Q+BwByRygnVpfWwtRipA=
PS E:\wwwroot\weibo>
23. When pushing, it still returned an error: Push failed: cannot parse Procfile.
PS E:\wwwroot\weibo> git push heroku main:main
Enumerating objects: 19, done.
Counting objects: 100% (19/19), done.
Delta compression using up to 4 threads
Compressing objects: 100% (17/17), done.
Writing objects: 100% (17/17), 1.59 KiB | 542.00 KiB/s, done.
Total 17 (delta 8), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpack: heroku/php
remote: -----> PHP app detected
remote: -----> Bootstrapping...
remote: -----> Installing platform packages...
remote: - php (8.1.1)
remote: - ext-mbstring (bundled with php)
remote: - composer (2.1.14)
remote: - apache (2.4.51)
remote: - nginx (1.20.2)
remote: -----> Installing dependencies...
remote: Composer version 2.1.14 2021-11-30 10:51:43
remote: Installing dependencies from lock file
remote: Verifying lock file contents can be installed on current platform.
remote: Package operations: 70 installs, 0 updates, 0 removals
remote: - Installing doctrine/inflector (2.0.4): Extracting archive
remote: - Installing doctrine/lexer (1.2.1): Extracting archive
remote: - Installing symfony/polyfill-ctype (v1.23.0): Extracting archive
remote: - Installing webmozart/assert (1.10.0): Extracting archive
remote: - Installing dragonmantank/cron-expression (v3.1.0): Extracting archive
remote: - Installing symfony/polyfill-php80 (v1.23.1): Extracting archive
remote: - Installing symfony/polyfill-php73 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-mbstring (v1.23.1): Extracting archive
remote: - Installing symfony/deprecation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/http-foundation (v5.4.1): Extracting archive
remote: - Installing psr/event-dispatcher (1.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher (v6.0.1): Extracting archive
remote: - Installing symfony/var-dumper (v5.4.1): Extracting archive
remote: - Installing psr/log (2.0.0): Extracting archive
remote: - Installing symfony/error-handler (v5.4.1): Extracting archive
remote: - Installing symfony/http-kernel (v5.4.1): Extracting archive
remote: - Installing voku/portable-ascii (1.5.6): Extracting archive
remote: - Installing phpoption/phpoption (1.8.1): Extracting archive
remote: - Installing graham-campbell/result-type (v1.0.4): Extracting archive
remote: - Installing vlucas/phpdotenv (v5.4.1): Extracting archive
remote: - Installing symfony/css-selector (v6.0.1): Extracting archive
remote: - Installing tijsverkoyen/css-to-inline-styles (2.2.4): Extracting archive
remote: - Installing symfony/routing (v5.4.0): Extracting archive
remote: - Installing symfony/process (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-php72 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-normalizer (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-idn (v1.23.0): Extracting archive
remote: - Installing symfony/mime (v5.4.0): Extracting archive
remote: - Installing symfony/finder (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-intl-grapheme (v1.23.1): Extracting archive
remote: - Installing symfony/string (v6.0.1): Extracting archive
remote: - Installing psr/container (1.1.2): Extracting archive
remote: - Installing symfony/service-contracts (v2.4.1): Extracting archive
remote: - Installing symfony/console (v5.4.1): Extracting archive
remote: - Installing symfony/polyfill-iconv (v1.23.0): Extracting archive
remote: - Installing egulias/email-validator (2.1.25): Extracting archive
remote: - Installing swiftmailer/swiftmailer (v6.3.0): Extracting archive
remote: - Installing symfony/polyfill-php81 (v1.23.0): Extracting archive
remote: - Installing ramsey/collection (1.2.2): Extracting archive
remote: - Installing brick/math (0.9.3): Extracting archive
remote: - Installing ramsey/uuid (4.2.3): Extracting archive
remote: - Installing psr/simple-cache (1.0.1): Extracting archive
remote: - Installing opis/closure (3.6.2): Extracting archive
remote: - Installing symfony/translation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/translation (v6.0.1): Extracting archive
remote: - Installing nesbot/carbon (2.55.2): Extracting archive
remote: - Installing monolog/monolog (2.3.5): Extracting archive
remote: - Installing league/mime-type-detection (1.9.0): Extracting archive
remote: - Installing league/flysystem (1.1.9): Extracting archive
remote: - Installing nette/utils (v3.2.6): Extracting archive
remote: - Installing nette/schema (v1.2.2): Extracting archive
remote: - Installing dflydev/dot-access-data (v3.0.1): Extracting archive
remote: - Installing league/config (v1.1.1): Extracting archive
remote: - Installing league/commonmark (2.1.0): Extracting archive
remote: - Installing laravel/serializable-closure (v1.0.5): Extracting archive
remote: - Installing laravel/framework (v8.76.2): Extracting archive
remote: - Installing asm89/stack-cors (v2.0.3): Extracting archive
remote: - Installing fruitcake/laravel-cors (v2.0.4): Extracting archive
remote: - Installing psr/http-message (1.0.1): Extracting archive
remote: - Installing psr/http-client (1.0.1): Extracting archive
remote: - Installing ralouphie/getallheaders (3.0.3): Extracting archive
remote: - Installing psr/http-factory (1.0.1): Extracting archive
remote: - Installing guzzlehttp/psr7 (2.1.0): Extracting archive
remote: - Installing guzzlehttp/promises (1.5.1): Extracting archive
remote: - Installing guzzlehttp/guzzle (7.4.1): Extracting archive
remote: - Installing laravel/sanctum (v2.13.0): Extracting archive
remote: - Installing nikic/php-parser (v4.13.2): Extracting archive
remote: - Installing psy/psysh (v0.10.12): Extracting archive
remote: - Installing laravel/tinker (v2.6.3): Extracting archive
remote: Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
remote: Generating optimized autoload files
remote: > Illuminate\Foundation\ComposerScripts::postAutoloadDump
remote: > @php artisan package:discover --ansi
remote: Discovered Package: fruitcake/laravel-cors
remote: Discovered Package: laravel/sanctum
remote: Discovered Package: laravel/tinker
remote: Discovered Package: nesbot/carbon
remote: Package manifest generated successfully.
remote: 49 packages you are using are looking for funding.
remote: Use the `composer fund` command to find out more!
remote: -----> Preparing runtime environment...
remote: -----> Checking for additional extensions to install...
remote: -----> Discovering process types
remote:
remote: ! Push failed: cannot parse Procfile.
remote: ! Please try pushing again.
remote: ! If the problem persists, see https://help.heroku.com/ and provide Request ID 691561db-a116-53f5-a4e5-0100a3777ce9.
remote:
remote:
remote: !
remote: ! ## Warning - The same version of this code has already been built: a30f3dde79d674408b2fb440cda5f9dbeb2204fe
remote: !
remote: ! We have detected that you have triggered a build from source code with version a30f3dde79d674408b2fb440cda5f9dbeb2204fe
remote: ! at least twice. One common cause of this behavior is attempting to deploy code from a different branch.
remote: !
remote: ! If you are developing on a branch and deploying via git you must run:
remote: !
remote: ! git push heroku :main
remote: !
remote: ! This article goes into details on the behavior:
remote: ! https://devcenter.heroku.com/articles/duplicate-build-version
remote:
remote: Verifying deploy...
remote:
remote: ! Push rejected to secret-stream-72395.
remote:
To https://git.heroku.com/secret-stream-72395.git
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/secret-stream-72395.git'
PS E:\wwwroot\weibo>
24. I saved the file encoding as UTF-8. See Figure 21.

25. The push was successful, and opening the URL https://secret-stream-72395.herokuapp.com/ returned a 200 response. See Figure 22.

PS E:\wwwroot\weibo> git add .
PS E:\wwwroot\weibo> git commit -m "Procfile for Heroku"
[main 362c878] Procfile for Heroku
1 file changed, 0 insertions(+), 0 deletions(-)
PS E:\wwwroot\weibo> git push heroku main
Enumerating objects: 22, done.
Counting objects: 100% (22/22), done.
Delta compression using up to 4 threads
Compressing objects: 100% (19/19), done.
Writing objects: 100% (20/20), 1.84 KiB | 470.00 KiB/s, done.
Total 20 (delta 9), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpack: heroku/php
remote: -----> PHP app detected
remote: -----> Bootstrapping...
remote: -----> Installing platform packages...
remote: - php (8.1.1)
remote: - ext-mbstring (bundled with php)
remote: - composer (2.1.14)
remote: - apache (2.4.51)
remote: - nginx (1.20.2)
remote: -----> Installing dependencies...
remote: Composer version 2.1.14 2021-11-30 10:51:43
remote: Installing dependencies from lock file
remote: Verifying lock file contents can be installed on current platform.
remote: Package operations: 70 installs, 0 updates, 0 removals
remote: - Installing doctrine/inflector (2.0.4): Extracting archive
remote: - Installing doctrine/lexer (1.2.1): Extracting archive
remote: - Installing symfony/polyfill-ctype (v1.23.0): Extracting archive
remote: - Installing webmozart/assert (1.10.0): Extracting archive
remote: - Installing dragonmantank/cron-expression (v3.1.0): Extracting archive
remote: - Installing symfony/polyfill-php80 (v1.23.1): Extracting archive
remote: - Installing symfony/polyfill-php73 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-mbstring (v1.23.1): Extracting archive
remote: - Installing symfony/deprecation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/http-foundation (v5.4.1): Extracting archive
remote: - Installing psr/event-dispatcher (1.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher (v6.0.1): Extracting archive
remote: - Installing symfony/var-dumper (v5.4.1): Extracting archive
remote: - Installing psr/log (2.0.0): Extracting archive
remote: - Installing symfony/error-handler (v5.4.1): Extracting archive
remote: - Installing symfony/http-kernel (v5.4.1): Extracting archive
remote: - Installing voku/portable-ascii (1.5.6): Extracting archive
remote: - Installing phpoption/phpoption (1.8.1): Extracting archive
remote: - Installing graham-campbell/result-type (v1.0.4): Extracting archive
remote: - Installing vlucas/phpdotenv (v5.4.1): Extracting archive
remote: - Installing symfony/css-selector (v6.0.1): Extracting archive
remote: - Installing tijsverkoyen/css-to-inline-styles (2.2.4): Extracting archive
remote: - Installing symfony/routing (v5.4.0): Extracting archive
remote: - Installing symfony/process (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-php72 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-normalizer (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-idn (v1.23.0): Extracting archive
remote: - Installing symfony/mime (v5.4.0): Extracting archive
remote: - Installing symfony/finder (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-intl-grapheme (v1.23.1): Extracting archive
remote: - Installing symfony/string (v6.0.1): Extracting archive
remote: - Installing psr/container (1.1.2): Extracting archive
remote: - Installing symfony/service-contracts (v2.4.1): Extracting archive
remote: - Installing symfony/console (v5.4.1): Extracting archive
remote: - Installing symfony/polyfill-iconv (v1.23.0): Extracting archive
remote: - Installing egulias/email-validator (2.1.25): Extracting archive
remote: - Installing swiftmailer/swiftmailer (v6.3.0): Extracting archive
remote: - Installing symfony/polyfill-php81 (v1.23.0): Extracting archive
remote: - Installing ramsey/collection (1.2.2): Extracting archive
remote: - Installing brick/math (0.9.3): Extracting archive
remote: - Installing ramsey/uuid (4.2.3): Extracting archive
remote: - Installing psr/simple-cache (1.0.1): Extracting archive
remote: - Installing opis/closure (3.6.2): Extracting archive
remote: - Installing symfony/translation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/translation (v6.0.1): Extracting archive
remote: - Installing nesbot/carbon (2.55.2): Extracting archive
remote: - Installing monolog/monolog (2.3.5): Extracting archive
remote: - Installing league/mime-type-detection (1.9.0): Extracting archive
remote: - Installing league/flysystem (1.1.9): Extracting archive
remote: - Installing nette/utils (v3.2.6): Extracting archive
remote: - Installing nette/schema (v1.2.2): Extracting archive
remote: - Installing dflydev/dot-access-data (v3.0.1): Extracting archive
remote: - Installing league/config (v1.1.1): Extracting archive
remote: - Installing league/commonmark (2.1.0): Extracting archive
remote: - Installing laravel/serializable-closure (v1.0.5): Extracting archive
remote: - Installing laravel/framework (v8.76.2): Extracting archive
remote: - Installing asm89/stack-cors (v2.0.3): Extracting archive
remote: - Installing fruitcake/laravel-cors (v2.0.4): Extracting archive
remote: - Installing psr/http-message (1.0.1): Extracting archive
remote: - Installing psr/http-client (1.0.1): Extracting archive
remote: - Installing ralouphie/getallheaders (3.0.3): Extracting archive
remote: - Installing psr/http-factory (1.0.1): Extracting archive
remote: - Installing guzzlehttp/psr7 (2.1.0): Extracting archive
remote: - Installing guzzlehttp/promises (1.5.1): Extracting archive
remote: - Installing guzzlehttp/guzzle (7.4.1): Extracting archive
remote: - Installing nikic/php-parser (v4.13.2): Extracting archive
remote: - Installing psy/psysh (v0.10.12): Extracting archive
remote: - Installing laravel/tinker (v2.6.3): Extracting archive
remote: Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
remote: Generating optimized autoload files
remote: > Illuminate\Foundation\ComposerScripts::postAutoloadDump
remote: > @php artisan package:discover --ansi
remote: Discovered Package: fruitcake/laravel-cors
remote: Discovered Package: laravel/sanctum
remote: Discovered Package: laravel/tinker
remote: Discovered Package: nesbot/carbon
remote: Package manifest generated successfully.
remote: 49 packages you are using are looking for funding.
remote: Use the `composer fund` command to find out more!
remote: -----> Preparing runtime environment...
remote: -----> Checking for additional extensions to install...
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 19.8M
remote: -----> Launching...
remote: Released v6
remote: https://secret-stream-72395.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/secret-stream-72395.git
e72b466..362c878 main -> main
PS E:\wwwroot\weibo> heroku open
» Warning: heroku update available from 7.53.0 to 7.59.2.
PS E:\wwwroot\weibo>
26. However, when submitting the form to write data to MySQL, it returned a 500 server error because the database did not exist yet. See Figure 23.

27. I used PostgreSQL on Heroku as the database for our app. I installed the PostgreSQL add-on. Heroku generated a unique database URL, DATABASE_URL, for us. We can view all of Heroku’s configuration information using the command: heroku config. See Figure 24.

PS E:\wwwroot\weibo> heroku addons:add heroku-postgresql:hobby-dev
» Warning: heroku update available from 7.53.0 to 7.59.2.
Creating heroku-postgresql:hobby-dev on ⬢ secret-stream-72395... free
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pg:copy
Created postgresql-parallel-13694 as DATABASE_URL
Use heroku addons:docs heroku-postgresql to view documentation
PS E:\wwwroot\weibo> heroku config
» Warning: heroku update available from 7.53.0 to 7.59.2.
=== secret-stream-72395 Config Vars
APP_KEY: base64:TXoum9anbYcE/VGilCjxrSQQ5E4cR5UVb+55SjIsbg0=
DATABASE_URL: postgres://eayusxxdstiniz:31d9e092c4c8d1740380641299d36711b04e72b98e2f92b9be4253153087bbea@ec2-52-200-28-255.compute-1.amazonaws.com:5432/d9nb3l2ot2cutp
PS E:\wwwroot\weibo>
28. In local development, we used MySQL as the database storage, but in the Heroku environment, we need to switch to PostgreSQL. Therefore, when configuring the database, we need to determine the current environment. If it is the local environment, use the MySQL database; if it is the Heroku environment, use the PostgreSQL database. We can determine whether the app is running on Heroku by adding a new IS_IN_HEROKU configuration option for Heroku. Generally, the app’s database is configured in config/database.php, so we need to define a helper method for the database connection methods of different environments within this configuration file. This allows us to specify the database configuration information based on the app’s different runtime environments. We need to create a new helpers.php file and write the following content:
<?php
function get_db_config()
{
if (getenv('IS_IN_HEROKU')) {
$url = parse_url(getenv("DATABASE_URL"));
return $db_config = [
'connection' => 'pgsql',
'host' => $url["host"],
'database' => substr($url["path"], 1),
'username' => $url["user"],
'password' => $url["pass"],
];
} else {
return $db_config = [
'connection' => env('DB_CONNECTION', 'mysql'),
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
];
}
}29. After adding the helpers.php file, you also need to add this file to the files field under the autoload option in the composer.json file located in the project root directory. See Figure 25.

"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
},
"files": [
"app/helpers.php"
]
},
30. After saving the modifications, run the following command to reload the files. If this might affect the operation of the local environment, it is recommended to execute the corresponding command within the Sail environment. See Figure 26.

wangqiang@DESKTOP-QLPK8QM:/mnt/e/wwwroot/weibo$ sail composer dump-autoload
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: laravel/ui
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Discovered Package: overtrue/laravel-lang
Package manifest generated successfully.
Generated optimized autoload files containing 5027 classes
wangqiang@DESKTOP-QLPK8QM:/mnt/e/wwwroot/weibo$
31. Now, let’s configure the database using the get_db_config method we just defined. Adjust the database configuration file; there are a total of 2 changes. See Figure 28.

<?php
use Illuminate\Support\Str;
$db_config = get_db_config();
return [
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for all database work. Of course
| you may use many connections at once using the Database library.
|
*/
'default' => $db_config['connection'],32. Commit the modified code, and push it to GitHub and Heroku.
wangqiang@DESKTOP-QLPK8QM:/mnt/e/wwwroot/weibo$ git push
Enumerating objects: 12, done.
Counting objects: 100% (12/12), done.
Delta compression using up to 4 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 936 bytes | 58.00 KiB/s, done.
Total 7 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), completed with 5 local objects.
To https://github.com/shuijingwan/weibo.git
876eb29..173fc8d sign-up -> sign-up
wangqiang@DESKTOP-QLPK8QM:/mnt/e/wwwroot/weibo$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
wangqiang@DESKTOP-QLPK8QM:/mnt/e/wwwroot/weibo$ git merge sign-up
Merge made by the 'recursive' strategy.
app/helpers.php | 24 ++++++++++++++++++++++++
composer.json | 5 ++++-
config/database.php | 4 +++-
3 files changed, 31 insertions(+), 2 deletions(-)
create mode 100644 app/helpers.php
wangqiang@DESKTOP-QLPK8QM:/mnt/e/wwwroot/weibo$ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 300 bytes | 33.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/shuijingwan/weibo.git
cd4e270..1e23962 main -> main
wangqiang@DESKTOP-QLPK8QM:/mnt/e/wwwroot/weibo$
PS E:\wwwroot\weibo> git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
PS E:\wwwroot\weibo> git push heroku main
Enumerating objects: 19, done.
Counting objects: 100% (15/15), done.
Delta compression using up to 4 threads
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 1.13 KiB | 576.00 KiB/s, done.
Total 9 (delta 6), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpack: heroku/php
remote: -----> PHP app detected
remote: -----> Bootstrapping...
remote: -----> Installing platform packages...
remote: - php (8.1.1)
remote: - ext-mbstring (bundled with php)
remote: - composer (2.1.14)
remote: - apache (2.4.51)
remote: - nginx (1.20.2)
remote: -----> Installing dependencies...
remote: Composer version 2.1.14 2021-11-30 10:51:43
remote: Installing dependencies from lock file
remote: Verifying lock file contents can be installed on current platform.
remote: Package operations: 72 installs, 0 updates, 0 removals
remote: - Installing doctrine/inflector (2.0.4): Extracting archive
remote: - Installing doctrine/lexer (1.2.1): Extracting archive
remote: - Installing symfony/polyfill-ctype (v1.23.0): Extracting archive
remote: - Installing webmozart/assert (1.10.0): Extracting archive
remote: - Installing dragonmantank/cron-expression (v3.1.0): Extracting archive
remote: - Installing symfony/polyfill-php80 (v1.23.1): Extracting archive
remote: - Installing symfony/polyfill-php73 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-mbstring (v1.23.1): Extracting archive
remote: - Installing symfony/deprecation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/http-foundation (v5.4.1): Extracting archive
remote: - Installing psr/event-dispatcher (1.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/event-dispatcher (v6.0.1): Extracting archive
remote: - Installing symfony/var-dumper (v5.4.1): Extracting archive
remote: - Installing psr/log (2.0.0): Extracting archive
remote: - Installing symfony/error-handler (v5.4.1): Extracting archive
remote: - Installing symfony/http-kernel (v5.4.1): Extracting archive
remote: - Installing voku/portable-ascii (1.5.6): Extracting archive
remote: - Installing phpoption/phpoption (1.8.1): Extracting archive
remote: - Installing graham-campbell/result-type (v1.0.4): Extracting archive
remote: - Installing vlucas/phpdotenv (v5.4.1): Extracting archive
remote: - Installing symfony/css-selector (v6.0.1): Extracting archive
remote: - Installing tijsverkoyen/css-to-inline-styles (2.2.4): Extracting archive
remote: - Installing symfony/routing (v5.4.0): Extracting archive
remote: - Installing symfony/process (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-php72 (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-normalizer (v1.23.0): Extracting archive
remote: - Installing symfony/polyfill-intl-idn (v1.23.0): Extracting archive
remote: - Installing symfony/mime (v5.4.0): Extracting archive
remote: - Installing symfony/finder (v5.4.0): Extracting archive
remote: - Installing symfony/polyfill-intl-grapheme (v1.23.1): Extracting archive
remote: - Installing symfony/string (v6.0.1): Extracting archive
remote: - Installing psr/container (1.1.2): Extracting archive
remote: - Installing symfony/service-contracts (v2.4.1): Extracting archive
remote: - Installing symfony/console (v5.4.1): Extracting archive
remote: - Installing symfony/polyfill-iconv (v1.23.0): Extracting archive
remote: - Installing egulias/email-validator (2.1.25): Extracting archive
remote: - Installing swiftmailer/swiftmailer (v6.3.0): Extracting archive
remote: - Installing symfony/polyfill-php81 (v1.23.0): Extracting archive
remote: - Installing ramsey/collection (1.2.2): Extracting archive
remote: - Installing brick/math (0.9.3): Extracting archive
remote: - Installing ramsey/uuid (4.2.3): Extracting archive
remote: - Installing psr/simple-cache (1.0.1): Extracting archive
remote: - Installing opis/closure (3.6.2): Extracting archive
remote: - Installing symfony/translation-contracts (v3.0.0): Extracting archive
remote: - Installing symfony/translation (v6.0.1): Extracting archive
remote: - Installing nesbot/carbon (2.55.2): Extracting archive
remote: - Installing monolog/monolog (2.3.5): Extracting archive
remote: - Installing league/mime-type-detection (1.9.0): Extracting archive
remote: - Installing league/flysystem (1.1.9): Extracting archive
remote: - Installing nette/utils (v3.2.6): Extracting archive
remote: - Installing nette/schema (v1.2.2): Extracting archive
remote: - Installing dflydev/dot-access-data (v3.0.1): Extracting archive
remote: - Installing league/config (v1.1.1): Extracting archive
remote: - Installing league/commonmark (2.1.0): Extracting archive
remote: - Installing laravel/serializable-closure (v1.0.5): Extracting archive
remote: - Installing laravel/framework (v8.76.2): Extracting archive
remote: - Installing asm89/stack-cors (v2.0.3): Extracting archive
remote: - Installing fruitcake/laravel-cors (v2.0.4): Extracting archive
remote: - Installing psr/http-message (1.0.1): Extracting archive
remote: - Installing psr/http-client (1.0.1): Extracting archive
remote: - Installing ralouphie/getallheaders (3.0.3): Extracting archive
remote: - Installing psr/http-factory (1.0.1): Extracting archive
remote: - Installing guzzlehttp/psr7 (2.1.0): Extracting archive
remote: - Installing guzzlehttp/promises (1.5.1): Extracting archive
remote: - Installing guzzlehttp/guzzle (7.4.1): Extracting archive
remote: - Installing laravel/sanctum (v2.13.0): Extracting archive
remote: - Installing nikic/php-parser (v4.13.2): Extracting archive
remote: - Installing psy/psysh (v0.10.12): Extracting archive
remote: - Installing laravel/tinker (v2.6.3): Extracting archive
remote: - Installing laravel-lang/lang (5.0.0): Extracting archive
remote: - Installing overtrue/laravel-lang (4.2.2): Extracting archive
remote: Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
remote: Generating optimized autoload files
remote: > Illuminate\Foundation\ComposerScripts::postAutoloadDump
remote: > @php artisan package:discover --ansi
remote: Discovered Package: fruitcake/laravel-cors
remote: Discovered Package: laravel/sanctum
remote: Discovered Package: laravel/tinker
remote: Discovered Package: nesbot/carbon
remote: Discovered Package: overtrue/laravel-lang
remote: Package manifest generated successfully.
remote: 50 packages you are using are looking for funding.
remote: Use the `composer fund` command to find out more!
remote: -----> Preparing runtime environment...
remote: -----> Checking for additional extensions to install...
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 19.9M
remote: -----> Launching...
remote: Released v10
remote: https://secret-stream-72395.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/secret-stream-72395.git
cd4e270..1e23962 main -> main
PS E:\wwwroot\weibo>
33. We can use heroku run to execute specific Laravel commands on Heroku. Now we need to run the migration on Heroku to generate the users table, which can be done with the following command. It returned an error: SQLSTATE[22023]: Invalid parameter value: 7 ERROR: invalid value for parameter “client_encoding”: “utf8mb4”. See Figure 28.
![We can use heroku run to execute specific Laravel commands on Heroku. Now we need to run the migration on Heroku to generate the users table, which can be done with the following command. It returned an error: SQLSTATE[22023]: Invalid parameter value: 7 ERROR: invalid value for parameter "client_encoding": "utf8mb4".](https://media.shuijingwanwq.com/2021/12/28-1.png)
PS E:\wwwroot\weibo> heroku run php artisan migrate
» Warning: heroku update available from 7.53.0 to 7.59.2.
Running php artisan migrate on ⬢ secret-stream-72395... up, run.1841 (Free)
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) [no]:
> yes
In Connection.php line 703:
SQLSTATE[22023]: Invalid parameter value: 7 ERROR: invalid value for parameter "client_encoding": "utf8mb4" (SQL:
select * from information_schema.tables where table_schema = public and table_name = migrations and table_type = 'B
ASE TABLE')
In PostgresConnector.php line 68:
SQLSTATE[22023]: Invalid parameter value: 7 ERROR: invalid value for parameter "client_encoding": "utf8mb4"
PS E:\wwwroot\weibo>
34. I adjusted the database configuration file again; the pgsql-related configuration had not been modified previously.
'pgsql' => [
'driver' => 'pgsql',
'host' => $db_config['host'],
'port' => env('DB_PORT', '5432'),
'database' => $db_config['database'],
'username' => $db_config['username'],
'password' => $db_config['password'],
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'schema' => 'public',
'sslmode' => 'prefer',
],
35. I executed the command: heroku config:add DB_CONNECTION=pgsql . When running the migration again, the error was different:
» Warning: heroku update available from 7.53.0 to 7.59.2.
DB_CONNECTION: pgsql
PS E:\wwwroot\weibo> heroku run php artisan migrate
» Warning: heroku update available from 7.53.0 to 7.59.2.
Running php artisan migrate on ⬢ secret-stream-72395... up, run.7170 (Free)
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) [no]:
> yes
In Connection.php line 703:
SQLSTATE[08006] [7] connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections? (SQL: select * from information_schema.tables
where table_schema = public and table_name = migrations and table_type = 'BASE TABLE')
In Connector.php line 70:
SQLSTATE[08006] [7] connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
PS E:\wwwroot\weibo> git push heroku main
Everything up-to-date
PS E:\wwwroot\weibo> heroku run php artisan migrate
» Warning: heroku update available from 7.53.0 to 7.59.2.
Running php artisan migrate on ⬢ secret-stream-72395... up, run.6564 (Free)
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) [no]:
> yes
In Connection.php line 703:
SQLSTATE[08006] [7] connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections? (SQL: select * from information_schema.tables
where table_schema = public and table_name = migrations and table_type = 'BASE TABLE')
In Connector.php line 70:
SQLSTATE[08006] [7] connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
PS E:\wwwroot\weibo>
36. Finally, I found the root cause: I had missed adding an IS_IN_HEROKU configuration option on Heroku to determine whether the app is running on Heroku. The migration was successful. See Figure 29.

PS E:\wwwroot\weibo> heroku config:set IS_IN_HEROKU=true
» Warning: heroku update available from 7.53.0 to 7.59.2.
Setting IS_IN_HEROKU and restarting ⬢ secret-stream-72395... done, v16
IS_IN_HEROKU: true
PS E:\wwwroot\weibo> heroku run php artisan migrate
» Warning: heroku update available from 7.53.0 to 7.59.2.
Running php artisan migrate on ⬢ secret-stream-72395... up, run.3491 (Free)
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) [no]:
> yes
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (850.26ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (466.16ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (902.11ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated: 2019_12_14_000001_create_personal_access_tokens_table (1,079.00ms)
PS E:\wwwroot\weibo>
37. I submitted the form data again, and the submission was successful. See Figure 30.

38. Use heroku rename to change the app name, but make sure the new name is not already taken by someone else. See Figure 31.

PS E:\wwwroot\weibo> heroku rename app-wangqiang-weibo
» Warning: heroku update available from 7.53.0 to 7.59.2.
Renaming secret-stream-72395 to app-wangqiang-weibo... done
https://app-wangqiang-weibo.herokuapp.com/ | https://git.heroku.com/app-wangqiang-weibo.git
! Don't forget to update git remotes for all other local checkouts of the app.
Git remote heroku updated
PS E:\wwwroot\weibo>
39. Opening https://app-wangqiang-weibo.herokuapp.com/ returns a 200 response. This is as expected. See Figure 32.

40. Opening https://secret-stream-72395.herokuapp.com/ returns a 404 response. There’s nothing here, yet. This is as expected. See Figure 33.

