I am new to laravel and to websockets. I have got my websockets working on the laravel-websockets dashboard, and now am trying to trigger a websocket event with this javascript command:
axios.post('updatequeue', {queue_position: newPos});
newPos is a number.
This is my controller method:
public function updateQueue(Request $request){
$queueposition = $request->input('queue_position');
event(new QueueUpdate($queueposition));
}
This is my Event:
class QueueUpdate implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $queue_position;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($queue_position)
{
$this->queue_position = $queue_position;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('sessionid');
}
}
When I watch for events in the dashboard, nothing shows up. I get a 200 response from the axios request. I have placed logs throughout, and my events __construct method is called, but broadcastOn() is not.
I am really stuck here, if anyone has any ideas, I would be very grateful.
EDIT
here is my broadcasting.php:
<?php
return [
'default' => env('BROADCAST_DRIVER', 'null'),
'connections' => [
'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'),
'host' => env('WEBSOCKET_BROADCAST_HOST'),
'port' => env('WEBSOCKET_BROADCAST_PORT'),
'scheme' => env('WEBSOCKET_SCHEME'),
'encrypted' => env('WEBSOCKET_ENCRYPTED'),
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];
and websockets.php:
<?php
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;
return [
'dashboard' => [
'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
],
'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,
],
],
'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,
'allowed_origins' => [
//
],
'max_request_size_in_kb' => 250,
'path' => 'laravel-websockets',
'middleware' => [
'web',
Authorize::class,
],
'statistics' => [
'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,
'interval_in_seconds' => 60,
'delete_statistics_older_than_days' => 60,
'perform_dns_lookup' => false,
],
'ssl' => [
'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
'verify_peer' => env('LARAVEL_WEBSOCKETS_SSL_VERIFY_PEER', true),
],
'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
];
EDIT
I am local.
Here are the values for broadcasting.php:
'driver' => 'pusher',
'key' => portalkey,
'secret' => secret,
'app_id' => portalID,
'cluster' => portalcluster,
'host' => 127.0.0.1,
'port' => 6001,
'scheme' => http,
'encrypted' => false,
If you can connect to the laravel-websockets dashboard but the events won't show up, chances are your /laravel-websockets/auth request is failing due to csrf token. Try adding laravel-websockets to the $except variable in VerifyCsrfToken middleware.
You should set the QUEUE_CONNECTION=sync in your .env file.
This will make the broadcast work and fix your problem.
Related
This is my auth.php file
return [
'defaults' => [
'guard' => 'salon_emp',
// 'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'salon_emp' => [
'driver' => 'jwt',
'provider' => 'salon_emp'
],
'app' => [
'driver' => 'session',
'provider' => 'client'
]
],
'providers' => [
'salon_emp' => [
'driver' => 'eloquent',
'model' => SalonEmployee::class,
],
'client' => [
'driver' => 'eloquent',
'model' => Client::class
]
],
This is my login function in my LoginController
public function login(LoginRequest $request)
{
if (auth('app')->attempt($request->validated())) {
auth('app')->user()->tokens()->delete();
return apiResponse([
'message' => 'Login successful!',
'token' => auth('app')->user()->createToken(auth('app')->user()->name)->plainTextToken
]);
} else {
return apiResponse([
'message' => 'Login not successful!',
], Response::HTTP_UNAUTHORIZED);
}
}
I am also using sanctum for authentication
in my routes file i am using the auth:sanctum middleware to secure my routs, for example:
Route::get('/test',function ()
{
dd('ss');
})->middleware('auth:sanctum');
how ever i get this error whenever i try to access it
Argument 2 passed to Illuminate\\Auth\\SessionGuard::__construct() must implement interface Illuminate\\Contracts\\Auth\\UserProvider, null given, called in \vendor\\laravel\\framework\\src\\Illuminate\\Auth\\AuthManager.php on line 128",
i have tried changing providers and drivers but no luck
I added this line to sanctum.php
'guard' => 'app'
and it worked fine
To implement chat In Laravel 8/vue 2.6 I added beyondcode/laravel-websockets
and reading some manuals I found that I need to use pusher packages, like
laravel-echo and pusher-js not not pusher App API. So I tried to make as in .env :
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=myId
PUSHER_APP_KEY=myKey
PUSHER_APP_SECRET=mySecret
PUSHER_APP_CLUSTER=eu
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
and in resources/js/bootstrap.js :
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'myKey',
wsHost: 601,
disableStats: true,
forceTLS: false
});
In config/app.php I uncommented line :
App\Providers\BroadcastServiceProvider::class,
In config/broadcasting.php :
<?php
return [
'default' => env('BROADCAST_DRIVER', 'null'),
'connections' => [
'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',
'useTLS' => false,
],
],
'ably' => [
'driver' => 'ably',
'key' => env('ABLY_KEY'),
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];
and in routes/channels.php :
Broadcast::channel('chat', function ($user, $id) {
\Log::info( varDump($user, ' routes/channels.php -1 $user::') ); // I DO NOT SEE THESE log lines
// return (int) $user->id === (int) $id;
return $user;
});
and in config/websockets.php :
<?php
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;
return [
'dashboard' => [
'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
],
'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,
],
],
'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,
'allowed_origins' => [
//
],
'max_request_size_in_kb' => 250,
'path' => 'laravel-websockets',
'middleware' => [
'web',
Authorize::class,
],
'statistics' => [
'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,
'logger' => BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class,
'interval_in_seconds' => 60,
'delete_statistics_older_than_days' => 60,
'perform_dns_lookup' => false,
],
'ssl' => [
'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
],
'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
];
Running server I see :
user#os:app_path$ php artisan websockets:serve
Starting the WebSocket server on port 6001...
New connection opened for app key myKey.
Connection id 447562709.864005085 sending message {"event":"pusher:connection_established","data":"{\"socket_id\":\"447562709.864005085\",\"activity_timeout\":30}"}
...
RunningWebSockets Dashboard at
http://127.0.0.1:8000/laravel-websockets
is connected with success with many messages,
But trying to post new event I see error : https://imgur.com/a/7zJZPyu
{"message":"The given data was invalid.","errors":{"data":["The data must be a valid JSON string."]}}
But in the brwosers console I see error :
app.js:119179 WebSocket connection to 'ws://0.0.2.89/app/myKey?protocol=7&client=js&version=7.0.3&flash=false' failed:
It fails with "myKey". Maybe it some options not to use pusher server key?
Thanks!
You need to ensure the credentials are the same on both the server and the client. You are setting the key value as PUSHER_APP_KEY=myKey in the client. What is the value of the variable used in the config/broadcasting.php file
and config/websockets.php : key' => env('PUSHER_APP_KEY'),.
Source: Make sure to use the same app id, key and secret as in your broadcasting configuration section. Otherwise broadcasting events from Laravel will not work.
You will also need to ensure you use a valid JSON payload from the debug console.
Source: Simply enter the channel, the event name and provide a valid JSON payload to send it to all connected clients in the given channel.
I tried to integration error log laravel to slack notification. But when i tested to send log it can't send massage to slack. I followed this tutorial https://panjeh.medium.com/send-laravel-6-log-to-slack-notification-573a6d95a14e. And I've tested on route too
Here is it the config.php
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single','slack'],
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 14,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => 'warning',
],
Here is it the route to test
Route::get('slack', function() {
Log::error('Test');
return 'Slack notif';
});
I've got the url too and have it put in .env LOG_SLACK_WEBHOOK_URL=
You can change default log channels to slack.So you have to set
LOG_CHANNEL=stack
Also you can specify channels. Instead of changing channels
Log::channel('slack')->inf("test");
or you can do
Log::stack(['daily', 'slack'])->info("test");
or you can specify channels inside daily array.So that no need to change anythink
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'slack'],
'ignore_exceptions' => false,
],
I have a application where I have created a new guard called residents which is the exact copy of the default User class that comes with the laravel. But when i change the guard it start showing this error:
Argument 2 passed to Illuminate\Auth\SessionGuard::__construct() must be an instance of Illuminate\Contracts\Auth\UserProvider, null given, called in ...\vendor\laravel\framework\src\Illuminate\Auth\AuthManager.php on line 125
I tried googling for the solution and read many but nothing worked.
Laravel version is 5.8
auth.php
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'residents',
'hash' => false,
],
],
'providers' => [
'residents' => [
'driver' => 'eloquent',
'model' => App\ApiModels\Resident::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
],
App\ApiModels\Resident.php
namespace App\ApiModels;
use \Illuminate\Notifications\Notifiable;
use \Illuminate\Contracts\Auth\MustVerifyEmail;
use \Illuminate\Foundation\Auth\User as Authenticatable;
class Resident extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* Authenticate the user
*
* #param object $request
* #return array
*/
public function _login($request)
{
if(\Auth::attempt([
'email' => $request->email,
'password' => $request->password
]))
{
return [
'success' => true
];
}
else
{
return [
'success' => false
];
}
}
}
route\api.php
Route::get('/login', 'Api\ResidentsController#login');
Api\ResidentsController.php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
/**
* Models
*/
use App\ApiModels\Resident;
class ResidentsController extends Controller
{
public function __construct()
{
/**
* Middleware(s)
*/
$this->middleware('auth:api', [
'except' => [
'login',
'logout'
]
]);
}
public function login(Request $request)
{
...
return response()->json([
'login_id' => $request->login_id,
'password' => $request->password
]);
}
}
The problem occurs in your config/auth.php. Your web guard is using the users provider which is not declared in your providers array. You have 2 options to fix this (choose one):
Add a users provider
If you're planning NOT to use the web guard, remove it instead then make your default guard to api:
'defaults' => [
'guard' => 'api',
'passwords' => 'residents',
],
'guards' => [
'api' => [
'driver' => 'token',
'provider' => 'residents',
'hash' => false,
],
],
'providers' => [
'residents' => [
'driver' => 'eloquent',
'model' => App\ApiModels\Resident::class,
],
],
'passwords' => [
'residents' => [
'provider' => 'residents',
'table' => 'password_resets',
'expire' => 60,
],
],
You Must use this for web guard:
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
Or
you can remove web guard:
I have found famous library for using RabbitMQ in Laravel.
In configuration config/queue.php
I can specify only one exchange and queue name.
Does it
support multiple exchanges?
For future people who will search the answer for this question.
There is one(bad) way to add multiple exchanges. You have to duplicate rabbitmq connection with new exchange and when you will want to publish the message to new exchange, you will just change connection.
This is a very ugly way, but i didn't another one. Laravel queue doesn't provide a method to change the exchange, but there is the method onConnection what you help you.
Here is a simple example
'conn_one' => [
'driver' => 'rabbitmq',
'queue' => env('RABBITMQ_QUEUE', 'default'),
'connection' => PhpAmqpLib\Connection\AMQPLazyConnection::class,
'hosts' => [
[
'host' => env('RABBITMQ_HOST', '127.0.0.1'),
'port' => env('RABBITMQ_PORT', 5672),
'user' => env('RABBITMQ_USER', 'guest'),
'password' => env('RABBITMQ_PASSWORD', 'guest'),
'vhost' => env('RABBITMQ_VHOST', '/'),
],
],
'options' => [
'ssl_options' => [
'cafile' => env('RABBITMQ_SSL_CAFILE', null),
'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null),
'local_key' => env('RABBITMQ_SSL_LOCALKEY', null),
'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
],
'queue' => [
'job' => VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob::class,
'exchange' => 'exchange_two',
'exchange_type' => 'fanout',
],
],
],
'conn_two' => [
'driver' => 'rabbitmq',
'queue' => env('RABBITMQ_QUEUE', 'default'),
'connection' => PhpAmqpLib\Connection\AMQPLazyConnection::class,
'hosts' => [
[
'host' => env('RABBITMQ_HOST', '127.0.0.1'),
'port' => env('RABBITMQ_PORT', 5672),
'user' => env('RABBITMQ_USER', 'guest'),
'password' => env('RABBITMQ_PASSWORD', 'guest'),
'vhost' => env('RABBITMQ_VHOST', '/'),
],
],
'options' => [
'ssl_options' => [
'cafile' => env('RABBITMQ_SSL_CAFILE', null),
'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null),
'local_key' => env('RABBITMQ_SSL_LOCALKEY', null),
'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
],
'queue' => [
'job' => VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob::class,
'exchange' => 'exchange_two',
'exchange_type' => 'fanout',
],
],
],
Use
ExampleJob::dispach($data)->onConnection('conn_one');
ExampleJob::dispach($data)->onConnection('conn_two');
Or another ugly way could be to set config like this
Config::set('queue.connections.rabbitmq.options.queue.exchange', 'exchange_two');
before dispatching the job to the new exchange. In this way you dont have to create a duplicate connection just setting new exchange name before dispatching the job to the new exchange.