[presentations] master: Tweaks
[email protected] (Rasmus Lerdorf) Wed, 29 Sep 2021 17:52:14 +0000
| Newsgroups | php.pres |
|---|---|
| Message-ID | <[email protected]> |
Author: Rasmus Lerdorf (rlerdorf)
Date: 2021-09-29T10:52:41-07:00
Commit: https://github.com/php/presentations/commit/306f90b64a8b9b8948c80d0f4bbd2f39a7476a13
Raw diff: https://github.com/php/presentations/commit/306f90b64a8b9b8948c80d0f4bbd2f39a7476a13.diff
Tweaks
Changed paths:
A slides/intro/php81_2021.xml
M etsymex21.html
M etsymex21.xml
Diff:
diff --git a/etsymex21.html b/etsymex21.html
index ea61c7c9..251add2a 100644
--- a/etsymex21.html
+++ b/etsymex21.html
@@ -201,7 +201,7 @@ <h3>Sep.30, 2021</h3>
</section>
<section id="etsyfw2" >
<p class="p" style="font-size:1.4em;text-align:left;">awesome.php</p>
- <pre><code data-trim style="font-size:1em;" >require 'bootstrap.php';
+ <pre><code data-trim style="font-size:1em;" >require 'bootstrap.php';
$request = HTTP_Request::getInstance();
$response = HTTP_Response::getInstance();
$controller = new Awesome_Controller();
@@ -214,13 +214,13 @@ <h3>Sep.30, 2021</h3>
<p class="p" style="font-size:1.4em;text-align:left;">Code/Awesome/Controller.php</p>
<pre><code data-trim style="font-size:1em;" >class Awesome_Controller extends Controller_Base {
public function doCoolThings($request, $response) {
- $id = $request->getGet('id', 0);
+ $id = $request->getGet('id', 0);
if (!$id) {
$response->redirect_error(Constants::ERROR_NOT_FOUND);
return;
}
- $thing = EtsyORM::getFinder('Thing')->findById($id);
- $stuff = Api::endpoint('AwesomeStuff', [$thing->id, 'max'=>10]);
+ $thing = EtsyORM::getFinder('Thing')->findById($id);
+ $stuff = Api::endpoint('AwesomeStuff', [$thing->id, 'max'=>10]);
$this->renderViewTree(New Awesome_View($thing, $stuff));
}
}</code></pre>
@@ -240,12 +240,12 @@ <h3>Sep.30, 2021</h3>
$this->stuff = $stuff;
}
public function getCssFiles(): array {
- return [ '/awesome/main.scss' ];
+ return [ '/awesome/main.scss' ];
}
public function getTemplateData(): array {
- return [ 'thing_id' => $this->thing->id,
- 'thing_name' => $this->thing->name,
- 'stuff' => $this->stuff ];
+ return [ 'thing_id' => $this->thing->id,
+ 'thing_name' => $this->thing->name,
+ 'stuff' => $this->stuff ];
}
}</code></pre>
</section>
@@ -272,9 +272,9 @@ <h1 style="text-align:center;">Static Analysis</h1>
<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >$ composer require --dev phan/phan</code></pre>
<p class="p" style="font-size:1.5em;text-align:left;">Create .phan/config.php</p>
<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >return [
- 'target_php_version' => '8.0',
- 'directory_list' => [ 'src/' ],
- "exclude_analysis_directory_list" => [ 'vendor/' ],
+ 'target_php_version' => '8.0',
+ 'directory_list' => [ 'src/' ],
+ "exclude_analysis_directory_list" => [ 'vendor/' ],
];</code></pre>
<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >$ ./vendor/bin/phan</code></pre>
</section>
@@ -294,7 +294,7 @@ <h1 style="text-align:center;">Static Analysis</h1>
<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >$ phan --daemonize-tcp-port default &
[1] 28610
Listening for Phan analysis requests at tcp://127.0.0.1:4846
-Awaiting analysis requests for directory '/home/rasmus/phan_demo'
+Awaiting analysis requests for directory '/home/rasmus/phan_demo'
$ vi src/script.php</code></pre>
<pre><code class="shell nohighlight" data-trim style="font-size:1em;" >$ phan_client -l src/script.php
@@ -322,7 +322,7 @@ <h1 style="text-align:center;">phpspy</h1>
</section>
<section id="spy1" >
<p class="p" style="font-size:1.1em;text-align:left;">Sample frequency in nanoseconds (or Hz)</p>
- <pre><code class="shell nohighlight" data-trim style="font-size:0.9em;" >$ phpspy -s 200000000 -- php -r 'sleep(1);'
+ <pre><code class="shell nohighlight" data-trim style="font-size:0.9em;" >$ phpspy -s 200000000 -- php -r 'sleep(1);'
0 sleep <internal>:-1
1 <main> <internal>:-1
@@ -482,7 +482,7 @@ <h2 style="text-align:center;">How do you manage deploys?</h2>
*** pushbot has changed the topic on #push to <prod> *joe *frank|bob Rasmus
joe: .done
*** pushbot has changed the topic on #push to <prod> bob Rasmus
-pushbot: bob Rasmus: You're up
+pushbot: bob Rasmus: You're up
bob: .in
*** pushbot has changed the topic on #push *bob Rasmus
Rasmus: .in
@@ -618,7 +618,7 @@ <h1 style="text-align:center;">PHP 8.0</h1>
// instead of
-htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);</code></pre>
+htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);</code></pre>
</section>
<section id="php80_promotion" >
<p class="p" style="font-size:1.1em;text-align:left;">Constructor Property Promotion</p>
@@ -655,16 +655,16 @@ <h1 style="text-align:center;">PHP 8.0</h1>
</section>
<section id="php80_match" >
<p class="p" style="font-size:1em;text-align:left;">Match Expression</p>
- <pre><code data-trim style="font-size:0.9em;" >$statement = match ($this->lexer->lookahead['type']) {
+ <pre><code data-trim style="font-size:0.9em;" >$statement = match ($this->lexer->lookahead['type']) {
Lexer::T_SELECT => $this->SelectStatement(),
Lexer::T_UPDATE => $this->UpdateStatement(),
Lexer::T_DELETE => $this->DeleteStatement(),
- default => $this->syntaxError('SELECT, UPDATE or DELETE'),
+ default => $this->syntaxError('SELECT, UPDATE or DELETE'),
};
// Throws UnhandledMatchError on no match and no default expr
// instead of
-switch ($this->lexer->lookahead['type']) {
+switch ($this->lexer->lookahead['type']) {
case Lexer::T_SELECT:
$statement = $this->SelectStatement();
break;
@@ -675,7 +675,7 @@ <h1 style="text-align:center;">PHP 8.0</h1>
$statement = $this->DeleteStatement();
break;
default:
- $this->syntaxError('SELECT, UPDATE or DELETE');
+ $this->syntaxError('SELECT, UPDATE or DELETE');
break;
}</code></pre>
<aside class="notes"><br />
@@ -725,7 +725,7 @@ <h1 style="text-align:center;">PHP 8.0</h1>
return self::$data[$key];
}
}
-Store::add('player2', [1,2,3]);
+Store::add('player2', [1,2,3]);
// TypeError: Store::add(): Argument #2 ($val) must be of
// type string|int|float, array given</code></pre>
<aside class="notes"><br />
@@ -752,14 +752,14 @@ <h1 style="text-align:center;">PHP 8.0</h1>
}
$xkcd = new Endpoint("http://xkcd.com/info.0.json", fn($x)=>json_decode($x, associative:false));
-$joke = new Endpoint("https://icanhazdadjoke.com/", opts:['http'=>['header'=>"Accept:text/plain"]]);
-echo '<img src="'.Api::fetch($xkcd)->img.'" alt="'.Api::fetch($xkcd)->alt.'">'."\n";
+$joke = new Endpoint("https://icanhazdadjoke.com/", opts:['http'=>['header'=>"Accept:text/plain"]]);
+echo '<img src="'.Api::fetch($xkcd)->img.'" alt="'.Api::fetch($xkcd)->alt.'">'."\n";
echo Api::fetch($joke) . "\n";
echo Api::$cache->count() . "\n"; // 2
unset($xkcd);
echo Api::$cache->count() . "\n"; // 1
echo Api::fetch($joke) . "\n"; // Same bad joke
-$joke = new Endpoint("https://icanhazdadjoke.com/", opts:['http'=>['header'=>"Accept:text/plain"]]);
+$joke = new Endpoint("https://icanhazdadjoke.com/", opts:['http'=>['header'=>"Accept:text/plain"]]);
echo Api::fetch($joke) . "\n"; // New bad joke
echo Api::$cache->count() . "\n"; // 2?
gc_collect_cycles(); // Force gc
@@ -779,7 +779,7 @@ <h1 style="text-align:center;">PHP 8.0</h1>
private $id;
#[ORM\Column("string", ORM\Column::UNIQUE)]
- #[Assert\Email(array("message" => "The email '{{ value }}' is not a valid email."))]
+ #[Assert\Email(array("message" => "The email '{{ value }}' is not a valid email."))]
private $email;
#[Assert\Range(["min" => 120, "max" => 180, "minMessage" => "You must be at least {{ limit }}cm tall to enter"])]
@@ -798,6 +798,142 @@ <h1 style="text-align:center;">PHP 8.0</h1>
One per line, or comma-separated on same attribute line<br />
</aside>
</section> </section>
+ <section>
+ <section id="php81">
+ <h1 style="text-align:center;">PHP 8.1</h1>
+ </section>
+ <section id="php81_readonly_props" >
+ <p class="p" style="font-size:1.1em;text-align:left;">Readonly properties</p>
+ <div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/readonly_properties_v2" target="">https://wiki.php.net/rfc/readonly_properties_v2</a></div>
+ <pre><code data-trim style="font-size:1em;" >class Test {
+ public readonly string $prop;
+
+ public function __construct(string $prop) {
+ $this->prop = $prop; // Initialized once in same scope
+ }
+}
+
+$test = new Test("foobar");
+var_dump($test->prop);
+$test->prop = "foobar"; // Error</code></pre>
+ </section>
+ <section id="php81_enums" >
+ <p class="p" style="font-size:1.1em;text-align:left;">Enums</p>
+ <div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/enumerations" target="">https://wiki.php.net/rfc/enumerations</a></div>
+ <pre><code data-trim style="font-size:1em;" >enum Suit {
+ case Hearts;
+ case Diamonds;
+ case Clubs;
+ case Spades;
+}
+
+function pick_a_card(Suit $suit) { ... }
+pick_a_card(Suit::Clubs); // ok
+pick_a_card('Spades'); // error</code></pre>
+ </section>
+ <section id="php81_fibers" >
+ <p class="p" style="font-size:1.1em;text-align:left;">Fibers</p>
+ <div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/fibers" target="">https://wiki.php.net/rfc/fibers</a></div>
+ <pre><code data-trim style="font-size:1em;" >use React\EventLoop\LoopInterface;
+use React\Promise\PromiseInterface;
+
+function await(PromiseInterface $promise, LoopInterface $loop): mixed {
+ $fiber = Fiber::this();
+ $promise->done(
+ fn(mixed $value) => $loop->futureTick(fn() => $fiber->resume($value)),
+ fn(Throwable $reason) => $loop->futureTick(fn() => $fiber->throw($reason))
+ );
+
+ return Fiber::suspend();
+}</code></pre>
+ </section>
+ <section id="php81_fibers" >
+ <p class="p" style="font-size:1.1em;text-align:left;">Static Variable Inheritance</p>
+ <div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/static_variable_inheritance" target="">https://wiki.php.net/rfc/static_variable_inheritance</a></div>
+ <pre><code data-trim style="font-size:1em;" >class A {
+ public static function counter() {
+ static $i = 0;
+ return ++$i;
+ }
+}
+class B extends A {}
+
+echo A::counter();
+echo A::counter();
+echo B::counter();
+echo B::counter();
+// PHP 8.0 outputs 1212
+// PHP 8.1 outputs 1234</code></pre>
+ </section>
+ <section id="php81_never" >
+ <p class="p" style="font-size:1.1em;text-align:left;">Never Return Type</p>
+ <div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/noreturn_type" target="">https://wiki.php.net/rfc/noreturn_type</a></div>
+ <pre><code data-trim style="font-size:1em;" >function redirect(string $uri): never {
+ header('Location: ' . $uri);
+ exit();
+}
+
+redirect('/index.html');
+echo "this will never be executed!";</code></pre>
+ </section>
+ <section id="php81_final" >
+ <p class="p" style="font-size:1.1em;text-align:left;">Final class constants</p>
+ <div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/final_class_const" target="">https://wiki.php.net/rfc/final_class_const</a></div>
+ <pre><code data-trim style="font-size:1em;" >class Foo {
+ final public const X = "foo";
+}
+
+class Bar extends Foo {
+ public const X = "bar";
+}
+
+// Fatal error: Bar::X cannot override final constant Foo::X</code></pre>
+ </section>
+ <section id="php81_new_init" >
+ <p class="p" style="font-size:1.1em;text-align:left;">New in initializers</p>
+ <div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/new_in_initializers" target="">https://wiki.php.net/rfc/new_in_initializers</a></div>
+ <pre><code data-trim style="font-size:1em;" >class Test {
+ public function __construct(private Logger $logger = new NullLogger) {}
+}
+
+// instead of
+
+class Test {
+ private Logger $logger;
+
+ public function __construct(?Logger $logger = null) {
+ $this->logger = $logger ?? new NullLogger;
+ }
+}</code></pre>
+ </section>
+ <section id="php81_first_class_callable" >
+ <p class="p" style="font-size:1.1em;text-align:left;">First-class callable syntax</p>
+ <div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/first_class_callable_syntax" target="">https://wiki.php.net/rfc/first_class_callable_syntax</a></div>
+ <pre><code data-trim style="font-size:1em;" >$fn = strlen(...);
+$fn = $this->method(...)
+$fn = Foo::method(...);
+
+// instead of
+
+$fn = Closure::fromCallable('strlen');
+$fn = Closure::fromCallable([$this, 'method']);
+$fn = Closure::fromCallable([Foo::class, 'method']);</code></pre>
+ </section>
+ <section id="php81_pure_intersection" >
+ <p class="p" style="font-size:1.1em;text-align:left;">Pure intersection types</p>
+ <div align="left" style="font-size: ; color: ; text-align: left; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="https://wiki.php.net/rfc/pure-intersection-types" target="">https://wiki.php.net/rfc/pure-intersection-types</a></div>
+ <pre><code data-trim style="font-size:1em;" >class A {
+ private Traversable&Countable $countableIterator;
+
+ public function setIterator(Traversable&Countable $countableIterator): void {
+ $this->countableIterator = $countableIterator;
+ }
+
+ public function getIterator(): Traversable&Countable {
+ return $this->countableIterator;
+ }
+}</code></pre>
+ </section> </section>
<section data-background-color="#000000">
<section id="j">
<img src="/presentations/slides/intro/carl1.jpg" align="center" width="533" height="800">
diff --git a/etsymex21.xml b/etsymex21.xml
index 6b69e560..37af11bf 100644
--- a/etsymex21.xml
+++ b/etsymex21.xml
@@ -34,6 +34,7 @@
<slide>slides/intro/wp2021.xml</slide>
<slide>slides/intro/storage.xml</slide>
<slide>slides/intro/php80_2021.xml</slide>
+<slide>slides/intro/php81_2021.xml</slide>
<slide>slides/intro/journey_etsy.xml</slide>
<slide>slides/intro/matter_etsy.xml</slide>
<slide>slides/intro/sahana.xml</slide>
diff --git a/slides/intro/php81_2021.xml b/slides/intro/php81_2021.xml
new file mode 100644
index 00000000..ce5eda24
--- /dev/null
+++ b/slides/intro/php81_2021.xml
@@ -0,0 +1,156 @@
+<slide title="" section="php81">
+
+<blurb fontsize="20em" align="center">PHP 8.1</blurb>
+
+<break lines="1" section="php81_readonly_props"/>
+<blurb fontsize="1.1em" align="left">Readonly properties</blurb>
+<link align="left" href="https://wiki.php.net/rfc/readonly_properties_v2"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class Test {
+ public readonly string $prop;
+
+ public function __construct(string $prop) {
+ $this->prop = $prop; // Initialized once in same scope
+ }
+}
+
+$test = new Test("foobar");
+var_dump($test->prop);
+$test->prop = "foobar"; // Error
+]]></example>
+
+<break lines="1" section="php81_enums"/>
+<blurb fontsize="1.1em" align="left">Enums</blurb>
+<link align="left" href="https://wiki.php.net/rfc/enumerations"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+enum Suit {
+ case Hearts;
+ case Diamonds;
+ case Clubs;
+ case Spades;
+}
+
+function pick_a_card(Suit $suit) { ... }
+pick_a_card(Suit::Clubs); // ok
+pick_a_card('Spades'); // error
+]]></example>
+
+<break lines="1" section="php81_fibers"/>
+<blurb fontsize="1.1em" align="left">Fibers</blurb>
+<link align="left" href="https://wiki.php.net/rfc/fibers"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+use React\EventLoop\LoopInterface;
+use React\Promise\PromiseInterface;
+
+function await(PromiseInterface $promise, LoopInterface $loop): mixed {
+ $fiber = Fiber::this();
+ $promise->done(
+ fn(mixed $value) => $loop->futureTick(fn() => $fiber->resume($value)),
+ fn(Throwable $reason) => $loop->futureTick(fn() => $fiber->throw($reason))
+ );
+
+ return Fiber::suspend();
+}
+]]></example>
+
+<break lines="1" section="php81_fibers"/>
+<blurb fontsize="1.1em" align="left">Static Variable Inheritance</blurb>
+<link align="left" href="https://wiki.php.net/rfc/static_variable_inheritance"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class A {
+ public static function counter() {
+ static $i = 0;
+ return ++$i;
+ }
+}
+class B extends A {}
+
+echo A::counter();
+echo A::counter();
+echo B::counter();
+echo B::counter();
+// PHP 8.0 outputs 1212
+// PHP 8.1 outputs 1234
+]]></example>
+
+<break lines="1" section="php81_never"/>
+<blurb fontsize="1.1em" align="left">Never Return Type</blurb>
+<link align="left" href="https://wiki.php.net/rfc/noreturn_type"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+function redirect(string $uri): never {
+ header('Location: ' . $uri);
+ exit();
+}
+
+redirect('/index.html');
+echo "this will never be executed!";
+]]></example>
+
+<break lines="1" section="php81_final"/>
+<blurb fontsize="1.1em" align="left">Final class constants</blurb>
+<link align="left" href="https://wiki.php.net/rfc/final_class_const"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class Foo {
+ final public const X = "foo";
+}
+
+class Bar extends Foo {
+ public const X = "bar";
+}
+
+// Fatal error: Bar::X cannot override final constant Foo::X
+]]></example>
+
+<break lines="1" section="php81_new_init"/>
+<blurb fontsize="1.1em" align="left">New in initializers</blurb>
+<link align="left" href="https://wiki.php.net/rfc/new_in_initializers"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class Test {
+ public function __construct(private Logger $logger = new NullLogger) {}
+}
+
+// instead of
+
+class Test {
+ private Logger $logger;
+
+ public function __construct(?Logger $logger = null) {
+ $this->logger = $logger ?? new NullLogger;
+ }
+}
+]]></example>
+
+<break lines="1" section="php81_first_class_callable"/>
+<blurb fontsize="1.1em" align="left">First-class callable syntax</blurb>
+<link align="left" href="https://wiki.php.net/rfc/first_class_callable_syntax"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+$fn = strlen(...);
+$fn = $this->method(...)
+$fn = Foo::method(...);
+
+// instead of
+
+$fn = Closure::fromCallable('strlen');
+$fn = Closure::fromCallable([$this, 'method']);
+$fn = Closure::fromCallable([Foo::class, 'method']);
+]]></example>
+
+<break lines="1" section="php81_pure_intersection"/>
+<blurb fontsize="1.1em" align="left">Pure intersection types</blurb>
+<link align="left" href="https://wiki.php.net/rfc/pure-intersection-types"/>
+<example fontsize="1em" result='0' title="" type=""><![CDATA[<?php
+class A {
+ private Traversable&Countable $countableIterator;
+
+ public function setIterator(Traversable&Countable $countableIterator): void {
+ $this->countableIterator = $countableIterator;
+ }
+
+ public function getIterator(): Traversable&Countable {
+ return $this->countableIterator;
+ }
+}
+]]></example>
+
+
+</slide>