问题
I have an event in my Laravel application that for specific records it exceeds the allowed maximum limit (10240 bytes) of Pusher. Is it correct that Laravel serializes every public attribute on the Event class? If so I suspect that the serialized model should not exceed the 10kb limit but it fails anyway. Are there any approaches to decrease the size of the data content?
class PostChanged implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $post;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Post $post)
{
$this->post = $post;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('post-channel.'.$this->post->id);
}
public function broadcastWith()
{
$extra = [
'data' => $this->post->data,
];
return array_merge($this->post->toArray(), $extra);
}
}
produces:
The data content of this event exceeds the allowed maximum (10240 bytes).
See http://pusher.com/docs/server_api_guide/server_publishing_events for more info
回答1:
Approach 1: Resolve at client side
The most reliable approach would be what @ExohJosh described: Only send the event type along with an ID so the client (most likely JavaScript) can fetch the updated record through a separate REST (or whatever) API.
public function broadcastWith()
{
return [
'id' => $this->post->id,
];
}
Approach 2: Reduce Payload
An alternative (and simpler) approach would be to send only the data required by the client (the one you figured out yourself @sarotnem). However this approach is only safe, if you definitely know that the attributes you submit can not in any case exceed the 10KiB limit. This can be ensured through input validation, limitations on DB columns or other means.
When choosing this approach, be sure to also include the size of any relationships, that could possibly be loaded on the model, into your calculations.
A neat way to define an "external representation" of a model are Laravel's API Resources. They could make your code look like this:
public function broadcastWith()
{
return [
'post' => new \App\Http\Resources\PostResource($this->post),
];
}
where App\Http\Resources\PostResource
could be:
class PostResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'body' => $this->body,
];
}
}
回答2:
An approach I have taken to this in the past when working with large objects is to consider segregation of the large object or pass a reference of the object EG: the id and then do the additional functionality in the event listener.
An approach in the case of a post changing could be:
The post is changed on client 1.
Backend lets pusher know the post has changed and receives the id
Pusher broadcasts to client 2
client 2 is listening and hits the endpoint to get a client by id
If this approach isn't going to work for you – You need to check if the object you are serialising has any redundancies in data, if you are passing too much there is an issue there.
回答3:
After quite a lot of experimenting I've managed to get it working by simply unsetting some unnecessary values of the array produced by $post->toArray()
.
Also I noticed that the broadcastWith()
method returns the payload as an array and not serialised.
来源:https://stackoverflow.com/questions/51147924/laravel-event-exceeds-pusher-allowed-limit