I have different models, which describe different tables in database.
I use this trait for these classes
trait ApplicationModelTrait
{
protected static $_currentModel = null;
protected $currentModel;
public static function setCurrentModel(ApplicationModel $model) {
static::$_currentModel = $model;
}
public function __construct(array $attributes = [], ApplicationModel $model = null) {
parent::__construct($attributes);
$this->currentModel = $model !== null ? $model : static::$_currentModel;
if($this->currentModel === null) throw new \InvalidArgumentException('No model passed');
}
}
All models are similar. The only difference is what fields exist in database for every model, so I describe these fields in separate config and main model class ApplicationModel
has some methods to work with different tables. For example
public function getInstanceTable() {
return 'application_model_instances_' . $this->name;
}
public function getCommentsTable() {
return 'application_model_instance_' . $this->name . '_comments';
}
Where application_model_instances_{name}
contains (obviously) instances of this model and application_model_instance_{name}_comments
contains comments for instances of this model.
Everything works fine except events.
When I add comment to model instance, I pass as argument current model
$comment = new ApplicationModelInstanceComment([], $this->currentModel);
$comment->text = $request->input('comment');
// etc.
After comment has been saved I want it to be instantly delivered to user browser via websocket
event(new CommentCreated($comment, $this)); // this
represents model instance class
And, finally, the event
namespace App\Events;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\Models\Application\ApplicationModelInstanceComment;
use App\Models\Application\ApplicationModelInstance;
class CommentCreated implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;
public $comment;
public $instance;
public function __construct(ApplicationModelInstanceComment $comment, ApplicationModelInstance $instance)
{
$this->comment = $comment;
$this->instance = $instance;
}
public function broadcastOn() {
$notifiableUsers = $this->instance->getNotifiableUsers(); // this method is used to fetch list of users who must get this comment in their browser
$channels = [];
foreach($notifiableUsers as $user) {
$channels[] = new PrivateChannel('user.' . $user->id);
}
return $channels;
}
}
But when I add comment Laravel my code throws an exception (this is what I see in network tab in Google Chrome because request is done via ajax:
Whoops, looks like something went wrong.
1/1 InvalidArgumentException in ApplicationModelTrait.php line 20: No model passed
in ApplicationModelTrait.php line 20
at ApplicationModelInstanceComment->__construct() in SerializesAndRestoresModelIdentifiers.php line 45
at CommentCreated->getRestoredPropertyValue(object(ModelIdentifier)) in SerializesModels.php line 41
at CommentCreated->__wakeup()
at unserialize('O:38:"Illuminate\\Broadcasting\\BroadcastEvent":4:{s:5:"event";O:25:"App\\Events\\CommentCreated":3:{s:7:"comment";O:45:"Illuminate\\Contracts\\Database\\ModelIdentifier":2:{s:5:"class";s:54:"App\\Models\\Application\\ApplicationModelInstanceComment";s:2:"id";i:68;}s:8:"instance";O:45:"Illuminate\\Contracts\\Database\\ModelIdentifier":2:{s:5:"class";s:47:"App\\Models\\Application\\ApplicationModelInstance";s:2:"id";i:11;}s:6:"socket";N;}s:10:"connection";N;s:5:"queue";N;s:5:"delay";N;}') in CallQueuedHandler.php line 95
at CallQueuedHandler->failed(array('commandName' => 'Illuminate\\Broadcasting\\BroadcastEvent', 'command' => 'O:38:"Illuminate\\Broadcasting\\BroadcastEvent":4:{s:5:"event";O:25:"App\\Events\\CommentCreated":3:{s:7:"comment";O:45:"Illuminate\\Contracts\\Database\\ModelIdentifier":2:{s:5:"class";s:54:"App\\Models\\Application\\ApplicationModelInstanceComment";s:2:"id";i:68;}s:8:"instance";O:45:"Illuminate\\Contracts\\Database\\ModelIdentifier":2:{s:5:"class";s:47:"App\\Models\\Application\\ApplicationModelInstance";s:2:"id";i:11;}s:6:"socket";N;}s:10:"connection";N;s:5:"queue";N;s:5:"delay";N;}'), object(InvalidArgumentException)) in Job.php line 158
at Job->failed(object(InvalidArgumentException)) in FailingJob.php line 33
I've passed model into ApplicationModelInstanceComment upon creation of comment, so everything is fine here. There is some problem with deserialization, but I do not know how to deal with this problem.
via Jackson J