1<!doctype html> 2<html lang="en" dir="ltr"> 3<head> 4 <meta charset="utf-8"> 5 6 7 8 9 <title>Installation | AMPHP</title> 10 11 <meta name="description" content="Learn how to install our libraries with Composer and get started with important concepts for concurrent PHP."> 12 <meta name="keywords" content="amp, amphp, non-blocking, concurrency, io, php, future, coroutines, revolt"> 13 14 <link rel="preconnect" href="https://fonts.googleapis.com"> 15 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 16 <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700;800&family=Source+Code+Pro&display=swap" rel="stylesheet"> 17 18 <link rel="stylesheet" href="/asset/css/screen.css?v=d13ce5f981516c15bf68181bc838d6f8df882ea9"/> 19 20 <!-- non-critical CSS is lazy-loaded --> 21 <link rel="preload" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3" as="style" type="text/css"> 22 <noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3" type="text/css"></noscript> 23 <link rel="preload" href="/asset/css/font-awesome.min.css?v=d13ce5f981516c15bf68181bc838d6f8df882ea9" as="style" type="text/css"> 24 <noscript><link rel="stylesheet" href="/asset/css/font-awesome.min.css?v=d13ce5f981516c15bf68181bc838d6f8df882ea9" type="text/css"></noscript> 25 <link rel="preload" href="/asset/css/code.css?v=d13ce5f981516c15bf68181bc838d6f8df882ea9" as="style" type="text/css"> 26 <noscript><link rel="stylesheet" href="/asset/css/code.css?v=d13ce5f981516c15bf68181bc838d6f8df882ea9" type="text/css"></noscript> 27 28 <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> 29 <meta name="google-site-verification" content="lX-Oenz4-gpqzuAF71A-3MQBlDfgr9pIQIfrVniz1As"> 30 31 <meta name="twitter:card" content="summary"> 32 <meta name="twitter:site" content="@asyncphp"> 33 <meta name="twitter:creator" content="@asyncphp"> 34 <meta property="og:type" content="website"> 35 <meta property="og:url" content="/installation"> 36 <meta property="og:title" content="Installation"> 37 <meta property="og:image" content="https://amphp.org/asset/img/og-image.png"> 38 <meta property="og:description" content="Learn how to install our libraries with Composer and get started with important concepts for concurrent PHP."> 39 <meta property="og:locale" content="en_US"> 40 41 <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico"> 42 43 <meta name="apple-mobile-web-app-title" content="AMPHP"> 44 <meta name="application-name" content="AMPHP"> 45 <meta name="theme-color" content="#1376dd"> 46 47
47<script> 48 function loadScript(src, onload) { 49 var script = document.createElement("script"); 50 script.type = "application/javascript"; 51 script.async = true; 52 script.onload = function () { 53 script.onload = null; 54 if (onload) { 55 onload(); 56 } 57 }; 58 59 (document.getElementsByTagName("head")[0]).appendChild(script); 60 script.src = src; 61 } 62 63 function loadCss(src) { 64 var resource = document.createElement('link'); 65 resource.setAttribute('rel', 'stylesheet'); 66 resource.setAttribute('href', src); 67 resource.setAttribute('type', 'text/css'); 68 69 (document.getElementsByTagName("head")[0]).appendChild(resource); 70 } 71 </script>
71 72 73
73<script> 74 loadCss('https://cdn.jsdelivr.net/npm/@docsearch/css@3'); 75 loadCss('/asset/css/font-awesome.min.css?v=d13ce5f981516c15bf68181bc838d6f8df882ea9'); 76 loadCss('/asset/css/code.css?v=d13ce5f981516c15bf68181bc838d6f8df882ea9'); 77 78 loadScript('/asset/js/anchor.min.js?v=d13ce5f981516c15bf68181bc838d6f8df882ea9', function () { 79 var anchors = new AnchorJS(); 80 anchors.options.icon = "#"; 81 anchors.options.placement = "left"; 82 anchors.add("h2,h3,h4,h5,h6"); 83 }); 84 85 loadScript('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.7/highlight.min.js', function () { 86 hljs.configure({tabReplace: ' ', languages: ['php', 'js']}); 87 hljs.initHighlightingOnLoad(); 88 }); 89 90 loadScript('https://cdn.jsdelivr.net/npm/@docsearch/js@3', function () { 91 docsearch({ 92 appId: 'A5ZG0Y68AG', 93 apiKey: '6b0e299ad51fa720d825ab4bca1bd7c7', 94 indexName: 'amphp_v3', 95 container: '#docsearch', 96 debug: false 97 }); 98 }); 99 </script>
99 100</head> 101<body> 102 103 104 105<input type="checkbox" id="menu" name="menu"> 106<header id="top"> 107 <div class="mobile-only" id="menu-switch"> 108 <label for="menu"><i class="fa fa-lg fa-bars"></i></label> 109 </div> 110 111 <div id="logo-container"> 112 <a class="logo" href="/"> 113 <span class="logo-img-container"> 114 <img srcset="/asset/img/logo_text_60.png 1x, /asset/img/logo_text_120.png 2x" class="logo-img" width="200" height="60" alt="Amp Logo"> 115 </span> 116 </a> 117 </div> 118 119 <div class="search"> 120 <div id="docsearch"></div> 121 </div> 122</header> 123<aside class="navigation"> 124 <div class="navigation-scroll"> 125 <div id="top-menu"> 126 <ul> 127 <li> 128 <span class="menu-section open"> 129 Getting Started 130 </span> 131 132 <ul class="open"> 133 <li> 134 <a class="menu-item" href="/installation"> 135 Installation 136 </a> 137 </li> 138 139 <li> 140 <a class="menu-item" href="/architecture"> 141 Architecture 142 </a> 143 </li> 144 145 <li> 146 <a class="menu-item" href="/upgrade"> 147 Upgrade Guide 148 </a> 149 </li> 150 </ul> 151 </li> 152 153 <li> 154 <span class="menu-section open"> 155 Packages 156 </span> 157 158 <ul class="open"> 159 <li> 160 <a class="menu-item d-flex justify-content-between" href="/amp"> 161 <code>amphp/amp</code> 162 <code class="menu-item-version">3.x</code> 163 </a> 164 </li> 165 166 <li> 167 <a class="menu-item d-flex justify-content-between" href="/byte-stream"> 168 <code>amphp/byte-stream</code> 169 <code class="menu-item-version">2.x</code> 170 </a> 171 </li> 172 173 <li> 174 <span class="menu-item d-flex justify-content-between" title="Undocumented" href="/beanstalk"> 175 <code>amphp/beanstalk</code> 176 </span> 177 </li> 178 179 <li> 180 <a class="menu-item d-flex justify-content-between" href="/cache"> 181 <code>amphp/cache</code> 182 <code class="menu-item-version">2.x</code> 183 </a> 184 </li> 185 186 <li> 187 <a class="menu-item d-flex justify-content-between" href="/cluster"> 188 <code>amphp/cluster</code> 189 <code class="menu-item-version">2.x</code> 190 </a> 191 </li> 192 193 <li> 194 <a class="menu-item d-flex justify-content-between" href="/dns"> 195 <code>amphp/dns</code> 196 <code class="menu-item-version">2.x</code> 197 </a> 198 </li> 199 200 <li> 201 <a class="menu-item d-flex justify-content-between" href="/file"> 202 <code>amphp/file</code> 203 <code class="menu-item-version">3.x</code> 204 </a> 205 </li> 206 207 <li> 208 <a class="menu-item d-flex justify-content-between" href="/http"> 209 <code>amphp/http</code> 210 <code class="menu-item-version">2.x</code> 211 </a> 212 </li> 213 214 <li> 215 <a class="menu-item d-flex justify-content-between" href="/http-client"> 216 <code>
216amphp/http-client</code> 217 <code class="menu-item-version">5.x</code> 218 </a> 219 </li> 220 221 <li> 222 <a class="menu-item d-flex justify-content-between" href="/http-server"> 223 <code>amphp/http-server</code> 224 <code class="menu-item-version">3.x</code> 225 </a> 226 </li> 227 228 <li> 229 <a class="menu-item d-flex justify-content-between" href="/http-server-form-parser"> 230 <code>amphp/http-server-form-parser</code> 231 <code class="menu-item-version">2.x</code> 232 </a> 233 </li> 234 235 <li> 236 <a class="menu-item d-flex justify-content-between" href="/http-server-router"> 237 <code>amphp/http-server-router</code> 238 <code class="menu-item-version">2.x</code> 239 </a> 240 </li> 241 242 <li> 243 <a class="menu-item d-flex justify-content-between" href="/http-server-session"> 244 <code>amphp/http-server-session</code> 245 <code class="menu-item-version">2.x</code> 246 </a> 247 </li> 248 249 <li> 250 <a class="menu-item d-flex justify-content-between" href="/http-server-static-content"> 251 <code>amphp/http-server-static-content</code> 252 <code class="menu-item-version">2.x</code> 253 </a> 254 </li> 255 256 <li> 257 <a class="menu-item d-flex justify-content-between" href="/log"> 258 <code>amphp/log</code> 259 <code class="menu-item-version">2.x</code> 260 </a> 261 </li> 262 263 <li> 264 <a class="menu-item d-flex justify-content-between" href="/mysql"> 265 <code>amphp/mysql</code> 266 <code class="menu-item-version">3.x</code> 267 </a> 268 </li> 269 270 <li> 271 <a class="menu-item d-flex justify-content-between" href="/parallel"> 272 <code>amphp/parallel</code> 273 <code class="menu-item-version">2.x</code> 274 </a> 275 </li> 276 277 <li> 278 <a class="menu-item d-flex justify-content-between" href="/parser"> 279 <code>amphp/parser</code> 280 <code class="menu-item-version">1.x</code> 281 </a> 282 </li> 283 284 <li> 285 <a class="menu-item d-flex justify-content-between" href="/phpunit-util"> 286 <code>amphp/phpunit-util</code> 287 <code class="menu-item-version">3.x</code> 288 </a> 289 </li> 290 291 <li> 292 <a class="menu-item d-flex justify-content-between" href="/pipeline"> 293 <code>amphp/pipeline</code> 294 <code class="menu-item-version">1.x</code> 295 </a> 296 </li> 297 298 <li> 299 <a class="menu-item d-flex justify-content-between" href="/postgres"> 300 <code>amphp/postgres</code> 301 <code class="menu-item-version">2.x</code> 302 </a> 303 </li> 304 305 <li> 306 <a class="menu-item d-flex justify-content-between" href="/process"> 307 <code>amphp/process</code> 308 <code class="menu-item-version">2.x</code> 309 </a> 310 </li> 311 312 <li> 313 <a class="menu-item d-flex justify-content-between" href="/react-adapter"> 314 <code>amphp/react-adapter</code> 315 <code class="menu-item-version">2.x</code> 316 </a> 317 </li> 318 319 <li> 320 <a class="menu-item d-flex justify-content-between" href="/redis"> 321 <code>amphp/redis</code> 322 <code class="menu-item-version">2.x</code> 323 </a> 324 </li> 325 326 <li>
327 <span class="menu-item d-flex justify-content-between" title="Undocumented" href="/rpc"> 328 <code>amphp/rpc</code> 329 </span> 330 </li> 331 332 <li> 333 <a class="menu-item d-flex justify-content-between" href="/serialization"> 334 <code>amphp/serialization</code> 335 <code class="menu-item-version">1.x</code> 336 </a> 337 </li> 338 339 <li> 340 <a class="menu-item d-flex justify-content-between" href="/socket"> 341 <code>amphp/socket</code> 342 <code class="menu-item-version">2.x</code> 343 </a> 344 </li> 345 346 <li> 347 <a class="menu-item d-flex justify-content-between" href="/sync"> 348 <code>amphp/sync</code> 349 <code class="menu-item-version">2.x</code> 350 </a> 351 </li> 352 353 <li> 354 <a class="menu-item d-flex justify-content-between" href="/websocket-client"> 355 <code>amphp/websocket-client</code> 356 <code class="menu-item-version">2.x</code> 357 </a> 358 </li> 359 360 <li> 361 <a class="menu-item d-flex justify-content-between" href="/websocket-server"> 362 <code>amphp/websocket-server</code> 363 <code class="menu-item-version">4.x</code> 364 </a> 365 </li> 366 367 <li> 368 <a class="menu-item d-flex justify-content-between" href="/windows-registry"> 369 <code>amphp/windows-registry</code> 370 <code class="menu-item-version">1.x</code> 371 </a> 372 </li> 373 </ul> 374 </li> 375 376 <li> 377 <span class="menu-section"> 378 Testing & debugging 379 </span> 380 381 <ul> 382 <li> 383 <a class="menu-item" href="/testing"> 384 Writing tests 385 </a> 386 </li> 387 388 <li> 389 <a class="menu-item" href="/debugging"> 390 Debugging tools 391 </a> 392 </li> 393 </ul> 394 </li> 395 396 <li> 397 <span class="menu-section"> 398 Deployment 399 <!-- Performance & optimization --> 400 </span> 401 402 <ul> 403 <li> 404 <a class="menu-item" href="/extensions"> 405 Scaling with extensions 406 </a> 407 </li> 408 409 <li> 410 <a class="menu-item" href="/production"> 411 Production performance 412 </a> 413 </li> 414 </ul> 415 </li> 416 417 <li> 418 <span class="menu-section"> 419 Community 420 </span> 421 422 <ul> 423 <li> 424 <a class="menu-item" href="/sponsors"> 425 Sponsoring 426 </a> 427 </li> 428 429 <li> 430 <a class="menu-item" href="/support"> 431 Support 432 </a> 433 </li> 434 435 <li> 436 <a class="menu-item" href="/faq"> 437 FAQ 438 </a> 439 </li> 440 </ul> 441 </li> 442 </ul> 443 </div> 444 </div> 445 446
446<script> 447 document.querySelectorAll('.menu-section').forEach(element => { 448 element.addEventListener('click', () => { 449 element.classList.toggle('open'); 450 element.nextElementSibling.classList.toggle('open'); 451 }); 452 }); 453 454 document.querySelectorAll('.menu-item').forEach(element => { 455 if (element.href === window.location.href) { 456 element.classList.add('active'); 457 458 element.parentElement.parentElement.classList.add('open'); 459 element.parentElement.parentElement.previousElementSibling.classList.add('open'); 460 } 461 }); 462 </script>
462 463</aside> 464 465<div class="site-wrapper"> 466 467 468 469<div class="site-width"> 470 <div class="content content-with-sidebar"> 471 <div class="content-main"> 472 <div class="article-header"> 473 <div class="article-intro"> 474 <h1>Installation</h1> 475 <p>Learn how to install our libraries with Composer and get started with important concepts for concurrent PHP.</p> 476 477 <div class="content-actions"> 478 479 <a href="https://github.com/amphp/amphp.org/blob/main/installation.md"><i class="fa fa-pencil"></i>Suggest edit</a> 480 481 </div> 482 </div> 483 484 485 <div class="article-header-image-container"> 486 <img src="/asset/img/undraw/undraw_factory.svg" class="article-header-image"> 487 </div> 488 489 </div> 490 491 <div class="clear-both"></div> 492 493 <div class="article-content"> 494 <p>It may surprise people to learn that the PHP standard library already has everything we need to write event-driven and 495non-blocking applications. PHP 8.1 ships with fibers built-in.</p> 496 497<p>Our packages can be installed as <a href="https://getcomposer.org/">Composer</a> dependencies on PHP 8 and later, e.g.</p> 498 499<pre class="shell"><code class="language-plain">composer require amphp/amp 500</code></pre> 501 502<h2 id="dependencies">Dependencies</h2> 503 504<p>Transitive dependencies of our packages are not part of the public API. 505If you make use of transitive dependencies, declare them also in the <code class="language-plaintext highlighter-rouge">composer.json</code> file of your own package.</p> 506 507<blockquote class="note"> 508 <p><a href="https://github.com/maglnet/ComposerRequireChecker"><code class="language-plaintext highlighter-rouge">composer-require-checker</code></a> helps you finding packages you implicitly rely on.</p> 509</blockquote> 510 511<p>In addition to fibers, our packages heavily rely on the <a href="https://revolt.run">Revolt</a> event-loop for scheduling concurrent operations. 512If you want to schedule low-level events instead of using higher-level abstractions, such as timers or I/O callbacks, you should declare a 513dependency on the Revolt event-loop for your package.</p> 514 515<pre class="shell"><code class="language-plain">composer require revolt/event-loop 516</code></pre> 517 518<p class="small-hint">Applications with many concurrent file descriptors require one of the <a href="https://revolt.run/extensions">extensions</a>.</p> 519 520<h2 id="hello-world">Hello World</h2> 521 522<p>Letâs start into the world of concurrent PHP with an example that illustrates important aspects. 523We will print a greeting message to our console, but instead of printing the whole message at once, weâll use two coroutines to print the message in chunks with delays.</p> 524 525<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> <span class="c1">// hello-world.php</span> 526 527<span class="k">require</span> <span class="k">__DIR__</span> <span class="mf">.</span> <span class="s1">'/vendor/autoload.php'</span><span class="p">;</span> 528 529<span class="kn">use</span> <span class="nc">Amp\Future</span><span class="p">;</span> 530<span class="kn">use</span> <span class="k">function</span> <span class="n">Amp\async</span><span class="p">;</span> 531<span class="kn">use</span> <span class="k">function</span> <span class="n">Amp\delay</span><span class="p">;</span> 532 533<span class="nv">$future1</span> <span class="o">=</span> <span class="nf">async</span><span class="p">(</span><span class="k">function</span> <span class="p">()</span> <span class="p">{</span> 534 <span class="k">echo</span> <span class="s1">'Hello '</span><span class="p">;</span> 535 536 <span class="c1">// delay() is a non-blocking version of PHP's sleep() function,</span> 537 <span class="c1">// which only pauses the current fiber instead of blocking the whole process.</span> 538 <span class="nf">delay</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span> 539 540 <span class="k">echo</span> <span class="s1">'the future! '</span><span class="p">;</span> 541<span class="p">});
541</span> 542 543<span class="nv">$future2</span> <span class="o">=</span> <span class="nf">async</span><span class="p">(</span><span class="k">function</span> <span class="p">()</span> <span class="p">{</span> 544 <span class="k">echo</span> <span class="s1">'World '</span><span class="p">;</span> 545 546 <span class="c1">// Let's pause for only 1 instead of 2 seconds here,</span> 547 <span class="c1">// so our text is printed in the correct order.</span> 548 <span class="nf">delay</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> 549 550 <span class="k">echo</span> <span class="s1">'from '</span><span class="p">;</span> 551<span class="p">});</span> 552 553<span class="c1">// Our functions have been queued, but won't be executed until the event-loop gains control.</span> 554<span class="k">echo</span> <span class="s2">"Let's start: "</span><span class="p">;</span> 555 556<span class="c1">// Awaiting a future outside a fiber switches to the event loop until the future is complete.</span> 557<span class="c1">// Once the event loop gains control, it executes our already queued functions we've passed to async()</span> 558<span class="nv">$future1</span><span class="o">-></span><span class="nf">await</span><span class="p">();</span> 559<span class="nv">$future2</span><span class="o">-></span><span class="nf">await</span><span class="p">();</span> 560 561<span class="k">echo</span> <span class="kc">PHP_EOL</span><span class="p">;</span> 562</code></pre></div></div> 563 564<pre><code class="language-plain">Let's start: Hello World from the future! 565</code></pre> 566 567<p>Weâve seen that we can pause a coroutine for some time, and while weâre waiting, another coroutine can run and make use of the CPU. 568We have used <code class="language-plaintext highlighter-rouge">Amp\delay</code> instead of PHPâs <code class="language-plaintext highlighter-rouge">sleep</code> function to avoid blocking the whole process.</p> 569 570<p>But what does blocking the whole process look like? 571Try swapping the <code class="language-plaintext highlighter-rouge">delay</code> calls with <code class="language-plaintext highlighter-rouge">sleep</code> calls and run the example again, youâll observe different behavior! 572This happens, because blocking functions block the whole process instead of letting other coroutines run while waiting. 573Blocking functions include <code class="language-plaintext highlighter-rouge">sleep</code>, <code class="language-plaintext highlighter-rouge">usleep</code>, <code class="language-plaintext highlighter-rouge">fwrite</code>, <code class="language-plaintext highlighter-rouge">fread</code> and most other built-in functions doing I/O.</p> 574 575<blockquote class="warning"> 576 <p>Itâs important to avoid using blocking functions in concurrent code, such as <code class="language-plaintext highlighter-rouge">sleep</code>, <code class="language-plaintext highlighter-rouge">usleep</code>, <code class="language-plaintext highlighter-rouge">fwrite</code>, <code class="language-plaintext highlighter-rouge">fread</code> and other built-in functions doing I/O. 577We offer a great variety of non-blocking I/O implementations you can use instead.</p> 578</blockquote> 579 580<p>Letâs dig a bit deeper into the <a href="/architecture">architecture of concurrent applications</a>.</p> 581 582 </div> 583 </div> 584 </div> 585</div> 586 587 <div id="footer" style="background: #fff"> 588 <div class="site-width"> 589 <div class="content footer-columns py-0"> 590 <div class="text-center"> 591 <ul class="footer-networking-list"> 592 <li class="footer-list-item"><a href="https://github.com/amphp/amp"><i 593 class="fa fa-fw fa-github"></i>GitHub</a></li> 594 <li class="footer-list-item"><a href="https://stackoverflow.com/questions/tagged/amphp"><i 595 class="fa fa-fw fa-stack-overflow"></i>Stack Overflow</a></li> 596 <li class="footer-list-item"><a href="https://t.me/amphpchat"><i class="fa fa-fw fa-telegram"></i>Telegram</a> 597 </li> 598 <li class="footer-list-item"><a href="https://twitter.com/asyncphp"><i class="fa fa-fw fa-twitter"></i>Twitter</a></li> 599 </ul> 600 </div> 601 </div> 602 </div> 603 </div> 604</div> 605 606</body> 607</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.