Using configureMonologUsing after Laravel 5.7 upgrade - Supervisor Logging Permission - php

I am trying to upgrade my Laravel 5.5 project to 5.7. I use supervisor and before I was using configureMonologUsing() to generate the logs but apparently with 5.6 upgrade, it got depreciated. My full code in L5.5 was: in bootstrap/app.php:
$app->configureMonologUsing( function( Monolog\Logger $monolog) {
$processUser = posix_getpwuid( posix_geteuid() );
$processName= $processUser[ 'name' ];
$filename = storage_path( 'logs/laravel-' . php_sapi_name() . '-' . $processName . '.log' );
$handler = new Monolog\Handler\RotatingFileHandler( $filename );
$monolog->pushHandler( $handler );
});
And it was generating various loggers like (which was convenient):
laravel-cli-root-{date},
laravel-cli-ubuntu-{date},
laravel-cli-www-data-{date},
laravel-fpm-fcgi-www-data-{date}, etc...
However, it says in the upgrade guide so I can't use configureMonologUsing any more:
The configureMonologUsing Method
If you were using the configureMonologUsing method to customize the Monolog instance for your application, you should now create a custom Log channel. For more information on how to create custom channels, check out the full logging documentation.
I couldn't figure out how to achieve the same with logging channels. How can I utilise Monolog Channel to be able to write laravel/storage/logs folder?

Taken from https://stackoverflow.com/a/49379249/4705339
Laravel version 5.6.10 and later has support for a permission element in the configuration (config/logging.php) for the single and the daily driver:
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 7,
'permission' => 0664, // this line lets the file owner to be www-data:www-data
],
No need to juggle with Monolog in the bootstrap script.
Specifically, support was added in https://github.com/laravel/framework/commit/4d31633dca9594c9121afbbaa0190210de28fed8.

Related

Laravel - Nexmo not picking up credentials in .ENV file

I recently added laravel/nexmo-notification-channel to my laravel project which also installed Nexmo/nexmo-laravel.
After installing, I published vendor files so that I get config/nexmo.php and in there I noted that it looks in the .env file for NEXMO_KEY and NEXMO_SECRET.
So I went ahead and created these within my .env file
NEXMO_KEY=[my_key]
NEXMO_SECRET=[my secret]
NEXMO_SIGNATURE_SECRET=[my signature secret]
After this, I added Nexmo to my service providers in app.php:
'providers' => [
...,
Nexmo\Laravel\NexmoServiceProvider::class
]
and also added the following in config/services.php:
'nexmo' => [
'key' => env('NEXMO_KEY', ''),
'secret' => env('NEXMO_SECRET', ''),
'sms_from' => '[my number]'
],
But I still get the following error when thrying to send an SMS using the use Illuminate\Notifications\Messages\NexmoMessage; class:
"message": "Provide either nexmo.api_secret or nexmo.signature_secret",
I can use these same credentials to send an SMS from CLI, so why can't I send it from laravel?
There have been a couple of workarounds for this that are valid, but at first glance it looks like the Nexmo package does the work to bring in the ENV secrets into Laravel's config. Because of caching problems, you should never call env() within Laravel, instead you should be using config() - so in this case, config(nexmo.api_secret).
My main point here though is that I can't look into the "correct" solution for you because the package is abandoned. Nexmo is no longer Nexmo, it's Vonage, and Laravel core team have subsequently updated the notification-channel package.
For supported use to integrate Vonage services (SMS), please use the following package:
https://github.com/laravel/vonage-notification-channel
I'm not sure exactly why, but, Vonage/Nexmo doesn't pick details from the .ENV.
Instead, use a global constant to fetch the secrets:
Create a global.php file in the config folder, and add your secrets from the env like this:
<?php
return [
// Other constants values
'SMS_API_KEY' => env('SMS_API_KEY', ''),
'SMS_API_SECRET' => env('SMS_API_SECRET', ''),
]
?>
Then, you can use the constants in your controller as usual:
'key' => config('global.SMS_API_KEY'),
'secret' => config('global.SMS_API_SECRET')
then: recache, php artisan config:cache

Laravel not publishing to Redis

I am trying to implement Redis publishing in my local RESTful API which is built in Laravel for the purposes of implementing a chat system later on with Web Sockets. I intend to read them from a Node.JS server later on.
I am using Redis::publish to publish a simple message to my test-channel.
However, for some reason Laravel doesn't seem to publish to it.
I have also noticed that when I call Redis::set, whatever I set doesn't get persisted in Redis, but using Redis::get I can read the values that I'm setting.
public function redis(Request $request) {
$data = $request->validate([
'message' => 'string|required'
]);
Redis::publish('test-channel', 'a test message');
return 'Done';
}
I am using the code above in the api/redis route:
Route::post('/redis', 'API\MessageController#redis');
I have subscribed to the test-channel using the redis-cli command.
If I manually publish a message to the test-channel using the redis-cli in a terminal instance, I properly receive the messages that I am publishing. However, they don't seem to get published with Laravel for some reason.
What I can notice while running php artisan serve and visiting the aforementioned route is Laravel logging the following:
[*timestamp*] 127.0.0.1:39448 Accepted
[*timestamp*] 127.0.0.1:39448 Closing
The port after 127.0.0.1 appears to be random.
I tried both php-redis php extension and the predis package, just to be sure that it isn't any one of them, but I get the same result with both of them. I am currently using php-redis with both igbinary and redis extensions enabled in /etc/php/config.d and have removed the Redis alias from config/app.php.
I am using PHP 7.4, Laravel 6.0 and Redis 5.0.7 on Manjaro.
Been there, discovered that with:
$ redis-client
psubscribe *
will show you what's going on.
Chances are that your default config/database.php contains something like:
'redis' => [
'client' => env('REDIS_CLIENT', 'predis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
In that case, the channel name will be prefixed with this prefix option.
So you can just comment this option, or, if you keep it, be sure to subscribe to the right channel
Redis::publish('test-channel', 'a test message');
$prefix = config('database.redis.options.prefix');
$channel = $prefix . 'test-channel';
return "Done. (published on $channel)";

Setting up Chrome Logger Using Laravel Isn't Working

I'm trying to set up Chrome Logger to use alongside Laravel as detailed in "Easy Laravel 5", however following the instructions throws errors, and I'm new to Laravel (and not very experienced in PHP), so I'm not sure how to resolve them. We are directed to add a piece of code to the bootstrap/app.php file to use the chrome logger in the book.
The following is a screenshot of the error screen:
The following is the site without the code excerpt:
I tried requiring the chrome.php file using require_once() in the app.php file, but the error still persists. Removing the code excerpt produces the default screen.
This is the code excerpt:
if ($app->environment('local'))
{
$app->configureMonologUsing(function($monolog)
{
$monolog->pushHandler(new \Monolog\Handler\ChromePHPHandler());
});
}
I expected to be able to use the chrome logger, but instead receive the aforementioned error screen.
Add new channel in your configuration file (config/logging.php):
'chrome' => [
'driver' => 'monolog',
'handler' => \Monolog\Handler\ChromePHPHandler::class,
'formatter' => \Monolog\Formatter\ChromePHPFormatter::class
]
Sometimes you may wish to log a message to a channel other than your application's default channel. You may use the channel method on the Log facade to retrieve and log to any channel defined in your configuration file:
Log::channel('chrome')->info('Something happened!');
If you would like to create an on-demand logging stack consisting of multiple channels, you may use the stack method:
Log::stack(['single', 'chrome'])->info('Something happened!');
You can set new channel by default in your .env file
LOG_CHANNEL=chrome
or you can set
LOG_CHANNEL=stack
and change 'stack' list of channels (config/logging.php) like this:
'stack' => [
'driver' => 'stack',
'channels' => ['single', 'chrome'],
'ignore_exceptions' => false
]
After you can use log with all your list of channels
Log::info('General information log');
From Laravel 5.6 documentation.
The configureMonologUsing Method
If you were using the configureMonologUsing method to customize the
Monolog instance for your application, you should now create a custom
Log channel. For more information on how to create custom channels,
check out the full logging documentation.
Looks like we need to be on the earlier version for this to work.

ZF3 - composer require module -> module could not be initialised

I am working with the skeleton-application as a base, using the Vagrant / Composer setup. After the initial install I realised I would need the LDAP module. I then ran composer require zendframework/zend-ldap which ran successfully and I have located the files in ~/vendor/zendframework/zend-ldap.
The issue is when I add 'Zend\Ldap' to my ~/config/modules.config.php I encounter the following error:
Fatal error: Uncaught Zend\ModuleManager\Exception\RuntimeException: Module (Zend\Ldap) could not be initialized. in /var/www/vendor/zendframework/zend-modulemanager/src/ModuleManager.php:203 Stack trace: #0 /var/www/vendor/zendframework/zend-modulemanager/src/ModuleManager.php(175): Zend\ModuleManager\ModuleManager->loadModuleByName(Object(Zend\ModuleManager\ModuleEvent))
#1 /var/www/vendor/zendframework/zend-modulemanager/src/ModuleManager.php(97): Zend\ModuleManager\ModuleManager->loadModule('Zend\\Ldap') #2 /var/www/vendor/zendframework/zend-eventmanager/src/EventManager.php(322): Zend\ModuleManager\ModuleManager->onLoadModules(Object(Zend\ModuleManager\ModuleEvent))
#3 /var/www/vendor/zendframework/zend-eventmanager/src/EventManager.php(171): Zend\EventManager\EventManager->triggerListeners(Object(Zend\ModuleManager\ModuleEvent))
#4 /var/www/vendor/zendframework/zend-modulemanager/src/ModuleManager.php(120): Zend\EventManager\EventManager->triggerEvent(Object(Zend\ModuleManager\ModuleEvent))
#5 /var/www/vendor/zendfr in /var/www/vendor/zendframework/zend-modulemanager/src/ModuleManager.php on line 203
The ~/config/modules.config.php file:
/**
* List of enabled modules for this application.
*
* This should be an array of module namespaces used in the application.
*/
return [
'Zend\Session',
'Zend\Mvc\Plugin\Prg',
'Zend\Mvc\Plugin\Identity',
'Zend\Mvc\Plugin\FlashMessenger',
'Zend\Mvc\Plugin\FilePrg',
'Zend\Log',
'Zend\Form',
'Zend\Db',
'Zend\Router',
'Zend\Validator',
'Zend\Ldap', // All is well if this is commented out
'Application',
];
and the ~/config/application.config.php file:
/**
* If you need an environment-specific system or application configuration,
* there is an example in the documentation
* #see https://docs.zendframework.com/tutorials/advanced-config/#environment-specific-system-configuration
* #see https://docs.zendframework.com/tutorials/advanced-config/#environment-specific-application-configuration
*/
return [
// Retrieve list of modules used in this application.
'modules' => require __DIR__ . '/modules.config.php',
// These are various options for the listeners attached to the ModuleManager
'module_listener_options' => [
// This should be an array of paths in which modules reside.
// If a string key is provided, the listener will consider that a module
// namespace, the value of that key the specific path to that module's
// Module class.
'module_paths' => [
'./module',
'./vendor',
],
// An array of paths from which to glob configuration files after
// modules are loaded. These effectively override configuration
// provided by modules themselves. Paths may use GLOB_BRACE notation.
'config_glob_paths' => [
realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php',
],
// Whether or not to enable a configuration cache.
// If enabled, the merged configuration will be cached and used in
// subsequent requests.
'config_cache_enabled' => true,
// The key used to create the configuration cache file name.
'config_cache_key' => 'application.config.cache',
// Whether or not to enable a module class map cache.
// If enabled, creates a module class map cache which will be used
// by in future requests, to reduce the autoloading process.
'module_map_cache_enabled' => true,
// The key used to create the class map cache file name.
'module_map_cache_key' => 'application.module.cache',
// The path in which to cache merged configuration.
'cache_dir' => 'data/cache/',
// Whether or not to enable modules dependency checking.
// Enabled by default, prevents usage of modules that depend on other modules
// that weren't loaded.
// 'check_dependencies' => true,
],
// Used to create an own service manager. May contain one or more child arrays.
// 'service_listener_options' => [
// [
// 'service_manager' => $stringServiceManagerName,
// 'config_key' => $stringConfigKey,
// 'interface' => $stringOptionalInterface,
// 'method' => $stringRequiredMethodName,
// ],
// ],
// Initial configuration with which to seed the ServiceManager.
// Should be compatible with Zend\ServiceManager\Config.
// 'service_manager' => [],
];
I have tried removing cache folder, running composer update, restarting Vagrant, adding the full path to the 'modules_path' array in application.config.php but it is always the same error. Interestingly I run into the same issue with 'Zend\View' that was included from the install, but a module such as 'Zend\Session' can be added to the modules.config.php file with no issues (They are all located in the vendor/zendframework directory)
Can anyone point me in the right direction to resolve this issue?
Zend\Ldap is one of the ZF components. As it does not have a Module.php in its /src directory which is mandatory for a module. So you do not need to initialize like other modules through modules.config.php to use it in your application.
This component is not included as required with default installation of ZF. So if you want to use any component, you must add them to autoloader. Once you added a component like this one composer require zendframework/zend-ldap in your project, you would then be able to use it.
Check this answer and this issue to be clear!
zend-ldap doesn't have a src/Module.php file, so you can't add it as a module. Also it doesn't seem to include a standard factory so you need to write one yourself. More info on how to set it up:
https://zendframework.github.io/zend-ldap/intro/
As others have noted, zend-ldap does not provide a Module class; it is simply a component that provides functionality. It has no service definitions, which is why there is no Module class.
Two things to note:
Install zendframework/zend-component-installer in your application: composer require --dev zendframework/zend-component-installer. When you do, any time you add another component to your application that exposes a Module class, it will prompt you, asking if you want to add it to your application configuration. (zend-component-installer is installed by default if you start your project with the zendframework/skeleton-application.)
We have recently opened our Zend Framework forums; consider directing your ZF questions there in the future, to make the answers easily discoverable for ZF users.
Is zend-ldap included in your project? If not Run in your terminal
composer require zendframework/zend-ldap
And you can disable caching in development process by enabling development mode: composer development-enable

Laravel Omnipay with Omnipay/Paypal - Class not found

I'm trying to integrate the Omnipay Paypal package with my Laravel 4.1 application. I've installed the laravel-omnipay package, as suggested by Omnipay, and followed the instructions on how to set it up.
I've added the laravel-omnipay package to both the providers array and the aliases array in the app.php file of Laravel. The config file has also been created.
My composer.json has the following requirements:
"ignited/laravel-omnipay": "1.*",
"omnipay/paypal": "~2.0"
and the config file of ignited/laravel-omnipay looks like this:
<?php
return array(
// The default gateway to use
'default' => 'paypal',
// Add in each gateway here
'gateways' => array(
'paypal' => array(
'driver' => 'Paypal_Express',
'options' => array(
'solutionType' => '',
'landingPage' => '',
'headerImageUrl' => ''
)
)
)
);
But when I call $gateway = Omnipay::gateway('paypal'); I'm getting the error
Class '\Omnipay\Paypal\ExpressGateway' not found"
Is there something I'm forgetting? :I
I'm not familiar with ignited/laravel-omnipay specifically, so this may or may not be the problem, but you might try fixing the capitalisation on this line:
'driver' => 'PayPal_Express',
(note that PayPal has two capital P's).
Generally class names are not case sensitive in PHP, but if you are using a case-sensitive filesystem, then the composer autoloader will not be able to find the right class.
Try composer dumpautoload to load new classes.
UPDATE:
Think in a term of service that is provided to your application by that new package. Find where is that service linked to application. It is usually done through ServiceProviders class. If there is no bug, it should be easy, following simple business rule to see how is provider related to main app.
So, you have one entity (provider) that should communicate with another.
That communication is done through simple rules. This is the best way to learn Laravel. It helps to think in a term of business rules, rather then to stare at code which is often very abstract.

Categories