Search…
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:
1
webpush:
2
doctrine_mapping: true
Copied!
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

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
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Entity;
6
7
use Doctrine\ORM\Mapping as ORM;
8
use WebPush\Subscription as WebPushSubscription;
9
10
/**
11
* @ORM\Table(name="subscriptions")
12
* @ORM\Entity
13
*/
14
class Subscription extends WebPushSubscription
15
{
16
/**
17
* @ORM\Id
18
* @ORM\Column(type="integer")
19
* @ORM\GeneratedValue(strategy="AUTO")
20
*/
21
private ?int $id = null;
22
23
/**
24
* @ORM\ManyToOne(targetEntity="User", inversedBy="subscriptions", cascade={"persist"})
25
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable="true")
26
*/
27
private ?User $user;
28
29
public function getId(): ?int
30
{
31
return $this->id;
32
}
33
34
public function getUser(): ?User
35
{
36
return $this->user;
37
}
38
39
public function setUser(?User $user): self
40
{
41
$this->user = $user;
42
43
return $this;
44
}
45
46
// We need to override this method as it returns a WebPush\Subscription and we want an entity
47
public static function createFromString(string $input): self
48
{
49
$base = BaseSubscription::createFromString($input);
50
$object = new self($base->getEndpoint());
51
$object->withContentEncodings($base->getSupportedContentEncodings());
52
foreach ($base->getKeys()->all() as $k => $v) {
53
$object->getKeys()->set($k, $v);
54
}
55
56
return $object;
57
}
58
}
Copied!
In this exaple, we assume you already have a valid User entity class.

The User Entity

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
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Entity;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\Common\Collections\Collection;
9
use Doctrine\ORM\Mapping as ORM;
10
11
/**
12
* @ORM\Table(name="users")
13
* @ORM\Entity
14
*/
15
class User //Usual interface here
16
{
17
//Usual user stuff here
18
19
/**
20
* @ORM\OneToMany(targetEntity="Subscription", mappedBy="user")
21
*/
22
private Collection $subscriptions;
23
24
public function __construct()
25
{
26
$this->notifications = new ArrayCollection();
27
}
28
29
/**
30
* @return Notification[]
31
*/
32
public function getSubscriptions(): array
33
{
34
return $this->notifications->toArray();
35
}
36
37
public function addSubscription(Subscription $subscription): self
38
{
39
$subscription->setUser($this);
40
$this->subscriptions->add($subscription);
41
42
return $this;
43
}
44
45
public function removeSubscription(Subscription $subscription): self
46
{
47
$child->setUser(null);
48
$this->subscriptions->removeElement($subscription);
49
50
return $this;
51
}
52
}
Copied!

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().
1
$subscriptions = $user->getSubscriptions();
2
foreach ($subscriptions as $subscription) {
3
$report = $this->webPush->send($notification, $subscription);
4
if ($report->subscriptionExpired()) {
5
//...Remove this subscription
6
}
7
}
Copied!

Using Doctrine Type

The bundle auto-register the Doctrine type webpush_subscription. The Subscription object will automatically be converted.
src/Entity/Subscription.php
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Entity;
6
7
use Doctrine\ORM\Mapping as ORM;
8
use WebPush\Subscription as WebPushSubscription;
9
10
/**
11
* @ORM\Table(name="subscriptions")
12
* @ORM\Entity
13
*/
14
class Subscription
15
{
16
/**
17
* @ORM\Id
18
* @ORM\Column(type="integer")
19
* @ORM\GeneratedValue(strategy="AUTO")
20
*/
21
private ?int $id = null;
22
23
/**
24
* @ORM\ManyToOne(targetEntity="User", inversedBy="subscriptions", cascade={"persist"})
25
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable="true")
26
*/
27
private ?User $user;
28
29
/**
30
* @ORM\Column(type="webpush_subscription")
31
*/
32
private WebPushSubscription $subscription;
33
34
public function getId(): ?int
35
{
36
return $this->id;
37
}
38
39
public function getUser(): ?User
40
{
41
return $this->user;
42
}
43
44
public function setUser(?User $user): self
45
{
46
$this->user = $user;
47
48
return $this;
49
}
50
51
public function getSubscription(): WebPushSubscription
52
{
53
return $this->subscription;
54
}
55
}
Copied!

Using Your Own Entity Class

New in v1.1!
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.
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Entity;
6
7
use function array_key_exists;
8
use Assert\Assertion;
9
use DateTimeInterface;
10
use Safe\DateTimeImmutable;
11
use function Safe\json_decode;
12
13
class Subscription implements SubscriptionInterface
14
{
15
/**
16
* @ORM\Id
17
* @ORM\Column(type="integer")
18
* @ORM\GeneratedValue(strategy="AUTO")
19
*/
20
private ?int $id = null;
21
22
/**
23
* @ORM\Column(type="integer")
24
*/
25
private string $endpoint;
26
27
/**
28
* @ORM\Column(type="array")
29
*
30
* @var string[]
31
*/
32
private array $keys = [];
33
34
/**
35
* @ORM\Column(type="array")
36
*
37
* @var string[]
38
*/
39
private array $supportedContentEncodings = ['aesgcm'];
40
41
/**
42
* @ORM\Column(type="integer", nullable=true)
43
*/
44
private ?int $expirationTime = null;
45
46
public function __construct(string $endpoint)
47
{
48
$this->endpoint = $endpoint;
49
}
50
51
/**
52
* @param string[] $contentEncodings
53
*/
54
public function setContentEncodings(array $contentEncodings): self
55
{
56
$this->supportedContentEncodings = $contentEncodings;
57
58
return $this;
59
}
60
61
public function getKeys(): array
62
{
63
return $this->keys;
64
}
65
66
public function hasKey(string $key): bool
67
{
68
return isset($this->keys[$key]);
69
}
70
71
/**
72
* @return array<string, string>
73
*/
74
public function getKey(string $key): string
75
{
76
Assertion::keyExists($this->keys, $key, 'The key does not exist');
77
78
return $this->keys[$key];
79
}
80
81
public function setKeys(array $keys): self
82
{
83
$this->keys = $keys;
84
85
return $this;
86
}
87
88
public function getExpirationTime(): ?int
89
{
90
return $this->expirationTime;
91
}
92
93
public function setExpirationTime(?int $expirationTime): self
94
{
95
$this->expirationTime = $expirationTime;
96
97
return $this;
98
}
99
100
public function getEndpoint(): string
101
{
102
return $this->endpoint;
103
}
104
105
/**
106
* @return string[]
107
*/
108
public function getSupportedContentEncodings(): array
109
{
110
return $this->supportedContentEncodings;
111
}
112
113
/**
114
* @return array<string, string|string[]>
115
*/
116
public function jsonSerialize(): array
117
{
118
return [
119
'endpoint' => $this->endpoint,
120
'supportedContentEncodings' => $this->supportedContentEncodings,
121
'keys' => $this->keys,
122
];
123
}
124
}
Copied!