I recently performed a rather large update to this web app, and for the most part it went off without a hitch... Until the app tries to send an SMS notification from staging/production.
The upgrade from laravel 7.x to 8.x was quite simple and straightforward. At the same time we also installed Laravel Horizon. Everything went according to plan, and all works fine locally.
When we deploy to staging/production however, queued SMS notifications fail with the following exception:
ReflectionException: Class Http\Adapter\Guzzle6\Client does not exist in /home/forge/dev.example.com/releases/20210609194554/vendor/laravel/framework/src/Illuminate/Container/Container.php:836
Looking in the stack trace we can see that Nexmo is the culprit:
#5 /home/forge/dev.example.com/releases/20210609194554/vendor/nexmo/laravel/src/NexmoServiceProvider.php(150): Illuminate\Foundation\Application->make()
However in our composer.json file we are requiring Guzzle 7 with the following:
"guzzlehttp/guzzle": "^7.3",
It is worth mentioning again at this point, I have no issues sending SMS locally, the main difference between local and staging environments is that locally I use Laravel Valet and Staging uses Laravel Envoyer.
What I've tried so far:
- Changing
"guzzlehttp/guzzle": "^7.3"
to"guzzlehttp/guzzle": "^6.5|^7.3"
- Running
php artisan horizon:purge
andphp artisan horizon:terminate
both manually and in a deployment hook. - Restarting the laravel horizon daemon on forge.
- trying
php artisan queue:restart
- running
composer dump-autoload
andcomposer dump-autoload -o
- deleting composer.lock and the vendor/ directory from current/ then running
composer install
- Restarting PHP, Nginx, and eventually the entire server :(
and more...
Any help is greatly appreciated
UPDATE Below:
Complete composer.json:
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=7.4.1",
"arrilot/laravel-widgets": "^3.13",
"barryvdh/laravel-snappy": "^0.4.6",
"doctrine/dbal": "^2.10",
"facade/ignition": "^2.3.6",
"guzzlehttp/guzzle": "^7.3",
"intervention/image": "^2.4",
"laravel/framework": "^8.0",
"laravel/helpers": "^1.3",
"laravel/horizon": "^5.7",
"laravel/nexmo-notification-channel": "^2.5.1",
"laravel/passport": "^10.0",
"laravel/slack-notification-channel": "^2.0",
"laravel/telescope": "^4.0",
"laravel/tinker": "^2.0",
"laravel/ui": "^3.0",
"league/csv": "^8.2",
"league/flysystem-aws-s3-v3": "~1.0",
"maatwebsite/excel": "^3.1",
"milon/barcode": "^8.0.1",
"nexmo/laravel": "^2.4.1",
"nunomaduro/collision": "^5.0",
"predis/predis": "^1.1",
"pusher/pusher-php-server": "^4.1.1",
"webpatser/laravel-uuid": "^3.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "^9.0",
"filp/whoops": "~2.0"
},
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"post-root-package-install": [
"php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"php artisan key:generate"
],
"post-install-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postInstall"
],
"post-update-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postUpdate"
],
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover"
]
},
"config": {
"preferred-install": "dist",
"sort-packages": true
}
}
Additionally my nexmo config file does not have anything for http_client, maybe it's an upgrade step I missed somewhere along the line. As such, I have nothing in my .env file for nexmo's http_client. I will begin looking into this as well.
nexmo.php
<?php
return [
/*
|--------------------------------------------------------------------------
| API Credentials
|--------------------------------------------------------------------------
|
| If you're using API credentials, change these settings. Get your
| credentials from https://dashboard.nexmo.com | 'Settings'.
|
*/
'api_key' => function_exists('env') ? env('NEXMO_KEY', '') : '',
'api_secret' => function_exists('env') ? env('NEXMO_SECRET', '') : '',
/*
|--------------------------------------------------------------------------
| Signature Secret
|--------------------------------------------------------------------------
|
| If you're using a signature secret, use this section. This can be used
| without an `api_secret` for some APIs, as well as with an `api_secret`
| for all APIs.
|
*/
'signature_secret' => function_exists('env') ? env('NEXMO_SIGNATURE_SECRET', '') : '',
/*
|--------------------------------------------------------------------------
| Private Key
|--------------------------------------------------------------------------
|
| Private keys are used to generate JWTs for authentication. Generation is
| handled by the library. JWTs are required for newer APIs, such as voice
| and media
|
*/
'private_key' => function_exists('env') ? env('NEXMO_PRIVATE_KEY', '') : '',
'application_id' => function_exists('env') ? env('NEXMO_APPLICATION_ID', '') : '',
/*
|----------------------------------------------------------------------------
| Phone Numbers
|----------------------------------------------------------------------------
|
| Phone numbers to be used by the application.
*/
'number' => env('NEXMO_NUMBER'),
'batch' => env('NEXMO_BATCH'),
];
I see that the
NexmoServiceProvider
is trying to use the definedhttp_client
in the config, so can you share what the.env
has forNEXMO_HTTP_CLIENT
? I am pretty sure you have something wrong there or even not defined.And this is what it is defined in the
config/nexmo.php
related to that config: