Problem with broadcasting and websocket in Laravel - laravel

I don't understand where it is blocking. If I replace the update() with a create() method, it works, or if I remove the broadcast, the update works. How to update with the broadcast?
Call to a member function load() on bool
public function SendToMarket(Request $request, $id)
{
$card = auth()->user()->cards()->findOrFail($id)->update([
'market_id' => $request["_market"],
'borderStyle_id' => $request["_borderStyle"],
'price' => $request["_price"]
]
);
$notification = array(
'message' => 'Card Send to market Successfully !',
'alert-type' => 'warning'
);
broadcast(new FetchCardEvent($card->load('user')))->toOthers();
return redirect()->route('user.cards')->with($notification);
}

update() does not return the Modal instance. Instead it will return a Boolean.
After retrieving the card using firstOrFail() you should update it separately.
public function SendToMarket(Request $request, $id) {
$card = auth()->user()->cards()->findOrFail($id);
$card->update([
'market_id' => $request["_market"],
'borderStyle_id' => $request["_borderStyle"],
'price' => $request["_price"]
]);
$notification = array(
'message' => 'Card Send to market Successfully !',
'alert-type' => 'warning'
);
broadcast(new FetchCardEvent($card->load('user')))->toOthers();
return redirect()->route('user.cards')->with($notification);
}

Related

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().

Toastr notification on failed form submit

I'm using toastr notification in my app. I send the notification when the form submit is failed due to validation or when the form submit is succeed. I usually do it this way :
public function store(Request $request) {
$data = $request->all();
$rules = [
'name' => 'required|string',
'email' => 'required|email',
'message' => 'required|string',
'g-recaptcha-response' => 'required|captcha',
];
$validate = Validator::make($data, $rules);
if ($validate->fails()) {
$error = array(
'message' => "Error sending the message!",
'alert-type' => 'error'
);
return back()->withErrors($validate)->withInput()->with($error);
}
Feedback::create($data);
$success = array(
'message' => "Thanks for the feedback! Your message was sent successfully!",
'alert-type' => 'success'
);
return redirect()->route('contactus')->with($success);
}
But when the table columns number is large (10 columns or more) I'd like to use Form Request Class instead rather than declaring the rules in the store method. So it became like this :
public function store(FeedbackRequest $request) {
$data = $request->all();
Feedback::create($data);
$success = array(
'message' => "Thanks for the feedback! Your message was sent successfully!",
'alert-type' => 'success'
);
return redirect()->route('contactus')->with($success);
}
The problem is, when using Form Request I don't know how to send the error notification when validation fails. Is there a way to check if Form Request Class validation failed so I can send the error notification ? That's all and thanks!
Adding After Hooks To Form Requests is exactly what you need in your Request class:
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($validator->failed()) {
$validator->errors()->add('field', 'Something is wrong with this field!'); // handle your new error message here
}
});
}

Resources