The problem that I can't use two SocialiteProviders at the same time
in file EventServiceProvider I have the following
protected $listen = [
'App\Events\SomeEvent' => [
'App\Listeners\EventListener',
],
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
// add your listeners (aka providers) here
'SocialiteProviders\VKontakte\VKontakteExtendSocialite#handle',
],
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
\JhaoDa\SocialiteProviders\Odnoklassniki\OdnoklassnikiExtendSocialite::class
],
];
So If the Odnoklassniki provider works, there is no possibility to use Vkontakte provider. It gives the following:
InvalidArgumentException in Manager.php line 90:
Driver [vkontakte] not supported.
And if I comment Odnoklassniki, Ir will not work also.
How to make it both work.
When you place another item with the same key of an array, it overwrites previous value. Just add them to one key:
protected $listen = [
'App\Events\SomeEvent' => [
'App\Listeners\EventListener',
],
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
// add your listeners (aka providers) here
'SocialiteProviders\VKontakte\VKontakteExtendSocialite#handle',
\JhaoDa\SocialiteProviders\Odnoklassniki\OdnoklassnikiExtendSocialite::class
],
];
Related
I'm writing a couple of laravel packages and I'm wondering if it is possible to have the package write to a specific log file but only for messages related to the package?
I tried making a logging.php file in the packages/myorg/mypackage/config (below) but it doesn't seem to do anything.
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
return [
'default' => env('LOG_CHANNEL', 'stack'),
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single'],
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/mypackage.log'),
'level' => env('LOG_LEVEL', 'debug'),
]
]
];
I am using "jeroen-g/laravel-packager" to set up the packages. It appears to manually load the mypackage.config in the ServiceProvider bootForConsole
protected function bootForConsole(): void
{
// Publishing the configuration file.
$this->publishes([
mypackage.'/../config/mypackage.php' => config_path('mypackage.php'),
], 'mypackage.config');
}
I'm not sure how to add custom logging to that though. I'm still learning Laravel and I'm not quite sure what or how the main applications config/logging.php is read so I'm not quite sure how to inject a custom version for an add-on package.
EDIT:
I found a post that suggested using the following in the ServiceManager boot() method:
$this->app->make('config')->set('logging.channels.mychannel', [
/* settings */
]);
I used the package config to set a 'logging' => [ 'channels' => [ 'mychannel' => [ /* settings */ ] ] ] and could then do the same thing as above with:
$this->app->make('config')->set('logging.channels.mychannel', config('mypackage.logging.channels.mychannel');
But that still required something in the code. The next best thing I have found thus far is to change my config/logging.php to config/logging.channels.php and include something like:
return [
'mychannel' => [
'driver' => 'single',
'path' => storage_path('logs/mypackage.log'),
'level' => env('LOG_LEVEL', 'debug'),
]
];
Then in the service provider register() method add:
$this->mergeConfigFrom(__DIR__ . '/../config/logging.channels.php', 'logging.channels');
I tried doing it from the original 'logging.php' with channels array nested in a 'logging' key, but array_merge doesn't appear to merge the nested elements so my channel never showed up in logging.channels.
I'm not sure if this is ideal, however. I'd still like to know if there is a 'better' or best practices way of adding custom package logging parameters and whether there is a need to publish it in any way (and how).
I tried to create a mongodb logging channel
'mongo' => [
'driver' => 'monolog',
'handler' => \Monolog\Handler\MongoDBHandler::class,
'formatter' => \Monolog\Formatter\MongoDBFormatter::class,
'handler_with' => [
'mongo' => new \MongoDB\Client("mongodb://localhost:27017"),
'database' => 'testdb',
'collection' => 'testcoll'
]
],
However, im getting error:
Illuminate\Contracts\Container\BindingResolutionException(code: 0): Unresolvable dependency resolving [Parameter #0 [ <required> $mongodb ]] in class Monolog\Handler\MongoDBHandler
The error is only resolved when I tried to add type hint to the class constructor but obviously I can't do that since it's a package:
public function __construct(Client<<if I add this it works>> $mongodb, string $database, string $collection, $level = Logger::DEBUG, bool $bubble = true)
Any solution for this?
So, I wanted to add here a complete answer because this post is the first one that shows up when looking for adding a mongo logger, and since the answer is buried in the comments, I wanted to add a proper answer.
The solution was to change the key mongo to mongodb in the handler_with array.
Leaving the working code like this:
'mongo' => [
'driver' => 'monolog',
'handler' => \Monolog\Handler\MongoDBHandler::class,
'formatter' => \Monolog\Formatter\MongoDBFormatter::class,
'handler_with' => [
'mongodb' => new \MongoDB\Client("mongodb://localhost:27017"),
'database' => 'testdb',
'collection' => 'testcoll'
]
],
Also, you could add the following element at the same level as formatter to set a custom max level of nesting. This is because, by default, the document stored cannot have a depth greater than 3, and it's automatically converted to "[...]" in the log.
'formatter_with' => [
'maxNestingLevel' => 10
],
Warning, in the probable event of a recursion, or an incredibly deep array, it can cause problems in mongo, because it doesn't support more than 100 levels of nesting, source.
According to the Laravel 8.x doc:
'mongo' => [
'driver' => 'monolog',
'handler' => \Monolog\Handler\MongoDBHandler::class,
'formatter' => \Monolog\Formatter\MongoDBFormatter::class,
'with' => [ // <-- This is `with` instead of `handler_with`
// 'mongodb' => new \MongoDB\Client("mongodb://localhost:27017"), <-- This line will cause an error in `php artisan config:cache`
'database' => 'testdb',
'collection' => 'testcoll'
],
],
So you need to configure the service for MongoDBHandler. as you mentioned with a look at the handler source code the first argument is $mongodb.
public function __construct($mongodb, string $database, string $collection, $level = Logger::DEBUG, bool $bubble = true)
and to be able to resolve this dependency we can configure service container:
// AppServiceProvider.php
// ...
public function register() {
$this->app->when(\Monolog\Handler\MongoDBHandler::class)
->needs('$mongodb')
->give(app(
\MongoDB\Client::class,
[
'uri' => 'mongodb://localhost:27017'
]
));
}
// ...
For instance let's say the
'''
$model_name = 'student_table';
'''
'providers' => [
'users' => [
'$model_name' => [
'driver' => 'eloquent',
'model' => App\Models\.$model_name.::class
]
]
]
The problem is that laravel fires an unexpected '.' expecting identified (T_STRING)
And I need to insert the model name dynamically because there lot of database tables to connect with. Any other solution pls
that's not going to work, providers are loaded way before the controller is.
maybe if you use a config table in database that orient users to own specific auth table.
https://laravel.com/docs/5.7/lifecycle
That is a syntax error.
After App\Models\ you can't have ., It expects you to write the class name next.
Try this:
'providers' => [
'users' => [
'$model_name => [
'driver'=> 'eloquent',
'model' => "App\Models\\" . $model_name
]
]
]
Notice you don't need ::class anymore as you have the full namespace of the class in string.
I am using the basic login and registration scaffold that comes with Laravel 5.3. I've also created a logging function so that I can log some of the basic user actions for my platform, such as updating or deleting records.
I'd like to add the logging to the user login process so that I can log when they've logged in and a failed attempt. Because I'm using the basic included scaffolding, I'm not sure where to do this?
If you want to hook into login process and just log something. Consider hooking into the authentication events provided by Laravel's Authentication events
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
'Illuminate\Auth\Events\Registered' => [
'App\Listeners\LogRegisteredUser',
],
'Illuminate\Auth\Events\Attempting' => [
'App\Listeners\LogAuthenticationAttempt',
],
'Illuminate\Auth\Events\Authenticated' => [
'App\Listeners\LogAuthenticated',
],
'Illuminate\Auth\Events\Login' => [
'App\Listeners\LogSuccessfulLogin',
],
'Illuminate\Auth\Events\Failed' => [
'App\Listeners\LogFailedLogin',
],
'Illuminate\Auth\Events\Logout' => [
'App\Listeners\LogSuccessfulLogout',
],
'Illuminate\Auth\Events\Lockout' => [
'App\Listeners\LogLockout',
],
];
Sometimes, we'd like to separate users and admins in different 2 tables.
I think it is a good practice.
I am looking if that is possible in Laravel 5.
Before reading the following, you are supposed to have basic knowledge on ServiceProvider, Facade and IoC in Laravel 5. Here we go.
According to the doc of Laravel, you could find the Facade 'Auth' is refering to the Illuminate\Auth\AuthManager, which has a magic __call(). You could see the major function is not in AuthManager, but in Illuminate\Auth\Guard
Guard has a Provider. This provider has a $model property, according to which the EloquentUserProvider would create this model by "new $model". These are all we need to know. Here goes the code.
1.We need to create a AdminAuthServiceProvider.
public function register(){
Auth::extend('adminEloquent', function($app){
// you can use Config::get() to retrieve the model class name from config file
$myProvider = new EloquentUserProvider($app['hash'], '\App\AdminModel')
return new Guard($myProvider, $app['session.store']);
})
$app->singleton('auth.driver_admin', function($app){
return Auth::driver('adminEloquent');
});
}
2.Facade:
class AdminAuth extends Facade {
protected static function getFacadeAccessor() { return 'auth.driver_admin'; }
}
3. add the alias to Kernel:
'aliases' => [
//has to be beneath the 'Auth' alias
'AdminAuth' => '\App\Facades\AdminAuth'
]
Hope this could be helpful.
I have created a laravel package where you can handle multiple authentication.
Step 1 : Composer require
Firstly, composer require the multiauth package
composer require sarav/laravel-multiauth dev-master
Step 2 : Replacing default auth service provider
Replace
Illuminate\Auth\AuthServiceProvider::class
with
Sarav\Multiauth\MultiauthServiceProvider
in your config/app.php file
Step 3 : Modify auth.php
Modify your config/auth.php file to something like this
'multi' => [
'user' => [
'driver' => 'eloquent',
'model' => App\User::class,
'table' => 'users'
],
'admin' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
'table' => 'admins'
]
],
Thats it! Now you can try multiple authentication by passing the user as first parameter. For example
\Auth::loginUsingId("user", 1); // Login user with id 1
\Auth::loginUsingId("admin", 1); // Login admin with id 1
// Attempts to login user with email id johndoe#gmail.com
\Auth::attempt("user", ['email' => 'johndoe#gmail.com', 'password' => 'password']);
// Attempts to login admin with email id johndoe#gmail.com
\Auth::attempt("admin", ['email' => 'johndoe#gmail.com', 'password' => 'password']);
For more detailed documentation
http://sarav.co/blog/multiple-authentication-in-laravel/
http://sarav.co/blog/multiple-authentication-in-laravel-continued/