<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Marcel Pociot</title>
    <description>The latest articles on Forem by Marcel Pociot (@marcelpociot).</description>
    <link>https://forem.com/marcelpociot</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F614211%2Fcc417cf9-81c5-43aa-af4c-f14f5b451c5f.jpeg</url>
      <title>Forem: Marcel Pociot</title>
      <link>https://forem.com/marcelpociot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/marcelpociot"/>
    <language>en</language>
    <item>
      <title>Using Laravel Blade components in your layout</title>
      <dc:creator>Marcel Pociot</dc:creator>
      <pubDate>Wed, 14 Apr 2021 09:49:24 +0000</pubDate>
      <link>https://forem.com/beyondcode/using-laravel-blade-components-in-your-layout-541c</link>
      <guid>https://forem.com/beyondcode/using-laravel-blade-components-in-your-layout-541c</guid>
      <description>&lt;h1&gt;
  
  
  Blade Components for your Layout
&lt;/h1&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/blog/using-laravel-view-components"&gt;latest blog post&lt;/a&gt; I showed you how Laravels Blade view components work and how you can make use of them.&lt;br&gt;
In this part of the series, I want to focus on how we can use these components throughout our application - starting with the very basic: your layout.&lt;/p&gt;

&lt;p&gt;In a typical Laravel application, you might have a file called &lt;code&gt;layouts/app.blade.php&lt;/code&gt; that all of your other views extend from.&lt;/p&gt;

&lt;p&gt;Such a view could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        @yield('scripts')
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        @yield('content')
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in your actual pages, you will &lt;code&gt;extend&lt;/code&gt; that view and provide your content within the &lt;code&gt;content&lt;/code&gt; section. Here's an example &lt;code&gt;welcome.blade.php&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@extends('layouts.app')

@section('scripts')
    &lt;span class="c"&gt;&amp;lt;!-- Some JS and styles --&amp;gt;&lt;/span&gt;
@endsection

@section('content')
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;My Page content is here&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
@endsection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far so good, so let's see how we can make use of our newly learned Blade components to refactor this.&lt;/p&gt;

&lt;p&gt;First of all, we are going to create a new component called "Layout":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:component Layout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we can take all of our existing layout view code and place it inside of our new layout component view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- /views/components/layout.blade.php --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        @yield('scripts')
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        @yield('content')
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make this work, the only thing we need to do in our &lt;code&gt;welcome.blade.php&lt;/code&gt; file is, instead of extending our layout - we can just wrap all of the content inside of our new layout component, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;x-layout&amp;gt;&lt;/span&gt;
    @section('scripts')
        &lt;span class="c"&gt;&amp;lt;!-- Some JS and styles --&amp;gt;&lt;/span&gt;
    @endsection

    @section('content')
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;My Page content is here&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    @endsection
&lt;span class="nt"&gt;&amp;lt;/x-layout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is already pretty good, but as we have seen in the previous post, Laravel provides a &lt;code&gt;$slot&lt;/code&gt; variable that automatically holds all of the content that was placed inside of the blade component tags. So lets go and change our layout to make use of the &lt;code&gt;$slot&lt;/code&gt; variable, instead of yielding a content section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- /views/components/layout.blade.php --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        @yield('scripts')
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
          {{ $slot }}
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of using the &lt;code&gt;@section&lt;/code&gt; directive, we can now simply pass the data as is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;x-layout&amp;gt;&lt;/span&gt;
    @section('scripts')
        &lt;span class="c"&gt;&amp;lt;!-- Some JS and styles --&amp;gt;&lt;/span&gt;
    @endsection

  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;My Page content is here&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/x-layout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright - so we got rid of the content section and wrapped everything into our layout component. That's already pretty cool and I think this improves the readability of our view component. Because of the indentation it is immediately clear which layout is being used. This &lt;code&gt;scripts&lt;/code&gt; section is still bothering me though. So let's see how we can get rid of this as well - and there are multiple options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Named Slots
&lt;/h2&gt;

&lt;p&gt;The first option that we have is to make use of a "named slot". We already discussed the &lt;code&gt;$slot&lt;/code&gt; variable, that will automatically be populated with everything within the component HTML, but we can also manually specify a slot name. This can be done using the &lt;code&gt;x-slot&lt;/code&gt; tag - which itself is sort of a pre-defined Blade component that comes out of the box with Laravel.&lt;/p&gt;

&lt;p&gt;By passing a &lt;code&gt;name&lt;/code&gt; property to our &lt;code&gt;x-slot&lt;/code&gt;, we can make the data available within a variable with the same name as our &lt;code&gt;name&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;Let's modify our layout component to make use of a new &lt;code&gt;$scripts&lt;/code&gt; variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- /views/components/layout.blade.php --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        {{ $scripts }}
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
          {{ $slot }}
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To pass this variable to our view, we can now pass it into a &lt;code&gt;scripts&lt;/code&gt; slot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;x-layout&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;x-slot&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"scripts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Some JS and styles --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/x-slot&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;My Page content is here&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/x-layout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refresh the page, and you can see that everything works as expected. With this, we introduced an error though, as our &lt;code&gt;$scripts&lt;/code&gt; variable is now mandatory within our layout - so if a  view would not provide a &lt;code&gt;scripts&lt;/code&gt; slot, you would get an error "Undefined variable: scripts".&lt;/p&gt;

&lt;p&gt;While this works with a named slot, we no longer have the ability to append to the scripts section from within multiple of our views/components - because we don't have a real "section" anymore.&lt;/p&gt;

&lt;p&gt;So what if we want to get rid of the &lt;code&gt;@section&lt;/code&gt; directives and use a component for this instead? First of, lets get our &lt;code&gt;@yield&lt;/code&gt; directive back into our layout component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        @yield('scripts')
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
          {{ $slot }}
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright - now lets see how we can make use of this section, without using a directive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Renderless Blade components
&lt;/h2&gt;

&lt;p&gt;When you create a custom Blade component, the class has a &lt;code&gt;render&lt;/code&gt; method, that by default returns a string containing the name of the view for the given component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\View\Components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\View\Component&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Alert&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'components.alert'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's another way of returning a view though, which is by returning a callable, that is then going to return the actual view. In this case, our component only holds the data/state that was provided for the component, but it doesn't actually return a view - which is great for our section use case.&lt;/p&gt;

&lt;p&gt;So lets create a new view component called &lt;code&gt;Section&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:component Section
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now instead of returning a view, we are actually going to return a function - that will return the &lt;code&gt;@section&lt;/code&gt; directive for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\View\Components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\View\Component&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Section&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$componentData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;&amp;lt;&amp;lt;&amp;lt;BLADE
                @section("{$componentData['attributes']-&amp;gt;get('name')}")
                    {$componentData['slot']}
                @endsection
            BLADE;&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright - so lets break this render method down line by line.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;render&lt;/code&gt; method returns a callable with one parameter - an array holding the component data.&lt;br&gt;
This array has the following data and keys available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;componentName&lt;/code&gt; - The name for the component, in our case "section"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;attributes&lt;/code&gt; - The &lt;code&gt;Illuminate\View\ComponentAttributeBag&lt;/code&gt; instance that holds all of our component attributes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;slot&lt;/code&gt; - A &lt;code&gt;Illuminate\Support\HtmlString&lt;/code&gt; object with the string that was passed to the default slot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside of this callable, we are returning a string - this string is escaped using PHPs &lt;a href="https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc"&gt;Heredoc Syntax&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Inside of this string, we can now return any Blade code that we want - so in our case, we are opening a &lt;code&gt;@section&lt;/code&gt; directive, with the &lt;code&gt;name&lt;/code&gt; attribute that was provided in the &lt;code&gt;&amp;lt;x-section&lt;/code&gt; tag. Inside of that &lt;code&gt;@section&lt;/code&gt; directive, we pass the slot of our component (and cast it to a string, as it's a HtmlString object).&lt;br&gt;
And last but not least, we close the section directive.&lt;/p&gt;

&lt;p&gt;To make use of this renderless component, we can now rewrite our page view like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;x-layout&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;x-section&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"scripts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="c"&gt;&amp;lt;!-- Some JS and styles --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/x-section&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;My Page content is here&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/x-layout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yay - we did it! We got rid of our ugly directive and have successfully refactored it to make use of a custom blade component. &lt;/p&gt;

&lt;p&gt;Is this better than using the directives? You'll have to decide for yourself - but I hope that this inspired you to take a look at renderless Blade components, as well as how you can use components for your traditional layout extensions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Exporting Laravel Eloquent to CSV/XLS</title>
      <dc:creator>Marcel Pociot</dc:creator>
      <pubDate>Wed, 14 Apr 2021 09:47:53 +0000</pubDate>
      <link>https://forem.com/beyondcode/exporting-laravel-eloquent-to-csv-xls-589m</link>
      <guid>https://forem.com/beyondcode/exporting-laravel-eloquent-to-csv-xls-589m</guid>
      <description>&lt;h1&gt;
  
  
  Exporting Laravel Models to CSV or XLS
&lt;/h1&gt;

&lt;p&gt;As I was browsing Twitter, the question came up how you could easily export your Eloquent models to CSV or XLS. &lt;br&gt;
There are many possible ways, so let's inspect a couple of those.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using pure PHP
&lt;/h2&gt;

&lt;p&gt;Yeah, I know - this might definitely not be the simplest solution - but it is always a good idea to know your tools, so we should at least take a brief look at how you can export your models to CSV with no third-party dependency at all.&lt;/p&gt;

&lt;p&gt;PHP has a method called &lt;a href="https://www.php.net/manual/de/function.fputcsv.php"&gt;fputcsv&lt;/a&gt;, which allows you to write an array of data into a file handle. Pretty easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Open a file handle in 'write' mode for&lt;/span&gt;
&lt;span class="c1"&gt;// a file called export.csv&lt;/span&gt;
&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Marcel'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'marcel@beyondco.de'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sebastian'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'sebastian@beyondco.de'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'export.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;fputcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;fclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is pretty straight forward and simple to use. The resulting CSV file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,Marcel,marcel@beyondco.de
2,Sebastian,sebastian@beyondco.de
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to use a &lt;code&gt;;&lt;/code&gt; instead of a comma for the separator, you can pass it as a third argument to the &lt;code&gt;fputcsv&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Now in the example above, we have only used a static data array for our export - not a collection of models. Making this change is pretty easy too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'export.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;fputcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;';'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;fclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we export all of our users, load them into a &lt;code&gt;$data&lt;/code&gt; variable and then loop over these models to write them to the CSV file. Notice that we are using the &lt;code&gt;$row-&amp;gt;toArray()&lt;/code&gt; method, because fputcsv expects us to pass an array - not an object.&lt;/p&gt;

&lt;p&gt;And this works just fine, here's the resulting CSV for this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1;Marcel;marcel@beyondco.de;;2021-04-01T06:37:47.000000Z;2021-04-01T06:37:47.000000Z
2;Sebastian;sebastian@beyondco.de;;2021-04-01T06:37:54.000000Z;2021-04-01T06:37:54.000000Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we get more data than in the first example - that's because our models contain more information, such as the created_at and updated_at timestamps. You can also notice an empty value in the CSV export above - that's from the &lt;code&gt;email_verified_at&lt;/code&gt; column that ships with Laravel by default, which is &lt;code&gt;NULL&lt;/code&gt; in this case.&lt;/p&gt;

&lt;p&gt;Alright - so doing this with pure, raw PHP is not as fancy as the usage of a third-party package might be, but its certainly doable. This comes with some flaws though. &lt;/p&gt;

&lt;p&gt;Because we have to load all of our models into memory (by stuffing them in our &lt;code&gt;$data&lt;/code&gt; variable), this export will use a lot of memory, as your &lt;code&gt;users&lt;/code&gt; table grows. An easy fix is the usage of the &lt;a href="https://laravel.com/docs/8.x/eloquent#chunking-results"&gt;chunk&lt;/a&gt; method. Instead of loading thousands of rows into memory, this method will only receive a subset of Eloquent models and execute a closure with those models, saving a lot of memory.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;fputcsv&lt;/code&gt; method rewritten with chunking looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'export.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;fputcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;';'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;fclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create the file handle, and then for a chunk of every 100 users, we put those users into the handle. This way we won't load thousands of users into memory - great!&lt;/p&gt;

&lt;h2&gt;
  
  
  Third Party Packages
&lt;/h2&gt;

&lt;p&gt;There are a lot of third-party packages out there, that can help you with exporting data to either CSV or Excel. &lt;a href="https://docs.laravel-excel.com/"&gt;Laravel Excel&lt;/a&gt; is the most popular solution for this - by far. &lt;br&gt;
Let's see how we can create our User export with Laravel Excel.&lt;/p&gt;

&lt;p&gt;First of all, you need to install the package using composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require maatwebsite/excel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we can create our first export. Exports are classes that live in your &lt;code&gt;app/Exports&lt;/code&gt; folder and they contain all the logic for a given export.&lt;/p&gt;

&lt;p&gt;The package comes with an artisan command to create such an Export class for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:export UsersExport --model=User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets take a look at the generated UsersExport class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Exports&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Maatwebsite\Excel\Concerns\FromCollection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersExport&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;FromCollection&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So all that we do in this class, is we provide a collection method that returns the data that should be exported.&lt;/p&gt;

&lt;p&gt;To actually call our export from a controller, you can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Exports\UsersExport&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Maatwebsite\Excel\Facades\Excel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Excel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UsersExport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'users.xlsx'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use the &lt;code&gt;Excel&lt;/code&gt; facade provided by the package, call the &lt;code&gt;download&lt;/code&gt; method to instruct the package that we want to invoke a file download, and last but not least give it an instance of our export, as well as the desired file name for the export.&lt;/p&gt;

&lt;h3&gt;
  
  
  But what about memory usage...
&lt;/h3&gt;

&lt;p&gt;...you might wonder. If our User model would consist of thousands of rows, because we return &lt;code&gt;User::all()&lt;/code&gt;, wouldn't we run into memory issues all over again?&lt;br&gt;
Yes - we would. So let's fix this.&lt;/p&gt;

&lt;p&gt;Laravel Excel allows us to also export our models from a query, which is then going to handle the chunking for us. We can modify our &lt;code&gt;UsersExport&lt;/code&gt; class like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Exports&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Maatwebsite\Excel\Concerns\FromCollection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersExport&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;FromCollection&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is now simply returning a base query from our User model, which will then be exported.&lt;/p&gt;

&lt;h2&gt;
  
  
  GUI solutions
&lt;/h2&gt;

&lt;p&gt;While all the above solutions are great if you want to provide a CSV/XLS export from within your application, you sometimes simply need to export a given set of data to CSV or XLS, which you don't actually need inside of your application.&lt;/p&gt;

&lt;p&gt;For example: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're running a SaaS and you want to have an export of the latest invoices that were created - you don't need to do this multiple times, so there's no need to add this to your application&lt;/li&gt;
&lt;li&gt;Your boss tells you: "Hey, give me a CSV file with all users that have relation X real quick!"&lt;/li&gt;
&lt;li&gt;Any other "one-off" exports that you want to make for yourself/others&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this, the usage of a GUI based tool can be great. Let me show you how you can create a CSV export using &lt;a href="https://tinkerwell.app"&gt;Tinkerwell&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tinkerwell allows you to connect to your local or remote Laravel applications where you can then evaluate any PHP code within the context of your opened application - and there's no need to install a third-party package for this to work.&lt;/p&gt;

&lt;p&gt;This means that we can simply evaluate our fputcsv code snippet on any local or remote Laravel application, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3jIB9xB7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://beyondco.de/img-blog/tinkerwell_csv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3jIB9xB7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://beyondco.de/img-blog/tinkerwell_csv.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition to writing this code yourself, you can also make use of Tinkerwell's table mode. This mode gives you a table view of any collection or array that your PHP code evaluates and it then allows you to browse the data, as well as export it to CSV.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xFfyahXG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://beyondco.de/img-blog/tinkerwell_table.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xFfyahXG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://beyondco.de/img-blog/tinkerwell_table.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simply press the "Save CSV" button and you're good to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting fancier
&lt;/h2&gt;

&lt;p&gt;If you prefer an even simpler solution, you can make use of &lt;a href="https://invoker.app"&gt;Invoker&lt;/a&gt;. Invoker is a desktop application that, just like Tinkerwell, can connect to local or remote Laravel applications and provides you with an instant admin-panel of your Eloquent models, mailables, notifications, and much more.&lt;/p&gt;

&lt;p&gt;Inside of Invoker, you can then browse all of your models, filter them by adding additional Eloquent queries, as well as export the results to XLS/CSV with a click of a button. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NgitMYy6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://beyondco.de/img-blog/export_invoker.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NgitMYy6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://beyondco.de/img-blog/export_invoker.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It doesn't get easier than that.&lt;/p&gt;

&lt;p&gt;So we looked at a couple of different ways how we can export our Laravel models to CSV, either by using pure PHP methods, third-party libraries, or GUI tools for one-off exports and easier data-filtering.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Laravel Octane</title>
      <dc:creator>Marcel Pociot</dc:creator>
      <pubDate>Wed, 14 Apr 2021 09:30:19 +0000</pubDate>
      <link>https://forem.com/beyondcode/laravel-octane-3ji5</link>
      <guid>https://forem.com/beyondcode/laravel-octane-3ji5</guid>
      <description>&lt;h1&gt;
  
  
  Laravel Octane - What, How, and Why
&lt;/h1&gt;

&lt;p&gt;Taylor Otwell already showed a glimpse of Laravel's latest open-source package, Octane, during his Laracon Online talk - but today, the new package is &lt;a href="https://github.com/laravel/octane"&gt;available on GitHub&lt;/a&gt; for everyone to beta test.&lt;/p&gt;

&lt;p&gt;In this blog post, I'm going to explore Laravel Octane and tell you what it is, how you can install and use it, and why you might need it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; Laravel Octane is still a beta software and should not yet be used in production!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Laravel Octane?
&lt;/h2&gt;

&lt;p&gt;Laravel Octane is an open-source package that will boost your Laravel application performance. Laravel Octane requires PHP 8, so if you're still on 7.x, you need to upgrade your PHP version.&lt;br&gt;
Under the hood, Octane makes use of &lt;a href="https://www.swoole.co.uk/"&gt;Swoole&lt;/a&gt; and &lt;a href="https://roadrunner.dev/"&gt;RoadRunner&lt;/a&gt; - two application servers, that take care of serving and booting up your Laravel application. Why is it faster, you might ask. Let me explain.&lt;/p&gt;

&lt;p&gt;With a traditional PHP application that gets served via a webserver like nginx, every incoming request is going to spawn an PHP-FPM worker. This means that each request starts up one individual PHP process, that will run through all the necessary tasks in order to serve that one request.&lt;/p&gt;

&lt;p&gt;In the case of Laravel, this means that the Framework needs to be booted, all service providers register their services within the container, all providers get booted themselves, the request goes through a list of middleware classes, hits your controller, a view gets rendered, etc. until we eventually get a response from our server.&lt;/p&gt;

&lt;p&gt;With Swoole or RoadRunner in place, we still have a worker for each incoming HTTP request, but they all share the same booted framework. This means that only the first incoming request is going to bootstrap the framework (including all service providers, etc.) while every other request can then make use of a ready-to-go framework. And this is what makes Octane so insanely fast.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting started with Laravel Octane
&lt;/h2&gt;

&lt;p&gt;As Laravel Octane is a package, you need to install it as a dependency of your specific application. You can do this via composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel/octane&lt;span class="se"&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you installed Octane in your application, make sure to run &lt;code&gt;php artisan octane:install&lt;/code&gt;. This is going to publish the Octane configuration file, as well as add &lt;code&gt;rr&lt;/code&gt; - the RoadRunner binary, to the &lt;code&gt;.gitignore&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;As I said, Octane is going to publish its configuration file, which looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

    &lt;span class="cm"&gt;/*
    |--------------------------------------------------------------------------
    | Octane Server
    |--------------------------------------------------------------------------
    |
    | This value determines the default "server" that will be used by Octane
    | when starting, restarting, or stopping your server via the CLI. You
    | are free to change this to the supported server of your choosing.
    |
    */&lt;/span&gt;

    &lt;span class="s1"&gt;'server'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'OCTANE_SERVER'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'roadrunner'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="cm"&gt;/*
    |--------------------------------------------------------------------------
    | Force HTTPS
    |--------------------------------------------------------------------------
    |
    | When this configuration value is set to "true", Octane will inform the
    | framework that all absolute links must be generated using the HTTPS
    | protocol. Otherwise your links may be generated using plain HTTP.
    |
    */&lt;/span&gt;

    &lt;span class="s1"&gt;'https'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'OCTANE_HTTPS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="cm"&gt;/*
    |--------------------------------------------------------------------------
    | Octane Listeners
    |--------------------------------------------------------------------------
    |
    | All of the event listeners for Octane's events are defined below. These
    | listeners are responsible for resetting your application's state for
    | the next request. You may even add your own listeners to the list.
    |
    */&lt;/span&gt;

    &lt;span class="s1"&gt;'listeners'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;WorkerStarting&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nc"&gt;EnsureUploadedFilesAreValid&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="nc"&gt;RequestReceived&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prepareApplicationForNextOperation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prepareApplicationForNextRequest&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="c1"&gt;//&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="nc"&gt;RequestHandled&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="c1"&gt;//&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="nc"&gt;RequestTerminated&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="c1"&gt;//&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="nc"&gt;TaskReceived&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prepareApplicationForNextOperation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="c1"&gt;//&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="nc"&gt;TickReceived&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prepareApplicationForNextOperation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="c1"&gt;//&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="nc"&gt;OperationTerminated&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nc"&gt;FlushTemporaryContainerInstances&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;// DisconnectFromDatabases::class,&lt;/span&gt;
            &lt;span class="c1"&gt;// CollectGarbage::class,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="nc"&gt;WorkerErrorOccurred&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nc"&gt;ReportException&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nc"&gt;StopWorkerIfNecessary&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="nc"&gt;WorkerStopping&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="c1"&gt;//&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="cm"&gt;/*
    |--------------------------------------------------------------------------
    | Warm / Flush Bindings
    |--------------------------------------------------------------------------
    |
    | The bindings listed below will either be pre-warmed when a worker boots
    | or they will be flushed before every new request. Flushing a binding
    | will force the container to resolve that binding again when asked.
    |
    */&lt;/span&gt;

    &lt;span class="s1"&gt;'warm'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;defaultServicesToWarm&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="s1"&gt;'flush'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="cm"&gt;/*
    |--------------------------------------------------------------------------
    | Garbage Collection Threshold
    |--------------------------------------------------------------------------
    |
    | When executing long-lived PHP scripts such as Octane, memory can build
    | up before being cleared by PHP. You can force Octane to run garbage
    | collection if your application consumes this amount of megabytes.
    |
    */&lt;/span&gt;

    &lt;span class="s1"&gt;'garbage'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="cm"&gt;/*
    |--------------------------------------------------------------------------
    | Maximum Execution Time
    |--------------------------------------------------------------------------
    |
    | (info) 0 means no maximum limit
    |
    */&lt;/span&gt;

    &lt;span class="s1"&gt;'max_execution_time'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="cm"&gt;/*
    |--------------------------------------------------------------------------
    | Octane Cache Table
    |--------------------------------------------------------------------------
    |
    | While using Swoole, you may leverage the Octane cache, which is powered
    | by a Swoole table. You may set the maximum number of rows as well as
    | the number of bytes per row using the configuration options below.
    |
    */&lt;/span&gt;

    &lt;span class="s1"&gt;'cache'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'rows'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'bytes'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="cm"&gt;/*
    |--------------------------------------------------------------------------
    | Octane Swoole Tables
    |--------------------------------------------------------------------------
    |
    | While using Swoole, you may define additional tables as required by the
    | application. These tables can be used to store data that needs to be
    | quickly accessed by other workers on the particular Swoole server.
    |
    */&lt;/span&gt;

    &lt;span class="s1"&gt;'tables'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'example:1000'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'string:1000'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'votes'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'int'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up, you need to decide for yourself wether you want to use RoadRunner, or Swoole. You can then configure the application server that you want to use by customizing the &lt;code&gt;server&lt;/code&gt; key in the configuration file. This can either be &lt;code&gt;swoole&lt;/code&gt;, or &lt;code&gt;roadrunner&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  RoadRunner
&lt;/h3&gt;

&lt;p&gt;RoadRunner is an application server that is written in Go, that does not have any other dependencies within PHP itself. Choose RoadRunner, if you do not want to install additional PHP extensions. You can install RoadRunner through composer, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require spiral/roadrunner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Swoole
&lt;/h3&gt;

&lt;p&gt;Swoole comes with a couple of nice benefits, that RoadRunner can not provide. As Swoole is an extension on top of PHP, PHP itself gains some cool new features, such as "ticks" and "coroutines", which I'm going to cover in a bit. These features are not available with RoadRunner, so if you want to make use of them, you should go with Swoole.&lt;/p&gt;

&lt;p&gt;You can install the Swoole extension using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pecl &lt;span class="nb"&gt;install &lt;/span&gt;swoole
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During the installation, you will be asked if you want to have support for HTTP2, curl, JSON, and open_ssl within Swoole. You can safely stick to the default values here (which are &lt;code&gt;off&lt;/code&gt;) as those settings only affect things like coroutines. You will still be able to use curl, JSON, and everything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting Octane
&lt;/h3&gt;

&lt;p&gt;Once you have installed RoadRunner or Swoole, and defined it in your &lt;code&gt;octane.php&lt;/code&gt; configuration file, you can start Octane and let it serve your Laravel application. The Octane server can be started with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan octane:start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, Octane will start the server on port 8000, so you may access your application in a browser via &lt;code&gt;http://localhost:8000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So go ahead, visit that route and watch your Laravel application fly!&lt;br&gt;
If you make multiple requests to the app, you can see that the first one is a little bit slower - that's where the framework gets booted, while the other ones are noticeably faster, as they can use the booted framework from memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;200 GET / .............. 14.23 ms
200 GET / ..............  1.93 ms
200 GET / ..............  2.06 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Making code changes
&lt;/h2&gt;

&lt;p&gt;If you now go and make a code change - for example, add a new &lt;code&gt;/test&lt;/code&gt; route - and try to hit that URL, you will receive a 404!&lt;br&gt;
And that's because the request is still using the framework (and all of its routes/code) that was booted once you started the Octane server. So in order to see that code change, you need to restart your Octane server.&lt;br&gt;
Because this is super cumbersome to do during development, Octane comes with a nice way to automatically watch your codebase for changes and restart the Octane server automatically.&lt;/p&gt;

&lt;p&gt;In order to make this work, make sure to install &lt;a href=""&gt;Chokidar&lt;/a&gt; - a NodeJS based file watching library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev chokidar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then start the Octane server in "watch" mode, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan octane:start &lt;span class="nt"&gt;--watch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the next time you make a change in your codebase, this will be detected, and Octane will restart the workers for the requests and you can immediately see your changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing Workers
&lt;/h3&gt;

&lt;p&gt;Speaking of Workers - by default, Octane is going to start one worker for each CPU core that you have. But you can also change this, by passing a &lt;code&gt;--workers&lt;/code&gt; option to the &lt;code&gt;octane:start&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan octane:start &lt;span class="nt"&gt;--workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Swoole specific features
&lt;/h2&gt;

&lt;p&gt;As I mentioned, Octane comes with a couple of Swoole specific features, so lets take a look at those, as I think they are very interesting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrent Tasks
&lt;/h3&gt;

&lt;p&gt;Octane allows you to perform multiple tasks concurrently. This means that they will be performed at the same time and will be returned as soon as all tasks finished.&lt;/p&gt;

&lt;p&gt;Here's an example taken from the Octane documentation on GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Octane\Facades\Octane&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$servers&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;concurrently&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in this example, we are getting all users and all servers at the same time. To make this clearer, here's another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;concurrently&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are executing two "tasks" concurrently and PHP will continue evaluating the code as soon as both of the tasks are finished. One task waits for 0.5 seconds, the other one waits for 1 second. As they are being evaluated concurrently, in two individual tasks, PHP will wait exactly 1 second (not 1.5) until both results are available.&lt;br&gt;
This feature is a great way to perform multiple smaller tasks simultaneously.&lt;/p&gt;

&lt;p&gt;Just like the &lt;code&gt;--workers&lt;/code&gt; option, you can also customize the amount of &lt;code&gt;--task-workers&lt;/code&gt; that Octane should make available.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ticks / Intervals
&lt;/h3&gt;

&lt;p&gt;Octane in combination with Swoole, allows you to register &lt;code&gt;ticks&lt;/code&gt; - which are operations that will automatically be executed at a given interval. Similar to the &lt;code&gt;setInterval&lt;/code&gt; method in JavaScript.&lt;br&gt;
Unfortunately, there's no way to stop those ticks at the moment, but you can register them within your application like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'simple-ticker'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Ticking...'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Octane Cache
&lt;/h3&gt;

&lt;p&gt;Another new feature within Octane and Swoole is a new cache driver. This cache driver, according to the official documentation, provides read and write speeds of up to 2 million operations per second. Behind the scenes, Swoole is caching the data in a shared memory using &lt;a href="https://www.swoole.co.uk/docs/modules/swoole-table"&gt;Swoole Tables&lt;/a&gt;, which can be accessed across all workers. When the server restarts, the cached data will be flushed though, as the cache is only persisted in memory.&lt;/p&gt;

&lt;p&gt;To make use of this cache, you can access it through the &lt;code&gt;octane&lt;/code&gt; cache store on the Cache facade, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'octane'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'framework'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Laravel'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another cool new addition, that is Swoole and Octane specific is the ability of a "cache interval". This allows you to store information in the Octane cache and refresh the data in a given interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'octane'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'random'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Octane Tables
&lt;/h3&gt;

&lt;p&gt;Built upon the feature of &lt;a href="https://www.swoole.co.uk/docs/modules/swoole-table"&gt;Swoole Tables&lt;/a&gt;, you can create your own tables that you want to access within your Octane applications. These tables have the same performance benefit as a Cache would have, by allowing you to save data in a structured way.&lt;br&gt;
Keep in mind that all data that you store within such a table will be lost when the server restarts though.&lt;/p&gt;

&lt;p&gt;To configure a table, you can create an entry in the &lt;code&gt;tables&lt;/code&gt; section of your &lt;code&gt;octane.php&lt;/code&gt; config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'tables' =&amp;gt; [
    'example:1000' =&amp;gt; [
        'name' =&amp;gt; 'string:1000',
        'votes' =&amp;gt; 'int',
    ],
],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we are defining a table called &lt;code&gt;example&lt;/code&gt;, which can hold a maximum of 1.000 entries/rows. The structure of this table is a &lt;code&gt;name&lt;/code&gt;, which is a string with a maximum length of 1000, and &lt;code&gt;votes&lt;/code&gt;, which is an integer.&lt;/p&gt;

&lt;p&gt;To write data to this table, we can make use of the &lt;code&gt;Octane::table&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Octane\Facades\Octane&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'example'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a-unique-identifier'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Marcel Pociot'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'votes'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to pull out the data, we can use a &lt;code&gt;get&lt;/code&gt; method on the table, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'example'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a-unique-identifier'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Caveats with Octane
&lt;/h2&gt;

&lt;p&gt;There are a couple of things that you need to watch out for, when you want to either make an existing application ready for Octane, or start building a new application from scratch.&lt;/p&gt;

&lt;p&gt;Since Octane holds the framework in memory across all workers, things like all of your applications service providers will only be registered and booted once. While Octane takes care of resetting the state of first-party packages (which includes Inertia), it's not possible for Octane to reset global state that you might have in your own application code.&lt;/p&gt;

&lt;p&gt;The official documentation, which currently can be found on &lt;a href="https://github.com/laravel/octane#dependency-injection--octane"&gt;GitHub&lt;/a&gt; holds some of the most common scenarios that you should watch out for.&lt;/p&gt;

&lt;h3&gt;
  
  
  Listeners
&lt;/h3&gt;

&lt;p&gt;One feature of Octane that hasn't been documented yet, is the ability to register custom listeners, whenever something happens in the application server within Octane.&lt;br&gt;
You can hook into the following events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WorkerStarting&lt;/li&gt;
&lt;li&gt;RequestReceived&lt;/li&gt;
&lt;li&gt;RequestHandled&lt;/li&gt;
&lt;li&gt;RequestTerminated&lt;/li&gt;
&lt;li&gt;TaskReceived&lt;/li&gt;
&lt;li&gt;TickReceived&lt;/li&gt;
&lt;li&gt;OperationTerminated&lt;/li&gt;
&lt;li&gt;WorkerErrorOccurred&lt;/li&gt;
&lt;li&gt;WorkerStopping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To attach listeners to these events, you can add them to your &lt;code&gt;octane.php&lt;/code&gt; config file.&lt;/p&gt;
&lt;h3&gt;
  
  
  Service Warming and Flushing
&lt;/h3&gt;

&lt;p&gt;When a new Octane worker gets booted, you can specify a list of container bindings/services that you want to "warm up" during the boot process. This means that, upon the booting of the worker, the service container will already make the specified services available, so that following requests can immediately access them.&lt;/p&gt;

&lt;p&gt;Octane already has a list of internal services that it keeps warm during each worker boot process, but you can add your own services to the &lt;code&gt;warm&lt;/code&gt; section of the &lt;code&gt;octane.php&lt;/code&gt; config file.&lt;/p&gt;

&lt;p&gt;Similar to this, you can also define a list of services that you want to flush, before a new request comes in. This can be useful for services that get manipulated over the course of a request, that you want to reset to its original/unloaded state when a fresh request comes in.&lt;/p&gt;
&lt;h2&gt;
  
  
  Octane Routes
&lt;/h2&gt;

&lt;p&gt;If Octane does not already grant you enough speed boost, you can even squeeze a little more out of it, by making use of routing built right into Octane.&lt;br&gt;
You can define a custom Octane route through the Octane facade like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'/fast'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These routes are very fast because they entirely skip Laravels routing system (so these routes do not provide any kind of middleware) - which can be helpful for endpoints that only need to provide data really fast.&lt;/p&gt;

&lt;p&gt;Since the HTTP Kernel in Laravel is not being used for these requests, you need to return a Symfony Response object yourself, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\HttpFoundation\Response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Octane&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'/faster'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello from Octane.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All service providers are of course booted and available, so that you can still make use of these services, perform Eloquent queries, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alright...so why Octane?
&lt;/h2&gt;

&lt;p&gt;Laravel Octane is definitely going to give your Laravel application a big performance boost - and we all love performance boosts, don't we?&lt;br&gt;
Do we actually need this performance boost? Well, maybe - I think it depends on the application that you are running. &lt;br&gt;
But what's more important to me, is the fact that Laravel is (once again) pushing the current state of PHP. Not only is Octane a package that requires at least PHP 8, but it also pushes exciting new features in the PHP world such as coroutines, ticks, and in general the mindset of serving your own application using an artisan command.&lt;/p&gt;

&lt;p&gt;I'm excited for the future of Octane!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
