Laravel broadcast doesnt get triggered - laravel-5

Trying to send user list to specific users after a friend requests been made.using pusher,vuejs 2.6,laravel 5.7 but in my function the broadcast its not getting triggered
when i do dd in channel it works! also in the construct function. so im kind of confused whether the broadcast itself gets called but I dont see a second XHR request for the list or some other situation !!?
//Boostrap.js
import Echo from 'laravel-echo'
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
app_id: '7xxxx4',
key: 'xxxxxxxxxxxxxxxxxxx',
secret: 'xxxxxxxxxxxxxxxxxxx',
encrypted: false
});
//Vuejs component
mounted(){ window.Echo.channel("newReq").listen(".newreq-list", e => {
this.getrequestedList();
});
.env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=7xxxxx4
PUSHER_APP_KEY=xxxxxxxxxxxxxxxxxxx
PUSHER_APP_SECRET=xxxxxxxxxxxxxxxxxxx
PUSHER_APP_CLUSTER=ap2
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' => false,
],
],
channels.php
Broadcast::channel('newReq', function(){
return true;
});
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class Friendreq implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public $req;
public function __construct($req)
{
$this->req = $req;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('newReq');
}
public function broadcastAs()
{
return 'newreq-list';
}
}
//in friendscontroller.php
broadcast(new \App\Events\Friendreq($requestToadd));
I have also uncommented App\Providers\BroadcastServiceProvider
for the result it should call the function this.getrequestedList(); which is a working function cause its also called in created()
Thanks for any help

2 days of debugging,searching was very simple :
PUSHER_APP_CLUSTER=ap2
the above line has to be CHANGED to this
PUSHER_APP_CLUSTER=eu
and now it gets triggered and working the way i want

Related

Understand a concept, is Service Provider the correct use case?

I have created a service provider that takes data from GITHUB API and stores it in a table in a database. Quite a simple thing but I'm wondering if is this how I'm should be using Service Providers?
The second question is about extending this, in reality I want to add more platforms and API's that do this (I currently have one other platform working) but I currently have it set up as a separate service provider. There's a lot of similarities, only some differences in what the API data returns - I feel like I should be abiding by DRY but think this could get complicated when more and more API's get added (def not KISS).
I really want to confirm this before I spend more time extending this platform so appreciate any advice!
<?php
namespace App\Providers;
use GuzzleHttp\Client;
use App\Projects;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Auth;
class GithubServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
//
$this->app->singleton('github_client', function ($app) {
try {
$client = new Client();
$code = $_GET['code'] ?? false;
$res = $client->post('https://github.com/login/oauth/access_token', [
'headers' => [
'Accept' => 'application/json',
],
'query' => [
'client_id' => env('GITHUB_ID'),
'client_secret' => env('GITHUB_SECRET'),
'code'=>$code
]
]
);
} catch(\GuzzleHttp\Exception\RequestException $e) {
$response = $e->getResponse();
throw new \App\Exceptions\CustomException($response->getStatusCode());
}
$username = Auth::user()->username;
$user_id = Auth::user()->id;
if($res->getBody() && !isset(json_decode($res->getBody())->error)):
$access_token = json_decode($res->getBody())->access_token;
$projects = json_decode($client->get('https://api.github.com/user/repos', [
'headers' => [
'Authorization'=> 'token ' . $access_token
]
])->getBody());
$i = 0;
foreach($projects as $project):
$i++;
// dd($project->images);
Projects::updateOrCreate(
[
'platform' => 'github',
'user_id' => $user_id,
'project_id' => $project->id
],
[
'platform' => 'github',
'sorting' => $i,
'user_id' => $user_id,
'title' => $project->name,
'description' => strip_tags($project->description),
'images' => '',
'url' => $project->html_url,
'project_id' => $project->id
]
);
endforeach;
endif;
});
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
A service provider adds services to the service (IoC) container.
In your case, it seems you want code that gets data from third-party providers in a consistent manner. So you probably want to define an interface for this, and then have individual classes that implement that interface (i.e. GithubProjectRepository, BitbucketProjectRepository, etc).
You’d probably use a service provider to register configured instances of GitHub, Bitbucket’s, etc SDKs. This would be instantiated and configured from your config files. You can then type-hint these SDKs in your class’s constructors and the container will give you configured instances instead of having to new-up all over your application.

Laravel Echo + Laravel Passport auth in private / presence websockets channels

I'm trying to connect to a presence wesocket channel using Laravel Echo. I'm also using Laravel Passport. I followed lots of tutorials, but I'm getting 403 error codes, 302 codes and so on. I'm hosting my websocket server locally, using laravel-websockets library to handle connections. Vue is my front-end library.
This is what I tried:
Edit the BroadcastServiceProvider's boot function.
public function boot() {
Broadcast::routes(["prefix" => "api", "middleware" => "auth:api"]);
require base_path('routes/channels.php');
}
Add the Authorization token to Echo headers and add an authEndpoint property in bootstrap.js
window.Echo = new Echo({
broadcaster: 'pusher',
authEndpoint: '/broadcasting/auth',
key: process.env.MIX_PUSHER_APP_KEY,
auth:{
headers:{
'Authorization': 'Bearer ' + auth_token,
}
},
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
//encrypted: false
wsHost: window.location.hostname,
wsPort: 6001});
Try joining the channel from Vue.
mounted(){
Echo.join(`game.0`)
.here((users) => {
alert("In the channel!");
})
.joining((user) => {
console.log("Someone entered");
})
.leaving((user) => {
console.log(user.name);
})
.listen('GameEvent', (e) => {
console.log("Hey")
});}
routes/channels.php file:
Route::prefix('/user')->group(function(){
Route::post('/login','api\v1\LoginController#Login');
Route::middleware('auth:api')->get('/all','api\v1\user\UserController#index');});
The event file:
class GameEvent implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $gameEvent;
public $gameId;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($gameEvent,$gameId)
{
//
$this->gameEvent = $gameEvent;
$this->gameId = $gameId;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
//return new PrivateChannel('channel-name');
return new PresenceChannel('game.0');
}
public function broadcastWith(){
return $this->gameEvent;
}
}
At this point, if I try to connect to the channel, the broadcasting/auth request gets a 302 code (Found). I found an answer in another post that claimed to solve this by adding this to the routes/web.php file.
Route::post('/broadcasting/auth', function(Request $request){
$pusher = new Pusher\Pusher(
env('PUSHER_APP_KEY'),
env('PUSHER_APP_SECRET'),
env('PUSHER_APP_ID'),
array(
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => false,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'http',
)
);
IT WORKED, the broadcasting/auth request gives a 200 code, and I get this as a response:
{"auth":"ABCFEDG:0bfff7db6506158755b012a47873799849d4e6b331f68da4bedd1caea04ad657"}
but the here, joining, leaving functions are not triggering.
Echo.join('game.0')
.here((users) => {
alert("In the channel!");
})
What should I do to get this to work?
Screenshot of the network inspector:
Did you add auth route in channel.php ?
please check it
You should make it based on channel name
Route::channel('game.'.$id,function($user,$id){
return .....
})
no channels there . Did you miss Broadcast::channel ?
try to change your authEndpoint like this
authEndpoint: window.location.hostname+'/api/broadcasting/auth',
and don't forget to update your BroadcastServiceProvider
Broadcast::routes([
'prefix' => 'api',
'middleware' => 'auth:api'
]);
require base_path('routes/channels.php');

Pusher Eloquent Event trigger returns false HTTP API Req Laravel 5.7

I have two eloquent model events performed by an API (insert and update). I have tested these with Postman and they're working I am getting logs of the operations performed. I have removed the logs, since my goal is to trigger pusher events when one of these events are triggered. I have set up pusher installing it from the composer. I have updated the config files and env ,which I will show below, and I have made some triggers to the channel from the pusher dashboard.
I am using Ubuntu 18.04 with apache, laravel 5.7 and when attempting an HTTP request I noticed that $re = $pusher->trigger('api-channel', 'model.insert', array('message' => 'hello')); returns false. I have tried both commenting the encrypt line in the config and setting it to the false, updating the time via ntp as suggested on other posts but these don't resolve my issue. I have tried triggering the event both from the controller and from the eventserviceprovider boot function but the result is always the same.
This is my js
//event listener for document repo api
// Enable pusher logging - don't include this in production
Pusher.logToConsole = true;
var pusher = new Pusher('*****', {
cluster: 'eu',
forceTLS: true
});
var channel = pusher.subscribe('api-channel');
channel.bind('model.insert', function(document) {
alert(JSON.stringify(document.message));
console.log(document);
});
I have tested if the config are setup correctly by adding these lines of code in the BroadCastManager.php
var_dump($config['key']);
var_dump($config['secret']);
var_dump( $config['app_id']);
var_dump($config['options']);
exit;
And from the output I can tell that they are correct.
This is my code when attempting trigger from the controller
namespace App\Http\Controllers;
.
.
.
use Illuminate\Http\Request;
use Pusher\Pusher as Pusher;
.
.
.
if ($model->save()) {
$options = array(
'cluster' => 'eu',
'encrypted' => false
// 'host' => '127.0.0.1',
// 'port' => 6001,
// 'scheme' => 'http'
);
$pusher = new Pusher(
'key',
'secret',
'app-id',
$options
);
// dd($pusher->get_channels());
$re = $pusher->trigger('api-channel', 'model.insert', array('message' => 'hello'));
dd($re);
return new ModelResource($model);
}
I have also attempted creating a laravel event and listener and triggering that event in the controller after a model change has been performed. In that case I get this error:
"message": "",
"exception": "Illuminate\\Broadcasting\\BroadcastException",
"file": "/home/usr/projects/tdv/vendor/laravel/framework/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php",
"line": 117,
"trace": [
{
"file": "/home/usr/projects/tdv/vendor/laravel/framework/src/Illuminate/Broadcasting/BroadcastEvent.php",
"line": 48,
"function": "broadcast",
"class": "Illuminate\\Broadcasting\\Broadcasters\\PusherBroadcaster",
"type": "->"
This is my event class. It is registered in the event service provider.
namespace App\Events;
use App\ModelRepository;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Log;
class ModelEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $modelRepository;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(ModelRepository $modelRepository)
{
//
$this->$modelRepository = $modelRepository;
$this->broadcast();
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('api-channel');
}
public function broadcast()
{
$options = array(
'cluster' => 'eu',
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'http',
'useTLS' => true
);
$pusher = new Pusher(
'***',
'***',
'***',
$options
);
return $pusher->trigger('api-channel', 'model.insert', array('data' => $this->modelRepository));
}
}
and in this case this is how I trigger the event in the controller
event(new ModelEvent(new ModelRepository()));
Thanks in advance! :)

Pusher and Laravel 5.3 Event Broadcasting

Trying to use Laravel 5.3 with pusher, but it seems its not working correct in my code.
My .env is correct
PUSHER_APP_ID= myappid
PUSHER_KEY= mykey
PUSHER_SECRET= mysecret
This is my 'pusher' configurations in broadcasting.php
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_KEY'),
'secret' => env('PUSHER_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => 'eu',
'encrypted' => true,
],
],
I created an event, here it is
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class ProposalEvent implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;
public $data;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return ['test-channel'];
// return new PrivateChannel('test-channel');
// return new PresenceChannel('test-channel');
}
}
my javascript
Pusher.logToConsole = true;
var pusher = new Pusher("mykey", {
cluster: 'eu',
encrypted: true
});
var channel = pusher.subscribe('test-channel');
channel.bind('App\\Events\\ProposalEvent', function(data) {
alert(data);
});
and finally in my view
event(new App\Events\ProposalEvent('some data'));
unfortunately this is not working for me, but when i use pusher->trigger like this, without event, it working fine, and i see message in pusher debug console
$options = array(
'cluster' => 'eu',
'encrypted' => true
);
$pusher = new Pusher(
'mykey',
'mysecret',
'myid',
$options
);
$data['message'] = 'some data';
$pusher->trigger('test-channel', 'my-event', $data);
I have searched for solution in Laravel documentation and other resources. There are questions with same problem in stackoverflow, but there are no response.I will be grateful if somebody can help me, because i can't find solution for several days
I was stuck in the same situation and found out that I wasn't using the queue!
In the documentation it says
Before broadcasting events, you will also need to configure and run a queue listener. All event broadcasting is done via queued jobs so that the response time of your application is not seriously affected.
I deleted the config/queue.php file before since I thought I wasn't using it. Maybe you're doing the same thing as me or having some problem with the queue.
Try to pass pusher credentials directly through config/broadcasting.php
It worked for me.
'default' => 'pusher',
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => '***',
'secret' => '**',
'app_id' => '**',
'options' => [
],
],
],
enter code here
triggering event in the views is a mistake when a page is loaded the php is execute first then js is loaded wich mean that you fired event with php before js listner wich will displaye an error this can the first case
the second case is that you didn't downloaded https://curl.haxx.se/docs/caextract.html
if you did go to php.ini and in [curl]you will find somthing like curl-info unecomment it
and right the path to culr file

Yii2: call custom method in class User from view

I would like to extend my own user model, with a function called getFirstname.
The function should return a custom field in the database.
But when I extend the user model. It says "Calling unknown method: yii\web\User::getFirstname()"
My user model in app\models\user.
I have removed methods in the file, that are not relevant for this problem.
<?php
namespace app\models;
use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
/**
* User model
*
*/
class User extends ActiveRecord implements IdentityInterface
{
/**
* #inheritdoc
*/
public static function tableName()
{
return '{{%user}}';
}
/**
* #inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [];
}
/**
* Finds user by email
*
* #param string $email
* #return static|null
*/
public static function findByEmail($username)
{
return static::findOne(['user_email' => $username]);
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->getPrimaryKey();
}
public function getFirstname()
{
return $this->user_firstname;
}
}
My config file:
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'components' => [
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'thepaXucufrE2pefRethaxetrusacRu3',
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
'user' => [
'identityClass' => 'app\models\User',
'loginUrl' => ['login/sign-in'],
'enableAutoLogin' => true,
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => require(__DIR__ . '/db.php'),
],
];
And in my view file:
<?= Yii::$app->user->getFirstname() ?>
What am I doing wrong here?
Try this:
<?= Yii::$app->user->identity->getFirstname() ?>
<!-- or -->
<?= Yii::$app->user->identity->firstname ?>
With Yii::$app->user you just get the user component. The User component class comment tells you:
User is the class for the "user" application component that manages
the user authentication status.
So it is not the actual user that you get with Yii::$app->user, it is the managing component. With identity or getIdentity() of this class you get the user object that is implementing the IdentityInterface. And when you have a look: your User class implements this interface. And in your configuration you tell the user component that it should use exactly your User class.
The User class with the getFirstname method is in the \app\models namespace, but the one being called in your view is in the yii\web namespace. You should change the code to use \app\models\User.

Resources