Laravel broadcasting a Presence Channel using pusher unable to pass parameters - laravel

I've followed the documentation at https://laravel.com/docs/6.x/broadcasting step by step and make sure I copy and paste to be certain I don't make any mistake. I'm able to broadcast just fine and everything is working just fine. Because I'm unable to pass attributes, people in different roomId are counted as if they are all in the same room.
Here is the live example:
https://prayershub.com/worship/82 - 82 is the worship_id I would like to pass to:
Broadcast::channel('worship_presence_channel.{id}', function ($id) {
if(Auth()->check())
{
$profile = Auth()->user()->Profile;
$user = Auth()->user();
$data = [
'id' => $user->id,
'name' => $user->name,
'username' => $user->username,
'avatar' => config('app.storage').$profile->profile_image,
'url' => $profile->profile_url,
'favorite_bible_verse' => $profile->favorite_bible_verse
];
return $id;
}
});
From:
Echo.join(`worship_presence_channel.${id}`)
.here((users) => {
worshipers=users;
joinUser(worshipers);
$('.group-count').html(worshipers.length);
console.log(users);
})
.joining((user) => {
worshipers.push(user);
popupNewUser(user);
joinUser(worshipers);
$('.group-count').html(worshipers.length);
})
.leaving((user) => {
worshipers = worshipers.filter(function(obj) {
return (obj.id !== user.id);
});
popupLeaveUser(user);
joinUser(worshipers);
$('.group-count').html(worshipers.length);
});
I also have an event which seems to be unneccassary but it lools like this:
public function broadcastOn()
{
return new PresenceChannel('worship_presence_channel.58');
}
public function broadcastAs()
{
return 'worship_presence_channel.58';
}
Can anyone please, tell me what i'm doing wrong or if I get the whole thing just wrong. Please help!

I've figured it out, I've change the echo codes above to this:
Broadcast::channel('worship_presence_channel.{id}', function ($user, $id) {
if(Auth()->check())
{
$profile = $user->Profile;
$data = [
'id' => $user->id,
'name' => $user->name,
'username' => $user->username,
'avatar' => config('app.storage').$profile->profile_image,
'url' => $profile->profile_url,
'favorite_bible_verse' => $profile->favorite_bible_verse,
'worships_id' => $id
];
return $data;
}
});
I'm passing 2 parameters $user, $id and it works just as the doc said it would!!!

Related

FatalThrowableError in Call to a member function get_one() on null

i have some laravel code like this
public function update_password(Request $request)
{
$data = array(
'password_current' => $request->input('password_current'),
'password_new' => $request->input('password_new'),
'password_new_confirmation' => $request->input('password_new_confirmation'),
);
$rules = [
'password_current' => 'required',
'password_new' => 'required|confirmed',
'password_new_confirmation' => 'required',
];
$validator = Validator::make($data, $rules);
if ($validator->fails()) {
return redirect()->action('Editor\ProfileController#edit_password')->withInput()->withErrors(['New password confirmation failed!']);
} else {
$user = $this->UserRepository->get_one(Auth::user()->id);
if(Hash::check($request->input('password_current'), $user->password))
{
$this->UserRepository->change_password(Auth::user()->id, $request->input('password_new'));
return redirect()->action('Editor\ProfileController#show');
} else {
return redirect()->action('Editor\ProfileController#edit_password')->withInput()->withErrors(['Current password mismatch!']);
}
}
}
but when i run the program, the program notification is FatalThrowableError, Call to a member function get_one() on null. i change with other script in google but no one is work.
$user = $this->UserRepository->get_one(Auth::user()->id);
anyone ever had this problem?
I try to change script like
use Auth;
$user_id = Auth::user()->id;
and still not work.

Laravel Many to one in Resource

I use laravel 8 & have 3 table:
Products, ProductPrice & ProductsPublisher:
this is my Products model for this relationship:
public function lastPrice(){
return $this->hasMany(ProductPrice::class)->where('status','active')->orderBy('created_at','DESC')->distinct('publisher_id');
}
and this is my productsPrice model for publisher relationship:
public function getPublisher(){
return $this->belongsTo(ProductsPublisher::class,'publisher_id');
}
now, i want to use laravel resource for my api, i wrote products resource:
public function toArray($request)
{
return [
'id' => $this->id,
'price' => lastPrice::make($this->lastPrice),
'status' => $this->status,
'slug' => $this->slug,
'title' => $this->title,
'description' => $this->description,
'txt' => $this->txt,
'lang' => $this->lang,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
but in lastPrice resource, when i wrote like this:
return [
'id' => $this->id,
'main_price' => $this->main_price
];
it give me this error:
Property [id] does not exist on this collection instance.
when i use this code:
return parent::toArray($request);
get response but because i need to use another relationship in my lastPirce for publishers, i cant use that code and should return separately my data.
What i should to do?
thanks
Edit 1:
this is my Controller Code:
$products = Product::where('id',$id)->where('slug',$slug)->where('status','confirm')->first();
if(!$products){
return $this->sendError('Post does not exist.');
}else{
return $this->sendResponse(new \App\Http\Resources\Products\Products($products), 'Posts fetched.');
}
and this is sendResponse & sendError:
public function sendResponse($result, $message)
{
$response = [
'success' => true,
'data' => $result,
'message' => $message,
];
return response()->json($response, 200);
}
public function sendError($error, $errorMessages = [], $code = 404)
{
$response = [
'success' => false,
'message' => $error,
];
if(!empty($errorMessages)){
$response['data'] = $errorMessages;
}
return response()->json($response, $code);
}
thanks.
Edit 2:
i change my lastPrice Resource toArray function to this and my problem solved, but i think this isn't a clean way, any better idea?
$old_data = parent::toArray($request);
$co = 0;
$new_data = [];
foreach ($old_data as $index){
$publisher_data = Cache::remember('publisher'.$index['publisher_id'], env('CACHE_TIME_LONG') , function () use ($index) {
return ProductsPublisher::where('id' , $index['publisher_id'])->first();
});
$new_data[$co]['main_prices'] = $index['main_price'];
$new_data[$co]['off_prices'] = $index['off_price'];
$new_data[$co]['publisher'] = SinglePublisher::make($publisher_data);
$new_data[$co]['created_at'] = $index['created_at'];
$co++;
}
return $new_data;

Error column not found, but I did not declare the column?

I'm inserting a record to a polymorphic imageable table, however it says column thread_id not found. I have not declared this thread_id column and I don't know where it's pulling it from. Here is the code it's trying to run.
protected static function bootRecordImage()
{
if (auth()->guest()) return;
foreach (static::getMethodToRecord() as $event) {
static::$event(function ($model) use ($event) {
$body = request()->body;
preg_match_all('/<img .*?(?=src)src=\"([^\"]+)\"/si', $body, $matches);
$images = $matches[1];
if($event == 'created') {
foreach ($images as $image) {
$model->images()->create([
'user_id' => auth()->id(),
'imageable_id' => $model->id,
'imageable_type' => get_class($model),
'path' => $image
]);
}
}
if($event == 'deleting') {
foreach ($images as $image) {
$model->images()->delete([
'user_id' => auth()->id(),
'imageable_id' => $model->id,
'imageable_type' => get_class($model),
'path' => $image
]);
if (File::exists(public_path($image))) {
File::delete(public_path($image));
}
}
}
});
}
}
My store method:
public function store(Request $request, Channel $channel, Spam $spam)
{
if (!auth()->user()) {
return back()->withInput()->with('flash', 'Sorry! You must be logged in to perform this action.');
}
if (!auth()->user()->confirmed) {
return back()->withInput()->with('flash', 'Sorry! You must first confirm your email address.');
}
$this->validate($request, [
'title' => 'required',
'body' => 'required',
'channel_id' => 'required|exists:channels,id',
'g-recaptcha-response' => 'required'
// yes it's required, but it also needs to exist on the channels model, specifically on the id
]);
$response = Zttp::asFormParams()->post('https://www.google.com/recaptcha/api/siteverify', [
'secret' => config('services.recaptcha.secret'),
'response' => $request->input('g-recaptcha-response'),
'remoteip' => $_SERVER['REMOTE_ADDR']
]);
// dd($response->json());
if (! $response->json()['success']) {
throw new \Exception('Recaptcha failed');
}
$spam->detect(request('title'));
$spam->detect(request('body'));
$thread = Thread::create([
'user_id' => auth()->id(),
'channel_id' => request('channel_id'),
'title' => request('title'),
'body' => request('body'),
//'slug' => str_slug(request('title'))
]);
return redirect('/forums/' . $thread->channel->slug . '/' . $thread->slug);
}
As you can see, no where is a thread_id mentioned, yet in the error it looks like it's trying to insert into a thread_id column that I've never declared.
Thanks for reading.
I put the polymorphic relation in the model and the trait. Remove it from the Model and you're good to go.

Store notifications data with saveMany Contents

So what I am trying to do is store notifications to the database with Notifiable, but I have a saveMany contents and I don't know how to declare the data in the notifications. getting a null from what I've declared like the picture below
this is my saveMany store
$post = new Post;
$post->user_id = Auth::guard('webcontrol')->user()->id;
$post->lob = $request->lob;
$post->type = 'post';
$post->category_id = $request->category_id;
$post->is_published = $request->is_published;
$post->published_at = ($request->published_at) ? $request->published_at : Carbon::now();
$post->metas = '{}';
$post->save();
$post->contents()->saveMany([
new PostContent([
'lang' => 'id',
'slug' => str_slug($request->contents['id']['title'], '-'),
'title' => $request->contents['id']['title'],
'body' => $request->contents['id']['body'],
'image' => $request->contents['id']['image'],
'tag' => $request->contents['id']['tag'],
'metas' => serialize($request->contents['id']['metas']),
]),
new PostContent([
'lang' => 'en',
'slug' => str_slug($request->contents['en']['title'], '-'),
'title' => $request->contents['en']['title'],
'body' => $request->contents['en']['body'],
'image' => $request->contents['en']['image'],
'tag' => $request->contents['en']['tag'],
'metas' => serialize($request->contents['en']['metas']),
])
]);
Notification::send($user, new OneSignalNotification($post));
dd('done');
this is my Notification
class OneSignalNotification extends Notification
{
use Queueable;
public $post;
public function __construct($post)
{
$this->post = $post;
}
public function via($notifiable)
{
return ['database'];
}
public function toDatabase($notifiable)
{
return [
'body' => $this->post['body'], //this is where i confused how to declare the saveMany contents so its not returning null
];
}
}
So I'm not sure what you're trying to achieve but the issue is with the fact that you want to retrieve the body from the post, but the way I see it, the $post doesn't have a body property. The PostContent seems to have the body property, but the problem is that you saved many PostContent to the same $post, so therefore there are multiple body properties, one for each PostContent. So that's why I would recommend use the first() method to get the first PostContent from $post and then return it. If you want to return all the body property, you would have to get all of them and add them into an array or a string, or whatever you want. I hope this makes sense.
You should try using this:
$post = new Post;
$post->user_id = Auth::guard('webcontrol')->user()->id;
$post->lob = $request->lob;
$post->type = 'post';
$post->category_id = $request->category_id;
$post->is_published = $request->is_published;
$post->published_at = ($request->published_at) ? $request->published_at : Carbon::now();
$post->metas = '{}';
$post->save();
$post->contents()->saveMany([
new PostContent([
'lang' => 'id',
'slug' => str_slug($request->contents['id']['title'], '-'),
'title' => $request->contents['id']['title'],
'body' => $request->contents['id']['body'],
'image' => $request->contents['id']['image'],
'tag' => $request->contents['id']['tag'],
'metas' => serialize($request->contents['id']['metas']),
]),
new PostContent([
'lang' => 'en',
'slug' => str_slug($request->contents['en']['title'], '-'),
'title' => $request->contents['en']['title'],
'body' => $request->contents['en']['body'],
'image' => $request->contents['en']['image'],
'tag' => $request->contents['en']['tag'],
'metas' => serialize($request->contents['en']['metas']),
])
]);
Notification::send($user, new OneSignalNotification($post->fresh()));
dd('done');
And then inside the Notification, like I said, we take the first PostContent from the $post and get it's body property:
class OneSignalNotification extends Notification
{
use Queueable;
public $post;
public function __construct($post)
{
$this->post = $post;
}
public function via($notifiable)
{
return ['database'];
}
public function toDatabase($notifiable)
{
return [
'body' => $this->contents()->first()->body,
];
}
}

Manually Passing a Foreign key Value

I can not pass a foreign key value (which is user_id) to my newly created article.
Here is my code...
<?php
if (is_null($request->user_id)) {
$request->user_id = $user->user_id;
}
$request->validate(['title' => 'Required|string|min:3', 'body' => 'Required|string|min:5', 'user_id' => 'Required|exists:users,user_id']);
if ($article = Article::create($request->all())) {
event(new ArticleCreated($user));
return response()->json(['success' => true, 'reason' => 'Article Created successfully', $article]);
} else {
return 'Article could not be created';
}
Change this:
if($article = Article::create($request->all())) {
$article->user_id = $request->user_id;
$article->save();
event(new ArticleCreated($user));
return response()->json(['success' => true, 'reason' => 'Article Created successfully', $article]);
}
Try this,
public function store(Request $request)
{
$request->validate([
'title' => 'Required|string|min:3',
'body' => 'Required|string|min:5',
]);
$data = $request->all();
//you don't need to validate user_id is correct
//if you are using auth middleware in the route
$user = auth()->user()
$data['user_id] = $user->id
if ($article = Article::create($data)) {
event(new ArticleCreated($user));
return response()->json([
'success' => true,
'reason' => 'Article Created successfully',
$article
]);
} else {
return 'Article could not be created';
}
}
Hope this helps
Check your fillable array in Article model, there must be user_id, and check if the user id is passed in the $request->all().

Resources