Change broadcast driver on the fly on laravel - php

I have multiple pusher accounts for my multi tenant laravel app with this configuration:
'pusher_it' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_IT_KEY'),
'secret' => env('PUSHER_APP_IT_SECRET'),
'app_id' => env('PUSHER_APP_IT_ID'),
'options' => [
'cluster' => 'eu',
'useTLS' => true
],
],
'pusher_es' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_ES_KEY'),
'secret' => env('PUSHER_ES_ES_SECRET'),
'app_id' => env('PUSHER_ES_ES_ID'),
'options' => [
'cluster' => 'eu',
'useTLS' => true
],
],
'pusher_pt' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_PT_KEY'),
'secret' => env('PUSHER_APP_PT_SECRET'),
'app_id' => env('PUSHER_APP_PT_ID'),
'options' => [
'cluster' => 'eu',
'useTLS' => true
],
],
When I send a new notification:
Notification::send($usersToNotify, (new VehicleFailureEstimateNotification($vehicleFailureEstimate))->locale(App::getLocale()));
I would set on the fly the pusher configuration:
class VehicleFailureEstimateNotification extends Notification
{
use Queueable;
/**
* #var VehicleFailureEstimate
*/
private $vehicleFailureEstimate;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(VehicleFailureEstimate $vehicleFailureEstimate)
{
Broadcast::setDefaultDriver('pusher_'.$this->locale);
Broadcast::connection('pusher_'.$this->locale);
$this->vehicleFailureEstimate = $vehicleFailureEstimate;
}
But the notification is fired always through .env default BROADCAST_DRIVER=pusher_it
Can you help me? Thank you

It has been a long time question but I hope it will help someone.
It can be set config in your constructor in your case OR in BroadcastServiceProvider.php in boot method
config()->set('broadcasting.default', 'pusher_'.$this->locale);
I tested it and it works for me.

Related

Laravel WebSockets cannot send event

I'm having troubles with dispatching events on my local Laravel configuration.
I'm trying to dispach it directly from the dashboard http://localhost:8000/laravel-websockets, but it always return Error sending event. Even if it is connecting to the dashboard.
My config looks:
.env file:
QUEUE_CONNECTION=database
QUEUE_DRIVER=sync
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=local
PUSHER_APP_KEY=local
PUSHER_APP_SECRET=local
PUSHER_APP_CLUSTER=mt1
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_HOST=127.0.0.1
Configuration in boradcasting.php:
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'host' => env('PUSHER_HOST', 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com',
'port' => env('PUSHER_PORT', 443),
'scheme' => env('PUSHER_SCHEME', 'https'),
'encrypted' => true,
'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
],
Configuration in websockets.php:
'apps' => [ [
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
I did enable all providers, and still not dispatching even from the dashboard.
I tried to create event and dispatch from the controller, but still not working.
Any ideas what could cause it?
Edit: just noticed in dashboard a message like:
Channels current state is connected

http://localhost:8000/broadcasting/auth 403 Forbidden using laravel

I want to do a real time chat, with websocket/pusher.
Installed laravel websockets by following the command: composer require beyondcode/laravel-websockets
Publish it by using: php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan migrate
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config" (I configure file config/websocket.php)
Installed laravel pusher: composer require pusher/pusher-php-server "~3.0"
Uncommented App\Providers\BroadcastServiceProvider::class in config/app.php
Created a ChatEvent event
Launched websockets server by: php artisan websockets:serve
Opened link http://localhost/jwtchat/public/laravel-websockets then connect and everything works fine
I run php artisan tinker:
event(new App\Events\ChatEvent('hello'))
It works very well, but when I try http://localhost/jwtchat/public/broadcasting/auth in postman, it gives me 403 Forbidden error.
in payload it return me:
socket_id: 726245173.481815034
channel_name: presence-chat
.env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=XXXXX
PUSHER_APP_KEY=YYYYY
PUSHER_APP_SECRET=ZZZZ
PUSHER_APP_CLUSTER=eu
broadcasting.php
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'http'
],
],
websockets.php
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
ChatEvent.php
class ChatEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $mesage;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('chat');
}

WebSocket connection to 'wss://127.0.0.1/app/anyKey?protocol=7&client=js&version=6.0.3&flash=false' failed. how to fix this laravel websocket error

broadcasting.php my sample. i don't know how to fix it
If you know the answer please help me
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => false,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'http',
],
],
Error Photo click Here

Laravel s3 multiple buckets

My Laravel application needs to manipulate files present in multiple buckets simultaneously into a single session. So, I couldn't find a way to change several times the current bucket, since my .env file is like this:
S3_KEY='MY-KEY'
S3_SECRET='MySeCret'
S3_REGION='us-east-1'
S3_BUCKET='my-first-used-bucket'
I found somewhere that I could do this:
Config::set('filesystems.disks.s3.bucket', 'another-bucket');
but It works only once. What I need is something like:
Storage::disk('s3')->put('/bucket-name/path/filename.jpg', $file, 'public');
Where /bucket-name/ could be any bucket that I already create. What can I do? Thanks a lot!
You are correct in that Config::set(); only works once per request. My estimation is that this is done intentionally to stop the kind of thing you are attempting to do in your code example.
In config/filesystems.php you can list any number of "disks". These are locations of your file repositories. It looks like so:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'ftp' => [
'driver' => 'ftp',
'host' => 'ftp.example.com',
'username' => 'your-username',
'password' => 'your-password',
// Optional FTP Settings...
// 'port' => 21,
// 'root' => '',
// 'passive' => true,
// 'ssl' => true,
// 'timeout' => 30,
],
's3' => [
'driver' => 's3',
'key' => env('S3_KEY',''),
'secret' => env('S3_SECRET',''),
'region' => env('S3_REGION',''),
'bucket' => env('S3_BUCKET',''),
],
]
The Solution
The solution is to create a new disk of the extra buckets you want to use. Treat your buckets like different disks.
Note: The user that the S3_Key belongs to needs to have permissions to perform your required actions on the S3 buckets you are setting up as additional 'disks'.
'disks' => [
//All your other 'disks'
...
//My default bucket details.
's3' => [
'driver' => 's3',
'key' => env('S3_KEY',''),
'secret' => env('S3_SECRET',''),
'region' => env('S3_REGION',''),
'bucket' => env('S3_BUCKET',''),
],
's3MyOtherBucketName' => [
'driver' => 's3',
'key' => env('S3_KEY',''),
'secret' => env('S3_SECRET',''),
'region' => env('S3_REGION',''),
'bucket' => 'myOtherBucketName',
],
's3YetAnotherBucketName' => [
'driver' => 's3',
'key' => env('S3_KEY',''),
'secret' => env('S3_SECRET',''),
'region' => env('S3_REGION',''),
'bucket' => 'yetAnotherBucketName',
],
]
Then whenever you want to access the bucket of your choice call it like so:
Storage::disk('s3')->put($fileName, $data);
Storage::disk('s3MyOtherBucketName')->put($anotherFileName, $moreData);
Storage::disk('s3YetAnotherBucketName')->put($yetAnotherFileName, $evenMoreData);
If you have dynamic buckets you also can create a new instance like this:
$storage = Storage::createS3Driver([
'driver' => 's3',
'key' => 'your-key',
'secret' => 'your-secret',
'region' => 'us-east-1',
'bucket' => $bucketName,
]);
$storage->put('path/to/file.png', $content);
You can add the buckets to the filesystems config like so:
'disks' => [
's3' => [
'bucket1' => [
'driver' => 's3',
'key' => env('AWS_BUCKET1_ACCESS_KEY_ID'),
'secret' => env('AWS_BUCKET1_SECRET_ACCESS_KEY'),
'region' => env('AWS_BUCKET1_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET1_BUCKET'),
'url' => env('AWS_BUCKET1_URL'),
],
'bucket2' => [
'driver' => 's3',
'key' => env('AWS_BUCKET2_ACCESS_KEY_ID'),
'secret' => env('AWS_BUCKET2_SECRET_ACCESS_KEY'),
'region' => env('AWS_BUCKET2_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET2_BUCKET'),
'url' => env('AWS_BUCKET2_URL'),
],
],
],
Then you can access the server using the following:
\Storage::disk('s3.bucket1')->put('path/to/file.png', $content);
I have created a class for myself and named it StorageProxy. You can find it here.
Let's say you want to work with multiple drivers, one of which is an S3-Compatible Object Storage but you may need to change the storage driver on-the-fly, local for example. No problem, the StorageProxy deals with it! (similar to mc - MinIO Client)
Usage:
StorageProxy::touch(?string $disk, ?string $bucket)->{everyStorageMethod}();
If no disk is specified, it uses the default disk (it's defined in filesystem.php).
Example:
For the local driver our file exists in images/sample.jpg
For s3 driver our file exists in images bucket with the name of sample.jpg
Our filesystem.php file should look like this:
'localhost' => [
'driver' => 'local',
'root' => storage_path('/'),
],
'DO' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
// No need to specify the `bucket` property here
],
Since it's a proxy class, all Storage methods are available in StorageProxy too. Also, you don't need to remove the bucket name from the file path for s3 disks.
// For local disk
$disk = 'localhost';
StorageProxy::touch($disk)->exists("images/sample.jpg"); // true
// For S3 disk
$disk = 'DO';
StorageProxy::touch($disk)->exists("images/sample.jpg"); // true
StorageProxy::touch($disk, "images")->exists("images/sample.jpg"); // true
StorageProxy::touch($disk, "images")->bucketDetection(false)->exists("images/sample.jpg"); // false - the file path is considered as images/images/sample.jpg
StorageProxy::touch($disk, "images")->exists("sample.jpg"); // true

Use different key and secret in Laravel Amazon SDK

I'm using aws-php-sdk with laravel.
But, i have a problem.
I want to use different key and secret for different amazon sevices.
For example:
Amazon S3:
Key: AAAAAA
Secret: BBBBB
Amazon EC2:
Key: DDDDD
Secret: EEEEE
is it possible? if this is possible, how can i do this?
Yes, you can do something like this.
<?php
return [
'default' => 'local',
'cloud' => 's3',
'disks' => [
's3_1' => [
'driver' => 's3',
'key' => 'AAAAAA',
'secret' => 'BBBBB',
'region' => 'us-east-1',
'bucket' => 'bucket1',
],
's3_2' => [
'driver' => 's3',
'key' => 'DDDDD',
'secret' => 'EEEEE',
'region' => 'us-east-1',
'bucket' => 'bucket2',
],
];
Then refer to them
$s3_1 = Storage::disk('s3_1');
$s3_2 = Storage::disk('s3_2');
I would extract them to a .env file.
.env
S3_KEY1=AAAAAA
S3_SECRET1=BBBBB
S3_REGION1=us-east-1
S3_BUCKET1=bucket1
S3_KEY2=DDDDD
S3_SECRET2=EEEEE
S3_REGION2=us-east-1
S3_BUCKET2=bucket1
config/filesystem.php
<?php
return [
'default' => 'local',
'cloud' => 's3',
'disks' => [
's3_1' => [
'driver' => 's3',
'key' => env('S3_KEY1'),
'secret' => env('S3_SECRET1'),
'region' => env('S3_REGION1'),
'bucket' => env('S3_BUCKET1'),
],
's3_2' => [
'driver' => 's3',
'key' => env('S3_KEY2'),
'secret' => env('S3_SECRET2'),
'region' => env('S3_REGION2'),
'bucket' => env('S3_BUCKET_MUSES2'),
],
];

Categories