Simplest thing you can do is following:
broadcast(new JobUpdated($jobsCollection->toArray()))->toOthers();
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
Hi.. I want to broadcast an api resource collection (sometimes only resource) and I send it to event as argument
broadcast(new JobUpdated($jobsCollection)->toOthers();
In event class I want to do something like below :
use Dispatchable, InteractsWithSockets, SerializesModels;
public $jobs;
public $TypeOfJobsVariable;
public function __construct($updatedJobs)
{
$this->jobs = $updatedJobs;
$this->TypeOfJobsVariable = gettype($this->jobs);
}
public function broadcastOn()
{
$channels = [];
if (is_array($this->jobs)) {
foreach ($this->jobs as $job) {
$order = Order::find($job->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
} else {
$order = Order::find($this->jobs->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
return $channels;
}
when I check the type of $this->jobs it's object it's object both $this->jobs is collection and just single record.
How Can I make this foreach loop in event?
Simplest thing you can do is following:
broadcast(new JobUpdated($jobsCollection->toArray()))->toOthers();
@bugsysha api resource collection class is already returning an array:
public function toArray($request)
{
return parent::toArray($request);
}
when I add ->toArray() method it wants $request argument.. actually it must return an array already but in event it looks like object.
Not sure I understand you, but let me try. Just pass the collection and in your code do following:
foreach (collect($this->jobs) as $job) { // notice here that you need to do collect($this->jobs)
$order = Order::find($job->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
So if it is a collection it will not wrap it, but if it is not a collection it will wrap it. And then you will be able to loop over it even it there is a single record.
@bugsysha that didn't work also.. I will be give full code path to make it more understandable..
broadcast(new JobUpdated((new JobController)->orderJobs($id)))->toOthers(); // sending a controllers method as argument to JobUpdated event
public function orderJobs ($orderId) {
$orderJobs = Job::with($this->with)->where('order_id', $orderId)->get();
return new JobCollection($orderJobs);
} // returns JobColleciton
public function broadcastOn()
{
$channels = [];
if (is_array(collect($this->jobs))) { // it must be an array but goes into else state..
foreach ($this->jobs as $job) {
$order = Order::find($job->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
} else {
$order = Order::find($this->jobs->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
// todo: when managers roles created, manager user ids will be added to channels..
return $channels;
}
So you are saying that you are unable to send the proper argument to the event object?
I think I send proper argument but I can't use it in event as I expect. Normally I get object array resposne from jobOrders method.. I expect an array like its http response. There is a point about event that I miss.
It is not a point that you miss about event, you miss it before event. Event is not swapping out anything during it's lifecycle.
the problem is I can not check $this->jobs is array or not.. Because even I send an object array or single object to event argument its type returns object.
dd(gettype($this->jobs)); put this at the top and report back what the result is.
public function broadcastOn()
{
dd(gettype($this->jobs)); // PUT THIS AT THE TOP AND REPORT BACK WHAT THE RESULT IS
$channels = [];
if (is_array(collect($this->jobs))) { // it must be an array but goes into else state..
foreach ($this->jobs as $job) {
$order = Order::find($job->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
} else {
$order = Order::find($this->jobs->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
// todo: when managers roles created, manager user ids will be added to channels..
return $channels;
}
@bugsysha "dd(gettype($this->jobs)); put this at the top and report back what the result is." already did.. and I said it returns type object.
You are just not listening. Sorry but I can not help you like this. All best.
ok anyway.. thank you..
Hi @mecjos
I don't think you are getting an Array here. I know that API Resource Collections are supposed to return an array, but that's when are returned as a Response from a Route (or Controller method).
In this case, you are probably passing an Eloquent Collection which is an Object, and that's why you allways see an object when you ask for it's type.
I'd remove the if statement and do a foreach straight away.
If it's only one object, it will contained inside a Collection anyway.
To be sure, paste here the result of doing add($this->jobs) at the top of the broadcasOn() method and see if it's always a Collection, even when only one result is returned.
To wrap up, you should end up with something like this:
use Dispatchable, InteractsWithSockets, SerializesModels;
public $jobs;
public $TypeOfJobsVariable;
public function __construct($updatedJobs)
{
$this->jobs = $updatedJobs;
$this->TypeOfJobsVariable = gettype($this->jobs);
}
public function broadcastOn()
{
$channels = [];
foreach ($this->jobs as $job) {
$order = Order::find($job->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
return $channels;
}
Hope this works for you!
Thank you so much @marianomoreyra for your interest. Yes you are right, it's JobCollection resource when I fetch multiple record and JobResource for single record like below.. But foreach doesn't work for JobResource because I think JobResource cotains one resource object, in case JobCollection it contains collection array. I need to determine whether $updatedJobs contains collection or not.
When send broadcast(new JobUpdated((new JobController)->orderJobs($id)))->toOthers();
App\Http\Resources\JobCollection {#1745
+collects: null
+collection: Illuminate\Support\Collection {#1779
#items: array:1 [
0 => App\Job {#1784
#fillable: array:12 [
0 => "user_id"
1 => "order_id"
2 => "part_id"
3 => "project_id"
4 => "operation_id"
5 => "queue"
6 => "is_prior"
7 => "state_id"
8 => "finish_date"
9 => "completed"
10 => "is_combined"
11 => "is_active"
]
#casts: array:10 [
"order_id" => "int"
"part_id" => "int"
"project_id" => "int"
"operation_id" => "int"
"state_id" => "int"
"is_active" => "boolean"
"is_prior" => "boolean"
"is_combined" => "boolean"
"queue" => "int"
"completed" => "int"
]
#connection: "mysql"
#table: "jobs"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:18 [
"id" => 59
"user_id" => 2
"order_id" => 59
"part_id" => 137
"project_id" => 2
"operation_id" => 1
"state_id" => 4
"queue" => null
"completed" => 0
"cost" => "0.00"
"start_date" => null
"finish_date" => null
"pf_date" => null
"is_prior" => 0
"is_active" => 0
"is_combined" => 0
"created_at" => "2021-01-16 11:53:34"
"updated_at" => "2021-01-16 11:53:48"
]
#original: array:18 [
"id" => 59
"user_id" => 2
"order_id" => 59
"part_id" => 137
"project_id" => 2
"operation_id" => 1
"state_id" => 4
"queue" => null
"completed" => 0
"cost" => "0.00"
"start_date" => null
"finish_date" => null
"pf_date" => null
"is_prior" => 0
"is_active" => 0
"is_combined" => 0
"created_at" => "2021-01-16 11:53:34"
"updated_at" => "2021-01-16 11:53:48"
]
#changes: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:2 [
"state" => App\State {#2044
+timestamps: false
#connection: "mysql"
#table: "states"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:3 [
"id" => 4
"color" => "red-12"
"class" => "bg-red-12"
]
#original: array:3 [
"id" => 4
"color" => "red-12"
"class" => "bg-red-12"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [
"stateLang" => Illuminate\Database\Eloquent\Collection {#2053
#items: array:2 [
0 => App\StateLang {#1787
+timestamps: false
#connection: "mysql"
#table: "state_langs"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:4 [
"id" => 7
"state_id" => 4
"lang_id" => 1
"name" => "İptal edildi"
]
#original: array:4 [
"id" => 7
"state_id" => 4
"lang_id" => 1
"name" => "İptal edildi"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
}
1 => App\StateLang {#2041
+timestamps: false
#connection: "mysql"
#table: "state_langs"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:4 [
"id" => 8
"state_id" => 4
"lang_id" => 2
"name" => "Cancelled"
]
#original: array:4 [
"id" => 8
"state_id" => 4
"lang_id" => 2
"name" => "Cancelled"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
}
]
}
]
#touches: []
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
}
"project" => App\Project {#1791
#fillable: array:8 [
0 => "name"
1 => "project_no"
2 => "customer_id"
3 => "user_id"
4 => "cad3d_name"
5 => "description"
6 => "start_date"
7 => "projected_finish_date"
]
#casts: array:3 [
"customer_id" => "int"
"user_id" => "int"
"active" => "int"
]
#connection: "mysql"
#table: "projects"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:11 [
"id" => 2
"name" => "Şasi Deneme"
"project_no" => "PRJ-03"
"customer_id" => 3
"user_id" => 2
"description" => null
"start_date" => null
"projected_finish_date" => null
"active" => 1
"created_at" => "2020-12-22 18:52:45"
"updated_at" => "2021-01-09 14:42:49"
]
#original: array:11 [
"id" => 2
"name" => "Şasi Deneme"
"project_no" => "PRJ-03"
"customer_id" => 3
"user_id" => 2
"description" => null
"start_date" => null
"projected_finish_date" => null
"active" => 1
"created_at" => "2020-12-22 18:52:45"
"updated_at" => "2021-01-09 14:42:49"
]
#changes: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [
"customer" => App\Customer {#2045
#fillable: array:7 [
0 => "name"
1 => "address"
2 => "email"
3 => "phone"
4 => "ref_number"
5 => "parent_user_id"
6 => "user_id"
]
#casts: array:3 [
"parent_user_id" => "int"
"user_id" => "int"
"active" => "int"
]
#connection: "mysql"
#table: "customers"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:11 [
"id" => 3
"parent_user_id" => 2
"user_id" => 9
"name" => "Adinamik"
"address" => "null"
"ref_number" => "M001"
"email" => "[email protected]"
"phone" => null
"active" => 1
"created_at" => "2020-08-21 21:51:32"
"updated_at" => "2020-08-21 21:51:32"
]
#original: array:11 [
"id" => 3
"parent_user_id" => 2
"user_id" => 9
"name" => "Adinamik"
"address" => "null"
"ref_number" => "M001"
"email" => "[email protected]"
"phone" => null
"active" => 1
"created_at" => "2020-08-21 21:51:32"
"updated_at" => "2020-08-21 21:51:32"
]
#changes: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
]
}
+resource: Illuminate\Support\Collection {#1779}
+with: []
+additional: []
}
and when send broadcast(new JobUpdated((new JobController)->show($id)))->toOthers();
App\Http\Resources\JobResource {#1726
+resource: App\Job {#1779
#fillable: array:12 [
0 => "user_id"
1 => "order_id"
2 => "part_id"
3 => "project_id"
4 => "operation_id"
5 => "queue"
6 => "is_prior"
7 => "state_id"
8 => "finish_date"
9 => "completed"
10 => "is_combined"
11 => "is_active"
]
#casts: array:10 [
"order_id" => "int"
"part_id" => "int"
"project_id" => "int"
"operation_id" => "int"
"state_id" => "int"
"is_active" => "boolean"
"is_prior" => "boolean"
"is_combined" => "boolean"
"queue" => "int"
"completed" => "int"
]
#connection: "mysql"
#table: "jobs"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:18 [
"id" => 57
"user_id" => 2
"order_id" => 57
"part_id" => 137
"project_id" => 2
"operation_id" => 1
"state_id" => 4
"queue" => null
"completed" => 0
"cost" => "0.00"
"start_date" => null
"finish_date" => null
"pf_date" => null
"is_prior" => 0
"is_active" => 0
"is_combined" => 0
"created_at" => "2021-01-16 00:55:55"
"updated_at" => "2021-01-16 00:56:08"
]
#original: array:18 [
"id" => 57
"user_id" => 2
"order_id" => 57
"part_id" => 137
"project_id" => 2
"operation_id" => 1
"state_id" => 4
"queue" => null
"completed" => 0
"cost" => "0.00"
"start_date" => null
"finish_date" => null
"pf_date" => null
"is_prior" => 0
"is_active" => 0
"is_combined" => 0
"created_at" => "2021-01-16 00:55:55"
"updated_at" => "2021-01-16 00:56:08"
]
#changes: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:2 [
"state" => App\State {#1784
+timestamps: false
#connection: "mysql"
#table: "states"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:3 [
"id" => 4
"color" => "red-12"
"class" => "bg-red-12"
]
#original: array:3 [
"id" => 4
"color" => "red-12"
"class" => "bg-red-12"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [
"stateLang" => Illuminate\Database\Eloquent\Collection {#2044
#items: array:2 [
0 => App\StateLang {#2053
+timestamps: false
#connection: "mysql"
#table: "state_langs"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:4 [
"id" => 7
"state_id" => 4
"lang_id" => 1
"name" => "İptal edildi"
]
#original: array:4 [
"id" => 7
"state_id" => 4
"lang_id" => 1
"name" => "İptal edildi"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
}
1 => App\StateLang {#1787
+timestamps: false
#connection: "mysql"
#table: "state_langs"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:4 [
"id" => 8
"state_id" => 4
"lang_id" => 2
"name" => "Cancelled"
]
#original: array:4 [
"id" => 8
"state_id" => 4
"lang_id" => 2
"name" => "Cancelled"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
}
]
}
]
#touches: []
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
}
"project" => App\Project {#2041
#fillable: array:8 [
0 => "name"
1 => "project_no"
2 => "customer_id"
3 => "user_id"
4 => "cad3d_name"
5 => "description"
6 => "start_date"
7 => "projected_finish_date"
]
#casts: array:3 [
"customer_id" => "int"
"user_id" => "int"
"active" => "int"
]
#connection: "mysql"
#table: "projects"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:11 [
"id" => 2
"name" => "Şasi Deneme"
"project_no" => "PRJ-03"
"customer_id" => 3
"user_id" => 2
"description" => null
"start_date" => null
"projected_finish_date" => null
"active" => 1
"created_at" => "2020-12-22 18:52:45"
"updated_at" => "2021-01-09 14:42:49"
]
#original: array:11 [
"id" => 2
"name" => "Şasi Deneme"
"project_no" => "PRJ-03"
"customer_id" => 3
"user_id" => 2
"description" => null
"start_date" => null
"projected_finish_date" => null
"active" => 1
"created_at" => "2020-12-22 18:52:45"
"updated_at" => "2021-01-09 14:42:49"
]
#changes: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [
"customer" => App\Customer {#1791
#fillable: array:7 [
0 => "name"
1 => "address"
2 => "email"
3 => "phone"
4 => "ref_number"
5 => "parent_user_id"
6 => "user_id"
]
#casts: array:3 [
"parent_user_id" => "int"
"user_id" => "int"
"active" => "int"
]
#connection: "mysql"
#table: "customers"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:11 [
"id" => 3
"parent_user_id" => 2
"user_id" => 9
"name" => "Adinamik"
"address" => "null"
"ref_number" => "M001"
"email" => "[email protected]"
"phone" => null
"active" => 1
"created_at" => "2020-08-21 21:51:32"
"updated_at" => "2020-08-21 21:51:32"
]
#original: array:11 [
"id" => 3
"parent_user_id" => 2
"user_id" => 9
"name" => "Adinamik"
"address" => "null"
"ref_number" => "M001"
"email" => "[email protected]"
"phone" => null
"active" => 1
"created_at" => "2020-08-21 21:51:32"
"updated_at" => "2020-08-21 21:51:32"
]
#changes: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
+with: []
+additional: []
}
Oh ok, I see now @mecjos
It wasn't clear that you were passing to different objects to the Event! I guess you have to options:
1 - Make the JobResource a Collection when passing it to the Event:
broadcast(new JobUpdated( collect((new JobController)->show($id))) )->toOthers();
Although that's similar to a solution suggested by bugsysha that you said it didn't work.
2 - Check the type using get_class() instead of is_array or gettype():
public function broadcastOn()
{
$channels = [];
if (get_class($this->jobs) == "App\Http\Resources\JobCollection") {
foreach ($this->jobs as $job) {
$order = Order::find($job->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
} else {
$order = Order::find($this->jobs->order_id);
$userId = Machine::find($order->machine_id)->operator->user->id;
array_push($channels, new PrivateChannel('Job.' . $userId));
}
return $channels;
}
I guess this second one should work without any problems....
Hope this helps!
Thank you... second solution is good for me.. Even I pass collect((new JobController)->show($id))), I will need to check it's a JobResource or JobCollection.. I thought to do that by checking array or not :) that solution solved.. thanks again.
@mecjos wow that was fast!! hehe
Well, actually in the first case, you shouldn't need to check as you should always get a Collection, although you can't trust that you'll always remember to do so...so I like the second solution the most too :)
Anyway, I'm glad it worked!!
:)) yeah fast beause I have been trying to solve that problem for 2 days. :) I have been waiting the anwer.. I try to make live data update when someone change the data. And all response should stay same, collection rosponse should be collection and etc.. because of frontside structure I can not send collection instead of resource object response. :) I hope it's not confusing :))
Please or to participate in this conversation.