Files
archived-presentations/phpdaymx13.html
2015-01-22 18:31:22 -08:00

600 lines
22 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>PHP</title>
<meta name="description" content="PHP">
<meta name="author" content="Rasmus Lerdorf">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<link rel="stylesheet" href="/reveal.js/css/reveal.css">
<link rel="stylesheet" href="/reveal.js/css/theme/white.css" id="theme">
<!-- For syntax highlighting -->
<link rel="stylesheet" href="/reveal.js/lib/css/zenburn.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? '/reveal.js/css/print/pdf.css' : '/reveal.js/css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
<!--[if lt IE 9]>
<script src="/reveal.js/lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section>
<h1>PHP</h1>
<h3></h3>
<h3>Mexico City</h3>
<h3>Nov. 16, 2013</h3>
<a href="http://talks.php.net/phpdaymx13">http://talks.php.net/phpdaymx13</a><br><br>
<p>Rasmus Lerdorf<br>
<small><a href="http://twitter.com/@rasmus">@rasmus</a></small>
</p>
</section>
<section>
<h2 margin-bottom="2em">1993</h2><br>
<pre><code class="C">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;ctype.h&gt;
#include &lt;string.h&gt;
#define ishex(x) (((x) &gt;= '0' &amp;&amp; (x) &lt;= '9') || ((x) &gt;= 'a' &amp;&amp; \
(x) &lt;= 'f') || ((x) &gt;= 'A' &amp;&amp; (x) &lt;= 'F'))
int htoi(char *s) {
int value;
char c;
c = s[0];
if(isupper(c)) c = tolower(c);
value=(c &gt;= '0' &amp;&amp; c &lt;= '9' ? c - '0' : c - 'a' + 10) * 16;
c = s[1];
if(isupper(c)) c = tolower(c);
value += c &gt;= '0' &amp;&amp; c &lt;= '9' ? c - '0' : c - 'a' + 10;
return(value);
}
void main(int argc, char *argv[]) {
char *params, *data, *dest, *s, *tmp;
char *name, *age;
puts(&quot;Content-type: text/html\r\n&quot;);
puts(&quot;&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;Form Example&lt;/TITLE&gt;&lt;/HEAD&gt;&quot;);
puts(&quot;&lt;BODY&gt;&lt;H1&gt;My Example Form&lt;/H1&gt;&quot;);
puts(&quot;&lt;FORM action=\&quot;form.cgi\&quot; method=\&quot;GET\&quot;&gt;&quot;);
puts(&quot;Name: &lt;INPUT type=\&quot;text\&quot; name=\&quot;name\&quot;&gt;&quot;);
puts(&quot;Age: &lt;INPUT type=\&quot;text\&quot; name=\&quot;age\&quot;&gt;&quot;);
puts(&quot;&lt;BR&gt;&lt;INPUT type=\&quot;submit\&quot;&gt;&quot;);
puts(&quot;&lt;/FORM&gt;&quot;);
data = getenv(&quot;QUERY_STRING&quot;);
if(data &amp;&amp; *data) {
params = data; dest = data;
while(*data) {
if(*data=='+') *dest=' ';
else if(*data == '%' &amp;&amp; ishex(*(data+1))&amp;&amp;ishex(*(data+2))) {
*dest = (char) htoi(data + 1);
data+=2;
} else *dest = *data;
data++;
dest++;
}
*dest = '\0';
s = strtok(params,&quot;&amp;&quot;);
do {
tmp = strchr(s,'=');
if(tmp) {
*tmp = '\0';
if(!strcmp(s,&quot;name&quot;)) name = tmp+1;
else if(!strcmp(s,&quot;age&quot;)) age = tmp+1;
}
} while(s=strtok(NULL,&quot;&amp;&quot;));
printf(&quot;Hi %s, you are %s years old\n&quot;,name,age);
}
puts(&quot;&lt;/BODY&gt;&lt;/HTML&gt;&quot;);
}
</code></pre>
</section>
<section>
<h2 margin-bottom="2em">1993</h2><br>
<pre><code class="Perl">use CGI qw(:standard);
print header;
print start_html('Form Example'),
h1('My Example Form'),
start_form,
&quot;Name: &quot;, textfield('name'),
p,
&quot;Age: &quot;, textfield('age'),
p,
submit,
end_form;
if(param()) {
print &quot;Hi &quot;,em(param('name')),
&quot;You are &quot;,em(param('age')),
&quot; years old&quot;;
}
print end_html;</code></pre>
</section>
<section>
<h2 margin-bottom="2em">1994</h2><br>
<pre><code class="PHP">&lt;html&gt;&lt;head&gt;&lt;title&gt;Form Example&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;&lt;h1&gt;My Example Form&lt;/h1&gt;
&lt;form action=&quot;form.phtml&quot; method=&quot;POST&quot;&gt;
Name: &lt;input type=&quot;text&quot; name=&quot;name&quot;&gt;
Age: &lt;input type=&quot;text&quot; name=&quot;age&quot;&gt;
&lt;br&gt;&lt;input type=&quot;submit&quot;&gt;
&lt;/form&gt;
&lt;?if($name):?&gt;
Hi &lt;?echo $name?&gt;, you are &lt;?echo $age?&gt; years old
&lt;?endif?&gt;
&lt;/body&gt;&lt;/html&gt;</code></pre>
</section>
<section>
<h3 class="p">Focus on the Ecosystem</h3>
<ul>
<li>LAMP wasn't an accident</li>
<li>Robustness, Performance and Security</li>
<li><font color="ff2233"></font> shared hosting ISPs</li>
</ul>
<h3 class="p">Scale</h3>
<ul>
<li>Scaling up is expected</li>
<li>Scaling down is surprisingly hard</li>
<li>Doing both is rocket science</li>
</ul>
</section>
<section>
<h3 class="p">What was he thinking?</h3>
<ul>
<li>Case insensitive function names?</li>
<li>Naming inconsistencies?</li>
<li>What's with the $ signs?</li>
<li>Globals?</li>
<li>register_globals?</li>
<li>magic_quotes?</li>
</ul>
<h3 class="p">OMGWTFBBQ?</h3>
<pre><code>array_search($needle, $haystack);
strstr($haystack, $needle);
in_array($needle, $haystack);
substr_count($haystack, $needle);
array_key_exists($needle, $haystack);
strchr($haystack, $needle);</code></pre>
</section>
<section>
<h3 class="p">Performance</h3>
<ul>
<li>mod_php</li>
<li>shared-nothing perfect sandbox model</li>
</ul>
<h3 class="p">Robustness</h3>
<ul>
<li>SQL LIMIT clause</li>
<li>Promote Prefork shared-nothing model</li>
</ul>
<h3 class="p">Security</h3>
<ul>
<li>max_execution_time</li>
<li>memory_limit</li>
<li>safe mode</li>
</ul>
</section>
<section>
<h2>2013</h2>
</section>
<section>
<section id="php54perf">
<h2 margin-bottom="2em">PHP 5.4</h2><br>
<h3 class="p">Performance Improvements</h3>
<ul>
<li>FastCGI request handling</li>
<li>better memory handling</li>
<li>startup/shutdown</li>
<li>repeated run-time function binding</li>
<li>string constants</li>
<li>access to global constants</li>
<li>access to static properties</li>
<li>empty hashes</li>
<li>@ operator</li>
<li>unserialize()</li>
</ul>
</section>
<section id="php54page2">
<h4 class="p">✔ Built-in Web Server</h4>
<h4 class="p">✔ Traits aka Horizontal Code Reuse</h4>
<p class="p">        (Compiler-assisted Copy-and-Paste)</p>
<h4 class="p">✔ Short Array Syntax</h4>
<pre><code>$a = [1, 2, 3];
$b = ['foo' =&gt; 'orange', 'bar' =&gt; 'apple'];</code></pre>
</section>
<section id="php54page3">
<h4 class="p">✔ Function Array Dereferencing</h4>
<pre><code>function fruits() {
return array('apple', 'banana', 'orange');
}
echo fruits()[0]; // Outputs: apple
?&gt;</code></pre>
<h4 class="p">✔ $this from current scope supported in Closures</h4>
<pre><code>class Foo {
private $prop = &quot;bar&quot;;
public function getPrinter() {
return function() { echo ucfirst($this-&gt;prop); };
}
}
$a = new Foo;
$func = $a-&gt;getPrinter();
$func(); // Outputs: Bar
?&gt;</code></pre>
</section>
<section id="php54page4">
<h4 class="p">&lt;?= is now always available</h4>
<h4 class="p">✔ New Session Object</h4>
<h4 class="p">✔ Callable Typehint</h4>
<h4 class="p">✔ Better support for asian chars in htmlspecialchars/htmlentities</h4>
<h4 class="p">✔ Multibyte support is now configurable at runtime</h4>
<h4 class="p">✔ JSON Improvements</h4>
<ul>
<li>JsonSerializable</li>
</ul>
<pre><code>class Foo implements JsonSerializable {
private $data = 'Bar';
public function jsonSerialize() {
return array('data'=&gt;$this-&gt;data);
}
}
echo json_encode(new Foo); // Outputs: {&quot;data&quot;:&quot;Bar&quot;}</code></pre>
</section>
<section id="php54page5">
<h4 class="p">✔ mysqlnd used by default everywhere</h4>
<h4 class="p">✔ iterator support added to mysqli (mysqli_result implements Traversable)</h4>
<h4 class="p">✔ Binary notation</h4>
<pre><code>$mask = 0b010101;</code></pre>
<h4 class="p">✔ AES Support added to OpenSSL</h4>
<h4 class="p">✔ Tokyo Cabinet and DB5 support added to dba</h4>
<h4 class="p">✔ Added stack frame count arg to debug_backtrace()</h4>
<h4 class="p">✔ $_SERVER['REQUEST_TIME_FLOAT'] added</h4>
<h4 class="p">✔ Apache 2.4 support on Windows</h4>
</section> </section>
<section>
<section id="php54perf1">
<h2 margin-bottom="2em">5.4 Performance</h2><br>
<p class="p">
PHP 5.4 + Opcache vs. PHP 5.3 + APC
</p>
<p>user cpu</p>
<img src="/presentations/slides/intro/php54_cpu.png" width="732" height="415">
</section>
<section id="php54perf2">
<p>system cpu</p>
<img src="/presentations/slides/intro/php54_system.png" width="732" height="416">
</section>
<section id="php54perf3">
<p>memory</p>
<img src="/presentations/slides/intro/php54_mem.png" width="732" height="416">
</section>
<section id="php54perf4">
<p>latency</p>
<img src="/presentations/slides/intro/php54_latency.png" width="732" height="415">
</section> </section>
<section>
<section id="php54trip1">
<h2 margin-bottom="2em">Watch out for...</h2><br>
<p class="p">✔ default charset is UTF-8 instead of ISO-8859-1</p>
<pre><code>echo htmlspecialchars(&quot;abc&quot;.chr(0xE0).&quot;def&quot;); // 5.3 &quot;abc<EFBFBD>def&quot;
echo htmlspecialchars(&quot;abc&quot;.chr(0xE0).&quot;def&quot;, NULL, 'UTF-8'); // 5.3 &quot;&quot;
echo htmlspecialchars(&quot;abc&quot;.chr(0xE0).&quot;def&quot;); // 5.4 &quot;&quot;
echo htmlspecialchars(&quot;abc&quot;.chr(0xE0).&quot;def&quot;, ENT_IGNORE); // 5.4 &quot;abcdef&quot;</code></pre>
<p class="p">✔ array to string conversion notice</p>
<pre><code>echo [1,2,3];
// Notice: Array to string conversion in test.php code on line 1
array_diff([1,2,3], [1,2, [3] ]);
// Notice: Array to string conversion in test.php on line 2</code></pre>
<p class="p">✔ register_globals completely removed</p>
<p class="p">✔ magic quotes completely removed</p>
</section>
<section id="php54trip2">
<p class="p">✔ removed variable break/continue</p>
<pre><code>$var = 'label';
while(1) {
break $var;
continue $var;
}
label:</code></pre>
<p class="p">✔ max_input_vars (default 1000)</p>
<p class="p">✔ "callable", "insteadof" and "trait" are now reserved words</p>
</section>
<section id="php54trip3">
<p class="p">✔ extending an abstract constructor must match the signature</p>
<pre><code>abstract class Base {
abstract public function __construct();
}
class Foo extends Base {
public function __construct($bar) {}
// FATAL Declaration of Foo::__construct() must be compatible
// with Base::__construct()
}</code></pre>
<p class="p">✔ stream_select() preserves keys of array arg</p>
<p class="p">✔ XSLT writes are disabled by default</p>
<p class="p">✔ mcrypt_generic_end() removed in favour of mcrypt_generic_deinit()</p>
<p class="p">✔ mysql_list_dbs() removed</p>
<p class="p">✔ PDO needs at least mysql client lib 4.1 now</p>
<p class="p">✔ Datetime ignores TZ env var and falls back to UTC if none set</p>
<p class="p">✔ Tiger hash output fixed - See bug 61307</p>
</section> </section>
<section>
<section id="performance">
<h2 margin-bottom="2em">PHP 5.5</h2><br>
<h3 class="p">Performance Improvements</h3>
<ul>
<li>Nested calls</li>
<li>Call stack pre-allocated by compiler</li>
<li>Bundled opcode cache</li>
</ul>
</section>
<section id="generators">
<h4 class="p">✔ Generators</h4>
<pre><code>function xrange($start, $end) {
for ($i = $start; $i &lt;= $end; $i ++) {
yield $i;
}
}
foreach (xrange(0, 5) as $i) {
echo $i, &quot;\n&quot;;
}</code></pre>
</section>
<section id="coroutines">
<h4 class="p">✔ Coroutines</h4>
<pre><code>function logger($fileName) {
$fileHandle = fopen($fileName, 'a');
while (true) {
fwrite($fileHandle, yield . &quot;\n&quot;);
}
}
$logger = logger(__DIR__ . '/log');
$logger-&gt;send('Foo');
$logger-&gt;send('Bar');</code></pre>
<p class="p">For an advanced explanation of coroutines, read this article by Nikita Popov</p>
<div align="" style="font-size: ; color: ; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="http://nikic.github.io/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html" target="">Cooperative multitasking using coroutines</a></div><br />
</section>
<section id="finally">
<h4 class="p">✔ finally</h4>
<pre><code>$db = mysqli_connect();
try {
call_some_function($db);
} finally {
mysqli_close($db);
}</code></pre>
</section>
<section id="foreachlist">
<h4 class="p">✔ list() in foreach</h4>
<pre><code>$names = [ ['John','Smith'], ['Fred','Johnson'] ];
foreach($names as list($first,$last)) {
echo $first,$last;
}</code></pre>
</section>
<section id="constarray">
<h4 class="p">✔ Const array/string Dereferencing</h4>
<pre><code>echo array(1, 2, 3)[0]; //output 1
echo &quot;foobar&quot;[3]; //output b
echo [1,3,4][2]; //output 4</code></pre>
</section>
<section id="others">
<h4 class="p">✔ empty() support for functions/expressions</h4>
<h4 class="p">✔ curl upload functionality rewritten</h4>
<h4 class="p">✔ Simplified password hashing API</h4>
<pre><code>// Hash
$hash = password_hash(&quot;super secret&quot;,PASSWORD_BCRYPT);
// To validate $pwd against the stored hash
if (password_verify($pwd, $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}</code></pre>
</section>
<section id="php55_done">
<div align="" style="font-size: ; color: ; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="http://php.net/migration55" target="">php.net/migration55</a></div><br />
</section> </section>
<section>
<section id="php56">
<h2 margin-bottom="2em">PHP 5.6</h2><br>
<div align="" style="font-size: 2em; color: ; margin-left: 0em; margin-right: ; margin-top: ; margin-bottom: ;"><a href="http://php.net/spec" target="">http://php.net/spec</a></div><br />
</section>
<section id="php56variadic">
<h4 class="p">✔ Variadic functions</h4>
<pre><code>class MySQL implements DB {
public function query($query, ...$params) {
$stmt = $this-&gt;pdo-&gt;prepare($query);
$stmt-&gt;execute($params);
return $stmt;
}
}
$q = 'SELECT * FROM users WHERE id = ?';
$user = $db-&gt;query($q, $userID)-&gt;fetch();</code></pre>
</section>
<section id="php56unpack">
<h4 class="p">✔ Argument Unpacking</h4>
<pre><code>// A better call_user_func_args
$args1 = [1, 2, 3];
$args2 = [4, 5, 6];
test(...$args1, ...$args2); // [1, 2, 3, 4, 5, 6]
test(1, 2, 3, ...$args2); // [1, 2, 3, 4, 5, 6]
test(...$args1, 4, 5, 6); // Fatal error: Cannot use positional argument after argument unpacking</code></pre>
</section>
<section id="php56constscalar">
<h4 class="p">✔ Constant scalar expressions</h4>
<pre><code>class Foo {
const FOO = 1 + 1;
const BAR = 1 &lt;&lt; 1;
const GREETING = &quot;HELLO&quot;;
const BAZ = self::GREETING.&quot; WORLD!&quot;
}</code></pre>
</section>
<section id="php56pow">
<h4 class="p">✔ Add right-associative power operator **</h4>
<pre><code>echo 2 ** 3 ** 2; // 512 (not 64)
echo -3 ** 2; // -9 (not 9)
echo 1 - 3 ** 2; // -8
echo ~3 ** 2; // -10 (not 16)</code></pre>
</section>
<section id="php56opoverload">
<h4 class="p">✔ Internal operator overloading for internal features like GMP</h4>
<pre><code>echo 2**512;
echo &quot;\n&quot;;
$n = gmp_init(2);
echo $n**512;</code></pre>
<pre><code>1.3407807929943E+154
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
</code></pre> </section>
<section id="php56use">
<h4 class="p">✔ use function and use const namespace imports</h4>
<pre><code>include 'template.inc';
include 'db.inc';
use function template\header, template\footer, db\query;
header('My Page');
query('select * from stuff');
footer();</code></pre>
</section>
<section id="php56_0">
<h4 class="p">✔ default_charset ini now applies to internal funcs</h4>
<h4 class="p">✔ SSL Peer verification by default</h4>
<h4 class="p">✔ openssl certificate fingerprints</h4>
<h4 class="p">✔ SAN x509 ext matching when verifying host names</h4>
<h4 class="p">✔ automatic DoS prevention of TLS renegotiation attacks</h4>
<h4 class="p">✔ and many more openssl-related options</h4>
</section>
<section id="php56_1">
<h4 class="p">✔ Asynchronous PostgreSQL database connections</h4>
<h4 class="p">✔ Non-blocking PostgreSQL queries</h4>
<h4 class="p">✔ New phpdbg SAPI</h4>
<h4 class="p">✔ Support for > 2GB file uploads</h4>
<h4 class="p">✔ The php://input stream is now re-usable</h4>
<h4 class="p">✔ Added hash_equals() for timing attack safe string comparison</h4>
<h4 class="p">✔ Added gost-crypto (CryptoPro S-box) hash algorithm</h4>
<h4 class="p">✔ FPM workers can now change their apparmor profile</h4>
<h4 class="p">✔ OCI8 Improvements</h4>
</section>
<section id="php56_done">
<div align="" style="font-size: ; color: ; margin-left: ; margin-right: ; margin-top: ; margin-bottom: ;"><a href="http://php.net/migration56" target="">php.net/migration56</a></div><br />
</section> </section>
<section>
<h2 margin-bottom="2em">Deploying Web Apps</h2><br>
<h3 class="p">Are your deploys atomic?</h3>
<h3 class="p">Are you sure?</h3>
<h4 class="p">What happens to a request that is currently executing when you deploy?</h4>
</section>
<section>
<h2 margin-bottom="2em">Deploying Web Apps</h2><br>
<img src="/presentations/slides/intro/dep1.png" width="642" height="300">
</section>
<section>
<h2 margin-bottom="2em">Deploying Web Apps</h2><br>
<h4 class="p">✔ Don't copy files into current document root</h4>
<h4 class="p">✔ Let existing requests finish on old code</h4>
<h4 class="p">✔ New requests start on new code</h4>
<h4 class="p">✔ Avoid clearing your opcode cache</h4>
<h4 class="p">✔ Minimal impact on production traffic</h4>
</section>
<section>
<h2 margin-bottom="2em">Deploying Web Apps</h2><br>
<img src="/presentations/slides/intro/dep2.png" width="680" height="428">
</section>
<section>
<h2 margin-bottom="2em">Deploying Web Apps</h2><br>
<img src="/presentations/slides/intro/dep3.png" width="680" height="428">
</section>
<section>
<h2 margin-bottom="2em">Deploying Web Apps</h2><br>
<h4 class="p">2 Document Root directories</h4>
<h4 class="p">Symlink /var/www/site toggles between them</h4>
<h4 class="p">realpath() symlink at the web server level</h4>
<h4 class="p">Set Document Root to symlink realpath</h4>
<h4 class="p">Never hardcode the document root in code</h4>
</section>
<section>
<h2 margin-bottom="2em">Deploying Web Apps</h2><br>
<h3 class="p">Apache</h3>
<h4 class="p">http://github.com/etsy/mod_realdoc</h4>
<h3 class="p">nginx</h3>
<h4 class="p">You can use $realpath_root</h4>
<p class="p">eg. fastcgi_param DOCUMENT_ROOT $realpath_root;</p>
<h3 class="p">PHP</h3>
<h4 class="p">http://github.com/etsy/incpath</h4>
</section>
<section>
<h2 margin-bottom="2em">Conclusion</h2><br>
<ul>
<li>Still running PHP 5.2 or 5.3? Upgrade now!</li>
<li>Test your code on PHP 5.5 and upgrade soon</li>
<li>Help us test PHP 5.6</li>
<li>Contribute!</li>
</ul>
<div align="" style="font-size: 2.5em; color: ; margin-left: 2em; margin-right: ; margin-top: ; margin-bottom: ;">Slides: <a href=":-:url:-:" target="">http://talks.php.net/phpdaymx13</a></div><br />
<div align="" style="font-size: 2.5em; color: ; margin-left: 2em; margin-right: ; margin-top: ; margin-bottom: ;">5.2->5.3: <a href="http://php.net/migration53" target="">http://php.net/migration53</a></div><br />
<div align="" style="font-size: 2.5em; color: ; margin-left: 2em; margin-right: ; margin-top: ; margin-bottom: ;">5.3->5.4: <a href="http://php.net/migration54" target="">http://php.net/migration54</a></div><br />
<div align="" style="font-size: 2.5em; color: ; margin-left: 2em; margin-right: ; margin-top: ; margin-bottom: ;">5.4->5.5: <a href="http://php.net/migration55" target="">http://php.net/migration55</a></div><br />
<div align="" style="font-size: 2.5em; color: ; margin-left: 2em; margin-right: ; margin-top: ; margin-bottom: ;">mysqlnd: <a href="http://php.net/mysqlnd" target="">http://php.net/mysqlnd</a></div><br />
<div align="" style="font-size: 2.5em; color: ; margin-left: 2em; margin-right: ; margin-top: ; margin-bottom: ;">Wiki: <a href="http://wiki.php.net" target="">http://wiki.php.net</a></div><br />
<div align="" style="font-size: 2.5em; color: ; margin-left: 2em; margin-right: ; margin-top: ; margin-bottom: ;">Bugs: <a href="http://bugs.php.net" target="">http://bugs.php.net</a></div><br />
</section>
</div>
</div>
<script src="/reveal.js/lib/js/head.min.js"></script>
<script src="/reveal.js/js/reveal.js"></script>
<script>
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
transition: 'slide', // none/fade/slide/convex/concave/zoom
transitionSpeed: 'fast',
// Optional reveal.js plugins
dependencies: [
{ src: '/reveal.js/lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: '/reveal.js/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: '/reveal.js/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: '/reveal.js/plugin/highlight/highlight.js', async: true, condition: function() { return !!document.querySelector( 'pre code' ); }, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: '/reveal.js/plugin/zoom-js/zoom.js', async: true },
{ src: '/reveal.js/plugin/notes/notes.js', async: true }
]
});
</script>
</body>
</html>