Doctrine
The bundle provides new Doctrine type and Schema to simplify the way you store the
Subscription
objects with Doctrine.To enable this feature, the following configuration option shall be set:
webpush:
doctrine_mapping: true
This will tell the bundle to register the Subscription object as a Doctrine mapped-superclass. The DoctrineBundle shall be enabled. No additional configuration is required.
First of all, we need to create a Subscription Entity that extends the Subscription object. In this example, we also need to associate one or more Subscription entities to a specific user (Many To One relationship).
src/Entity/Subscription.php
<?php
declare(strict_types=1);
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use WebPush\Subscription as WebPushSubscription;
/**
* @ORM\Table(name="subscriptions")
* @ORM\Entity
*/
class Subscription extends WebPushSubscription
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private ?int $id = null;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="subscriptions", cascade={"persist"})
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable="true")
*/
private ?User $user;
public function getId(): ?int
{
return $this->id;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
// We need to override this method as it returns a WebPush\Subscription and we want an entity
public static function createFromString(string $input): self
{
$base = BaseSubscription::createFromString($input);
$object = new self($base->getEndpoint());
$object->withContentEncodings($base->getSupportedContentEncodings());
foreach ($base->getKeys()->all() as $k => $v) {
$object->getKeys()->set($k, $v);
}
return $object;
}
}
In this exaple, we assume you already have a valid User entity class.
Now, to have a bidirectional relationship between this class and the User entity class, we will add this relationship to the User class.
src/Entity/User.php
<?php
declare(strict_types=1);
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="users")
* @ORM\Entity
*/
class User //Usual interface here
{
//Usual user stuff here
/**
* @ORM\OneToMany(targetEntity="Subscription", mappedBy="user")
*/
private Collection $subscriptions;
public function __construct()
{
$this->notifications = new ArrayCollection();
}
/**
* @return Notification[]
*/
public function getSubscriptions(): array
{
return $this->notifications->toArray();
}
public function addSubscription(Subscription $subscription): self
{
$subscription->setUser($this);
$this->subscriptions->add($subscription);
return $this;
}
public function removeSubscription(Subscription $subscription): self
{
$child->setUser(null);
$this->subscriptions->removeElement($subscription);
return $this;
}
}
Now that your entities are set, you can register Subcriptions and assign them to your users. To send a Notification to a specific user, you just have to get all subscriptions using
$user->getSubscriptions()
.$subscriptions = $user->getSubscriptions();
foreach ($subscriptions as $subscription) {
$report = $this->webPush->send($notification, $subscription);
if ($report->subscriptionExpired()) {
//...Remove this subscription
}
}
The bundle auto-register the Doctrine type webpush_subscription. The Subscription object will automatically be converted.
src/Entity/Subscription.php
<?php
declare(strict_types=1);
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use WebPush\Subscription as WebPushSubscription;
/**
* @ORM\Table(name="subscriptions")
* @ORM\Entity
*/
class Subscription
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private ?int $id = null;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="subscriptions", cascade={"persist"})
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable="true")
*/
private ?User $user;
/**
* @ORM\Column(type="webpush_subscription")
*/
private WebPushSubscription $subscription;
public function getId(): ?int
{
return $this->id;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function getSubscription(): WebPushSubscription
{
return $this->subscription;
}
}
It is possible to use your own Subscription entity class. The only constraint is that it shall implement the interface
WebPush\SubscriptionInterface
or shall have a method that returns an object that implements this interface.<?php
declare(strict_types=1);
namespace App\Entity;
use function array_key_exists;
use Assert\Assertion;
use DateTimeInterface;
use Safe\DateTimeImmutable;
use function Safe\json_decode;
class Subscription implements SubscriptionInterface
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private ?int $id = null;
/**
* @ORM\Column(type="integer")
*/
private string $endpoint;
/**
* @ORM\Column(type="array")
*
* @var string[]
*/
private array $keys = [];
/**
* @ORM\Column(type="array")
*
* @var string[]
*/
private array $supportedContentEncodings = ['aesgcm'];
/**
* @ORM\Column(type="integer", nullable=true)
*/
private ?int $expirationTime = null;
public function __construct(string $endpoint)
{
$this->endpoint = $endpoint;
}
/**
* @param string[] $contentEncodings
*/
public function setContentEncodings(array $contentEncodings): self
{
$this->supportedContentEncodings = $contentEncodings;
return $this;
}
public function getKeys(): array
{
return $this->keys;
}
public function hasKey(string $key): bool
{
return isset($this->keys[$key]);
}
/**
* @return array<string, string>
*/
public function getKey(string $key): string
{
Assertion::keyExists($this->keys, $key, 'The key does not exist');
return $this->keys[$key];
}
public function setKeys(array $keys): self
{
$this->keys = $keys;
return $this;
}
public function getExpirationTime(): ?int
{
return $this->expirationTime;
}
public function setExpirationTime(?int $expirationTime): self
{
$this->expirationTime = $expirationTime;
return $this;
}
public function getEndpoint(): string
{
return $this->endpoint;
}
/**
* @return string[]
*/
public function getSupportedContentEncodings(): array
{
return $this->supportedContentEncodings;
}
/**
* @return array<string, string|string[]>
*/
public function jsonSerialize(): array
{
return [
'endpoint' => $this->endpoint,
'supportedContentEncodings' => $this->supportedContentEncodings,
'keys' => $this->keys,
];
}
}
Last modified 5mo ago