Add daily email
This commit is contained in:
parent
2a4bb625cf
commit
cad9689e1e
3 changed files with 127 additions and 0 deletions
|
@ -6586,5 +6586,12 @@
|
|||
],
|
||||
"path_alias.8c7da716-41b8-4149-9a92-533e00b81152": [
|
||||
"node.e8baa6f7-3c40-4a5e-a7a5-bbb9c8070feb"
|
||||
],
|
||||
"node.43311430-52e8-4fe6-8dd4-ab7d158adafa": [
|
||||
"user.b8966985-d4b2-42a7-a319-2e94ccfbb849",
|
||||
"node.c74de3cf-5362-4d08-935a-a9d0d22fcb94"
|
||||
],
|
||||
"path_alias.7d2f0477-5908-46ac-b524-921d9bedc6aa": [
|
||||
"node.43311430-52e8-4fe6-8dd4-ab7d158adafa"
|
||||
]
|
||||
}
|
93
content/node.43311430-52e8-4fe6-8dd4-ab7d158adafa.json
Normal file
93
content/node.43311430-52e8-4fe6-8dd4-ab7d158adafa.json
Normal file
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "43311430-52e8-4fe6-8dd4-ab7d158adafa"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-07-01T22:29:08+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "An example of generics in PHP"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-06-29T22:20:18+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-07-01T22:29:08+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/06\/29\/example-generics-php",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "Unfortunately, unlike other languages like Go and TypeScript, generics aren't supported in PHP, but they are possible with static analysis tools like PHPStan and Psalm.\r\n\r\nI use generics as they allow me to make code more reusable whilst still being robust.\r\n\r\nFor example, if I created a Collection class to represent the guests for a podcast episode, it could look like this:\r\n\r\n```php\r\n<?php\r\n\r\n\/**\r\n * @implements \\IteratorAggregate<mixed>\r\n *\/\r\nclass Guests implements \\IteratorAggregate {\r\n\r\n \/**\r\n * @param Guest[] $guests\r\n *\/\r\n public function __construct(private array $guests) {\r\n }\r\n\r\n public function count(): int {\r\n return count($this->items);\r\n }\r\n\r\n public function first(): Guest {\r\n return array_values($this->items)[0];\r\n }\r\n\r\n public function getIterator(): \\Traversable {\r\n return new \\ArrayIterator($this->items);\r\n }\r\n\r\n}\r\n```\r\n\r\nNote: the idea of using `IteratorAggregate` came from [from Dan Leech][1] and his talk at a local PHP meetup.\r\n\r\nEach contains an array of `Guest` objects that I can run methods like `count()` and `first()` on.\r\n\r\nEverything is typed so PHPStan can parse the code and provide as much assistance as possible.\r\n\r\nBut, what if I wanted to make a generic Collection that could accept any type of item?\r\n\r\nThat's where generics are useful.\r\n\r\nFirst, I need to define a template:\r\n\r\n```php\r\n\/**\r\n * @implements \\IteratorAggregate<mixed>\r\n * @template T\r\n *\/\r\n```\r\n\r\nNow `T` is defined, I can use it in place of the original `Guest` types:\r\n\r\n```php\r\n\/**\r\n * @param T[] $items\r\n *\/\r\npublic function __construct(private array $items) {\r\n}\r\n\r\n\/**\r\n * @return T|null\r\n *\/\r\npublic function first(): mixed {\r\n return array_values($this->items)[0];\r\n}\r\n```\r\n\r\nThis says that the Collection accepts an array of `T` items and returns either a `T` or null.\r\n\r\n`T` could be a `Guest`, a `NodeInterface` or anything else.\r\n\r\nBut, whatever it is, either a null value or the same type is returned.\r\n\r\nGenerics means that PHPStan can continue to give the most detailed analysis, my language server can give the best completion and diagnostics, and the code is flexible and easy to reuse.\r\n\r\nHopefully, generics will be a core PHP feature but, until then, the same benefits can be found from static analysis tools.\r\n\r\n[1]: \/daily\/2025\/03\/29\/collections",
|
||||
"format": "markdown",
|
||||
"processed": "<p>Unfortunately, unlike other languages like Go and TypeScript, generics aren't supported in PHP, but they are possible with static analysis tools like PHPStan and Psalm.<\/p>\n<p>I use generics as they allow me to make code more reusable whilst still being robust.<\/p>\n<p>For example, if I created a Collection class to represent the guests for a podcast episode, it could look like this:<\/p>\n<pre><code><?php\n\n\/**\n * @implements \\IteratorAggregate<mixed>\n *\/\nclass Guests implements \\IteratorAggregate {\n\n \/**\n * @param Guest[] $guests\n *\/\n public function __construct(private array $guests) {\n }\n\n public function count(): int {\n return count($this->items);\n }\n\n public function first(): Guest {\n return array_values($this->items)[0];\n }\n\n public function getIterator(): \\Traversable {\n return new \\ArrayIterator($this->items);\n }\n\n}\n<\/code><\/pre><p>Note: the idea of using <code>IteratorAggregate<\/code> came from <a href=\"http:\/\/localhost:8888\/daily\/2025\/03\/29\/collections\">from Dan Leech<\/a> and his talk at a local PHP meetup.<\/p>\n<p>Each contains an array of <code>Guest<\/code> objects that I can run methods like <code>count()<\/code> and <code>first()<\/code> on.<\/p>\n<p>Everything is typed so PHPStan can parse the code and provide as much assistance as possible.<\/p>\n<p>But, what if I wanted to make a generic Collection that could accept any type of item?<\/p>\n<p>That's where generics are useful.<\/p>\n<p>First, I need to define a template:<\/p>\n<pre><code>\/**\n * @implements \\IteratorAggregate<mixed>\n * @template T\n *\/\n<\/code><\/pre><p>Now <code>T<\/code> is defined, I can use it in place of the original <code>Guest<\/code> types:<\/p>\n<pre><code>\/**\n * @param T[] $items\n *\/\npublic function __construct(private array $items) {\n}\n\n\/**\n * @return T|null\n *\/\npublic function first(): mixed {\n return array_values($this->items)[0];\n}\n<\/code><\/pre><p>This says that the Collection accepts an array of <code>T<\/code> items and returns either a <code>T<\/code> or null.<\/p>\n<p><code>T<\/code> could be a <code>Guest<\/code>, a <code>NodeInterface<\/code> or anything else.<\/p>\n<p>But, whatever it is, either a null value or the same type is returned.<\/p>\n<p>Generics means that PHPStan can continue to give the most detailed analysis, my language server can give the best completion and diagnostics, and the code is flexible and easy to reuse.<\/p>\n<p>Hopefully, generics will be a core PHP feature but, until then, the same benefits can be found from static analysis tools.<\/p>\n",
|
||||
"summary": ""
|
||||
}
|
||||
],
|
||||
"field_daily_email_cta": [
|
||||
{
|
||||
"target_type": "node",
|
||||
"target_uuid": "c74de3cf-5362-4d08-935a-a9d0d22fcb94"
|
||||
}
|
||||
]
|
||||
}
|
27
content/path_alias.7d2f0477-5908-46ac-b524-921d9bedc6aa.json
Normal file
27
content/path_alias.7d2f0477-5908-46ac-b524-921d9bedc6aa.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "7d2f0477-5908-46ac-b524-921d9bedc6aa"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"value": "\/node\/43311430-52e8-4fe6-8dd4-ab7d158adafa"
|
||||
}
|
||||
],
|
||||
"alias": [
|
||||
{
|
||||
"value": "\/daily\/2025\/06\/29\/example-generics-php"
|
||||
}
|
||||
],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue