Doctrine
The bundle provides new Doctrine type and Schema to simplify the way you store the Subscription
objects with Doctrine.
Using The Doctrine Mapping
Configuration
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.
The Subscription
Entity
Subscription
EntityFirst 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).
<?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;
}
}
The User
Entity
User
EntityNow, to have a bidirectional relationship between this class and the User entity class, we will add this relationship to the User class.
<?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;
}
}
Sending Notifications To A User
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
}
}
Using Doctrine Type
The bundle auto-register the Doctrine type webpush_subscription. The Subscription object will automatically be converted.
<?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;
}
}
Using Your Own Entity Class
Starting with v1.1, 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 updated
Was this helpful?