<?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>DEV Community: Ridwan Kasim</title>
    <description>The latest articles on DEV Community by Ridwan Kasim (@dotmarn).</description>
    <link>https://dev.to/dotmarn</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%2F192581%2F7529f1a7-a41e-4aaf-8388-5ce001cc5c52.jpg</url>
      <title>DEV Community: Ridwan Kasim</title>
      <link>https://dev.to/dotmarn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dotmarn"/>
    <language>en</language>
    <item>
      <title>Working with multiple image select in Laravel Livewire</title>
      <dc:creator>Ridwan Kasim</dc:creator>
      <pubDate>Sat, 09 Nov 2024 20:49:04 +0000</pubDate>
      <link>https://dev.to/dotmarn/working-with-multiple-image-select-in-laravel-livewire-4683</link>
      <guid>https://dev.to/dotmarn/working-with-multiple-image-select-in-laravel-livewire-4683</guid>
      <description>&lt;p&gt;In this article, I am going to show you a simple idea to fix the loss of previously selected image/images whenever you want to select more images using livewire with laravel.&lt;/p&gt;

&lt;p&gt;I know there are several ways to achieve this but I find this method very easy with the help of some livewire lifecycle hooks which are the&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Updating and the Updated hooks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This screenshot shows the full code needed by your livewire component class&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6rjkd6qpbnc794ry7kf0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6rjkd6qpbnc794ry7kf0.png" alt="full code" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start by looking at what &lt;strong&gt;Updating&lt;/strong&gt; and &lt;strong&gt;Updated&lt;/strong&gt; hooks do. Then, I will explain the codes in the above screenshot step by step.&lt;/p&gt;

&lt;h4&gt;
  
  
  Updating:
&lt;/h4&gt;

&lt;p&gt;This runs before any update to the Livewire component's data is completed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Updated:
&lt;/h4&gt;

&lt;p&gt;This runs after any update to the Livewire component's data is completed.&lt;/p&gt;

&lt;p&gt;The code explanation goes thus:&lt;/p&gt;

&lt;p&gt;First, add the &lt;code&gt;WithFileUploads&lt;/code&gt; trait to your component. Then declare the following properties&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Livewire&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;Livewire\Component&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;Livewire\WithFileUploads&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;Create&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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;WithFileUploads&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nv"&gt;$prevImages&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;In your blade template, add an input tag with a type of file and set the model name as images 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;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;wire:model=&lt;/span&gt;&lt;span class="s"&gt;"images"&lt;/span&gt; &lt;span class="na"&gt;multiple&lt;/span&gt; &lt;span class="na"&gt;accept=&lt;/span&gt;&lt;span class="s"&gt;"image/jpg,image/jpeg,image/png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if you attempt to select multiple images, Livewire will handle it and render the image for you and you can add a preview by using the code below:&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="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         @if (!empty($images))
                 @foreach ($images as $key =&amp;gt; $image)
                      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative float-left pt-[10px] pl-[15px] pr-[10px] pb-[0px] h-[150px] mb-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                          &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute bg-[#ddd] p-[8px] right-[25px] top-[20%] rounded-[50%]"&lt;/span&gt; &lt;span class="na"&gt;wire:click.prevent=&lt;/span&gt;&lt;span class="s"&gt;'removeItem({{ json_encode($key) }})'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                 &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fa fa-trash text-red-600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;
                          &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                         &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{{ $image-&amp;gt;temporaryUrl() }}"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-[150px] h-[150px] rounded-[15px]"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                  @endforeach
         @endif
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem with the above code is that anytime you click on the input tag to select a new set of files, the previously selected one(s) is lost during the process. Here is the quick fix I provided using two of the lifecycle hooks in Livewire.&lt;/p&gt;

&lt;p&gt;The first one is the updatingImages method. See the code sample below:&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;updatingImages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prevImages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;images&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;The above code is simply storing the content of the images property in &lt;code&gt;$prevImages&lt;/code&gt; property while the &lt;code&gt;$images&lt;/code&gt; property is about to start updating so as to prevent loss of content.&lt;/p&gt;

&lt;p&gt;The second one is the updatedImages method. See the code sample below:&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;updatedImages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prevImages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&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;The above code merges the data of the &lt;code&gt;$prevImages&lt;/code&gt; property with the data of the newly selected image/images then stores it back into the &lt;code&gt;$images&lt;/code&gt; property after the update is complete.&lt;/p&gt;

&lt;p&gt;This is one of the simplest ways of solving the issue stated at the beginning of this article. I hope you find it helpful.&lt;/p&gt;

&lt;p&gt;Thank you for reading!!!&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>livewire</category>
      <category>alpine</category>
    </item>
    <item>
      <title>Realtime logging in Laravel using Slack</title>
      <dc:creator>Ridwan Kasim</dc:creator>
      <pubDate>Mon, 11 Sep 2023 08:00:00 +0000</pubDate>
      <link>https://dev.to/dotmarn/realtime-logging-in-laravel-using-slack-46o9</link>
      <guid>https://dev.to/dotmarn/realtime-logging-in-laravel-using-slack-46o9</guid>
      <description>&lt;p&gt;To help developers know what is going on within their application, Laravel provides robust logging services that allow you to log messages to files, the system error log, and various other destinations.&lt;/p&gt;

&lt;p&gt;In this tutorial, I will cover the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduction to logging&lt;/li&gt;
&lt;li&gt;Overview of the Laravel log configuration file&lt;/li&gt;
&lt;li&gt;Setting up slack for real-time logging.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Introduction to logging
&lt;/h4&gt;

&lt;p&gt;Logging in Laravel is channel-based, and each channel defines a specific way of writing log messages. For example, the &lt;code&gt;single&lt;/code&gt; channel writes log files to a single log file, while the &lt;code&gt;daily&lt;/code&gt; channel writes log to file based on date e.g. &lt;code&gt;laravel-2023-01-09.log&lt;/code&gt;, and the &lt;code&gt;slack&lt;/code&gt; channel sends log messages to Slack.&lt;/p&gt;

&lt;p&gt;There are several cool packages that help to visualize our logs like &lt;a href="https://github.com/ARCANEDEV/LogViewer" rel="noopener noreferrer"&gt;ARCANEDEV/LogViewer&lt;/a&gt;, &lt;a href="https://github.com/rap2hpoutre/laravel-log-viewer" rel="noopener noreferrer"&gt;rap2hpoutre/laravel-log-viewer&lt;/a&gt;, and &lt;a href="https://github.com/opcodesio/log-viewer" rel="noopener noreferrer"&gt;opcodesio/log-viewer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, you can check my previous article &lt;a href="https://dev.to/dotmarn/how-to-send-application-logs-to-telegram-in-laravel-1l12"&gt;send logs to telegram&lt;/a&gt; where I covered how to set up a telegram bot to handle our application log.&lt;/p&gt;

&lt;h4&gt;
  
  
  Overview of Laravel Log Configuration file
&lt;/h4&gt;

&lt;p&gt;Laravel provides you with great configuration flexibility which is housed in the &lt;code&gt;config/logging.php&lt;/code&gt; file. This file allows you to configure your application's log channels, so let's take a look at the default file below:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Monolog\Handler\NullHandler&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;Monolog\Handler\StreamHandler&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;Monolog\Handler\SyslogUdpHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

    &lt;span class="s1"&gt;'default'&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;'LOG_CHANNEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'stack'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="s1"&gt;'deprecations'&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;'channel'&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;'LOG_DEPRECATIONS_CHANNEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'null'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s1"&gt;'trace'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="s1"&gt;'channels'&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;'stack'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'stack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'channels'&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;'single'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'ignore_exceptions'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'single'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'single'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logs/laravel.log'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'daily'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'daily'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logs/laravel.log'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'days'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'slack'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'slack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'url'&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;'LOG_SLACK_WEBHOOK_URL'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'username'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Laravel Log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'emoji'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;':boom:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'critical'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'papertrail'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'monolog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'handler'&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;'LOG_PAPERTRAIL_HANDLER'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SyslogUdpHandler&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="s1"&gt;'handler_with'&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;'host'&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;'PAPERTRAIL_URL'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'port'&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;'PAPERTRAIL_PORT'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'connectionString'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'tls://'&lt;/span&gt;&lt;span class="mf"&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;'PAPERTRAIL_URL'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="mf"&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;'PAPERTRAIL_PORT'&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="s1"&gt;'stderr'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'monolog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'handler'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;StreamHandler&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="s1"&gt;'formatter'&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;'LOG_STDERR_FORMATTER'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'with'&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;'stream'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'php://stderr'&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="s1"&gt;'syslog'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'syslog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'errorlog'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'errorlog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'null'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'monolog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'handler'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;NullHandler&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="s1"&gt;'emergency'&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;'path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logs/laravel.log'&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;From the config file, you can see different options available for use. Let's review a few of these options and what they do. We will use the &lt;code&gt;daily&lt;/code&gt; option.&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="s1"&gt;'daily'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'daily'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logs/laravel.log'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'days'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;14&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;&lt;code&gt;driver&lt;/code&gt;: This tells laravel the driver to use.&lt;br&gt;
&lt;code&gt;path&lt;/code&gt;: This tells Laravel where to write the logs to.&lt;br&gt;
&lt;code&gt;level&lt;/code&gt;: This tells Laravel the type of log to be handled by this channel. It can be &lt;code&gt;debug&lt;/code&gt;, &lt;code&gt;critical&lt;/code&gt;, &lt;code&gt;warning&lt;/code&gt; etc.&lt;br&gt;
&lt;code&gt;days&lt;/code&gt;: The &lt;code&gt;days&lt;/code&gt; option tells Laravel how long the log should be retained before deleting.&lt;br&gt;
You can read more about logging from the &lt;a href="https://laravel.com/docs/9.x/logging#main-content" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Setting up Slack for Logging
&lt;/h4&gt;

&lt;p&gt;Let's proceed by creating an app on &lt;a href="https://api.slack.com/apps/" rel="noopener noreferrer"&gt;Slack&lt;/a&gt;. Click on the &lt;strong&gt;Create New App&lt;/strong&gt; button and select the first option as seen in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2iecwrb7cgmz93h5n6y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2iecwrb7cgmz93h5n6y.png" alt="slack dashboard" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fill in the app name, select a workspace for the app and click the &lt;strong&gt;create app&lt;/strong&gt; button to save the form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihkcrabeowwoxjpuhite.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihkcrabeowwoxjpuhite.png" alt="App setup" width="800" height="401"&gt;&lt;/a&gt;&lt;br&gt;
Now that our app has been created, select the &lt;code&gt;incoming webhooks&lt;/code&gt; option and activate the toggle on the next screen shown to you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1a4z7bo3fnwfxzu5m9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1a4z7bo3fnwfxzu5m9g.png" alt="Webhook Setup" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down to the bottom of the page and click on &lt;strong&gt;Add New Webhook to Workspace&lt;/strong&gt;. On the next screen shown to you, select a channel and click on &lt;strong&gt;Allow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3as6e8aztedss4opc7r6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3as6e8aztedss4opc7r6.png" alt="Webhook Access grant" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Slack will now generate a webhook URL for us. Copy it, head over to your &lt;code&gt;.env&lt;/code&gt; file and add it to your app like below.&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="no"&gt;LOG_SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="n"&gt;hooks&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slack&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;xxxxxxxxxx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open up the &lt;code&gt;logging.php&lt;/code&gt; file then under &lt;strong&gt;channels&lt;/strong&gt; array, since the default is set to stack, let's change the channels to &lt;code&gt;slack&lt;/code&gt; from &lt;code&gt;single&lt;/code&gt; and save the file.&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="s1"&gt;'stack'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'stack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'channels'&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;'slack'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'ignore_exceptions'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&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;Let's test it out by opening up &lt;a href="https://laravel.com/docs/9.x/artisan#tinker" rel="noopener noreferrer"&gt;Tinker&lt;/a&gt; and run the command below:&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="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"This is just a tutorial demo logging"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9sjgomizwo3x2d3oe5l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9sjgomizwo3x2d3oe5l.png" alt="Slack channel logging test" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voila!!!&lt;/p&gt;

&lt;h4&gt;
  
  
  Wrapping up
&lt;/h4&gt;

&lt;p&gt;In this article, you have learned about logging in to Laravel and how to set up Slack to receive your application logs in real time.&lt;/p&gt;

&lt;p&gt;Don't forget to give me a shoutout on &lt;a href="https://www.linkedin.com/in/kasim-ridwan/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; &amp;amp; &lt;a href="https://twitter.com/oluwalosheyii" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>slack</category>
      <category>logging</category>
    </item>
    <item>
      <title>How to send application logs to Telegram in Laravel.</title>
      <dc:creator>Ridwan Kasim</dc:creator>
      <pubDate>Sun, 08 Jan 2023 20:12:35 +0000</pubDate>
      <link>https://dev.to/dotmarn/how-to-send-application-logs-to-telegram-in-laravel-1l12</link>
      <guid>https://dev.to/dotmarn/how-to-send-application-logs-to-telegram-in-laravel-1l12</guid>
      <description>&lt;p&gt;The Laravel framework has a robust logging system that allows you to send log messages to files, system logs, and various other destinations. Logging in Laravel is channel-based, and each channel defines a specific way of writing log messages. For example, the &lt;code&gt;single&lt;/code&gt; channel writes log files to a single log file, while the &lt;code&gt;daily&lt;/code&gt; channel writes log to file based on date e.g. &lt;code&gt;laravel-2023-01-09.log&lt;/code&gt;, and the &lt;code&gt;slack&lt;/code&gt; channel sends log messages to Slack.&lt;/p&gt;

&lt;p&gt;Laravel logging is created on top of &lt;a href="https://github.com/Seldaek/monolog" rel="noopener noreferrer"&gt;Monolog&lt;/a&gt;, which is a powerful logging library for PHP projects. In this guide, we will be looking at how to send our laravel logs to telegram channel with the help of the Telegram Bot API.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;p&gt;You need to have the latest version of PHP and &lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;Composer&lt;/a&gt; installed on your computer. You should also create a new Laravel project so that you can test the code snippets in this article. You can consult Laravel's &lt;a href="https://laravel.com/docs/9.x/installation#your-first-laravel-project" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; for details on creating a new project on your machine.&lt;/p&gt;

&lt;p&gt;Let's start by creating a laravel project with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;laravel new telegram-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  OR
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project laravel/laravel telegram-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to the project directory using the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;telegram-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's open the project in VsCode using the command below:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Exploring the logging config file
&lt;/h4&gt;

&lt;p&gt;Laravel projects include a &lt;code&gt;config&lt;/code&gt; directory containing several configuration files used to customize the project's different aspects, such as the database setup, caching, session management, and more. In addition, the configuration options related to logging are also present in this directory in the &lt;code&gt;logging.php&lt;/code&gt; file. Go ahead and open this file in your editor to examine its contents:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Monolog\Handler\NullHandler&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;Monolog\Handler\StreamHandler&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;Monolog\Handler\SyslogUdpHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

    &lt;span class="s1"&gt;'default'&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;'LOG_CHANNEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'stack'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="s1"&gt;'deprecations'&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;'channel'&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;'LOG_DEPRECATIONS_CHANNEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'null'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s1"&gt;'trace'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="s1"&gt;'channels'&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;'stack'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'stack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'channels'&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;'single'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'ignore_exceptions'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'single'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'single'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logs/laravel.log'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'daily'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'daily'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logs/laravel.log'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'days'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'slack'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'slack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'url'&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;'LOG_SLACK_WEBHOOK_URL'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'username'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Laravel Log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'emoji'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;':boom:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'critical'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="mf"&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;As we can see, there are several options in the channel array which can be used to customize the logging aspect of our project. Let's proceed by setting up our Telegram channel and creating a Bot through &lt;a href="https://telegram.me/BotFather" rel="noopener noreferrer"&gt;BotFather&lt;/a&gt;. Open the link in your browser and start the conversation by sending the message &lt;code&gt;/start&lt;/code&gt;. You should receive a message with the next steps to creating your bot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96d2uot67wwns2biwp04.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96d2uot67wwns2biwp04.png" alt="BotFather" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;/newbot&lt;/code&gt; and choose a name &amp;amp; a username for your bot. The bot will generate your API token for you as seen in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbdmainhp9i5q8hpezdf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbdmainhp9i5q8hpezdf.png" alt="Bot setup" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will now proceed to create a new channel &lt;code&gt;LaravelDemoLogging&lt;/code&gt; and add our new bot &lt;code&gt;DemoLoggingBot&lt;/code&gt; to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymrbio3f12kgkp1q7z8k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymrbio3f12kgkp1q7z8k.png" alt="Image description" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to change the channel type to public. Click the channel info and edit the channel type and set it to public. Also, set the channel username which we are going to use in our laravel project along with the API token.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frukyljdipe8rg0rtsiyy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frukyljdipe8rg0rtsiyy.png" alt="Image description" width="800" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, let's open the &lt;code&gt;.env&lt;/code&gt; file and the following variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TELEGRAM_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-api-key"&lt;/span&gt;
&lt;span class="nv"&gt;TELEGRAM_CHANNEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"@laraveldemologging"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: the channel must have a @ prefix when setting it in the .env file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Open the &lt;code&gt;logging.php&lt;/code&gt; file and add a new channel after the &lt;code&gt;stack&lt;/code&gt; array and it to the channels like so:&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="s1"&gt;'stack'&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;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'stack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'channels'&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;'single'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'telegram'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'ignore_exceptions'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="s2"&gt;"telegram"&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;'driver'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'monolog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'handler'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;FilterHandler&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="s1"&gt;'level'&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;'LOG_LEVEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'with'&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;'handler'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TelegramBotHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$apiKey&lt;/span&gt; &lt;span class="o"&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;'TELEGRAM_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$channel&lt;/span&gt; &lt;span class="o"&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;'TELEGRAM_CHANNEL'&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, add the handlers used within the telegram array to the top of the file like so:&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;Monolog\Handler\FilterHandler&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;Monolog\Handler\TelegramBotHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start Laravel tinker from the terminal then log something:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;info&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"This is a demo log"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrzuad5v31obcwchj1uy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrzuad5v31obcwchj1uy.png" alt="Image description" width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrh0fakm00xlrubl6ws3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrh0fakm00xlrubl6ws3.png" alt="Image description" width="800" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Wrapping up
&lt;/h4&gt;

&lt;p&gt;In this article, you have learned about logging in Laravel and how to setup a telegram channel &amp;amp; bot to receive your application logs in realtime.&lt;/p&gt;

&lt;p&gt;Don't forget to give me a shoutout on &lt;a href="https://www.linkedin.com/in/kasim-ridwan/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; &amp;amp; &lt;a href="https://twitter.com/oluwalosheyii" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Keep learning and happy coding!!!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to use Camera Preview plugin in Ionic with Capacitor v3</title>
      <dc:creator>Ridwan Kasim</dc:creator>
      <pubDate>Fri, 04 Mar 2022 06:19:14 +0000</pubDate>
      <link>https://dev.to/dotmarn/how-to-use-camera-preview-plugin-in-ionic-with-capacitor-v3-2plk</link>
      <guid>https://dev.to/dotmarn/how-to-use-camera-preview-plugin-in-ionic-with-capacitor-v3-2plk</guid>
      <description>&lt;p&gt;In this article, we will be looking at how to make use of the &lt;strong&gt;Camera Preview Plugin&lt;/strong&gt; in our ionic apps. This plugin doesn't cause your app to restart whenever the camera is launched unlike the &lt;strong&gt;Camera Plugin&lt;/strong&gt;. Research shows that the issue will occur when the device running the app is on low memory.&lt;/p&gt;

&lt;p&gt;Before we get started, make sure you have your development environment set up for ionic else follow the official &lt;a href="https://ionicframework.com/docs/intro/environment" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;&lt;br&gt;
Let's start by creating a blank ionic project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic start camera-preview blank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select &lt;em&gt;Angular&lt;/em&gt; from the options and wait for some minutes while the project is created.&lt;/p&gt;

&lt;p&gt;Navigate to the project directory by running the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd camera-preview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now install our camera preview plugin with this command:&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 @capacitor-community/camera-preview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then build the project and synchronise the changes by running the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic build &amp;amp;&amp;amp; npx cap sync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch the app by running the command below. This will open the project in your browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the newly created project in your favourite code editor. Also, we need to generate one more page component to render our camera.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic generate page preview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our project directory, we will now have a folder for &lt;strong&gt;home&lt;/strong&gt; &amp;amp; another for &lt;strong&gt;preview&lt;/strong&gt;. So let's open the &lt;strong&gt;home.page.html&lt;/strong&gt; and add a button to launch the camera.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ion-header [translucent]="true"&amp;gt;
  &amp;lt;ion-toolbar&amp;gt;
    &amp;lt;ion-title&amp;gt;
      Camera Preview Demo
    &amp;lt;/ion-title&amp;gt;
  &amp;lt;/ion-toolbar&amp;gt;
&amp;lt;/ion-header&amp;gt;

&amp;lt;ion-content [fullscreen]="true"&amp;gt;
    &amp;lt;div *ngIf="image"&amp;gt;
        &amp;lt;img [src]="image" alt="" srcset=""&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;ion-button (click)="openCamera()" color="primary" expand="block" fill="solid" size="default"&amp;gt;
       Open Camera
    &amp;lt;/ion-button&amp;gt;
&amp;lt;/ion-content&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing to do is to register the preview module in our &lt;strong&gt;app.module.ts&lt;/strong&gt; file. Your &lt;strong&gt;app.module.ts&lt;/strong&gt; should look like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { PreviewPageModule } from "./preview/preview.module";

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    PreviewPageModule
  ],
  providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
  bootstrap: [AppComponent],
})
export class AppModule { }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's open the &lt;strong&gt;home.page.ts&lt;/strong&gt; file and add the code for the &lt;strong&gt;openCamera()&lt;/strong&gt; method.&lt;/p&gt;

&lt;p&gt;Import the ionic modal and the preview page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ModalController } from '@ionic/angular';
import { PreviewPage } from '../preview/preview.page';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then inject the modal into the constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;constructor(private modal: ModalController) {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All is set and we can now implement the function to launch our camera in the preview modal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async openCamera() {
    const modal = await this.modal.create({
        component: PreviewPage,
        cssClass: '',
        animated: true
    });
    return await modal.present();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's implement the look and feel of the camera by opening our &lt;strong&gt;preview.page.html&lt;/strong&gt; and the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ion-content id="content" [fullscreen]="true"&amp;gt;
  &amp;lt;div *ngIf="cameraActive"&amp;gt;
      &amp;lt;ion-button (click)="stopCamera()" expand="block" id="close"&amp;gt;
          &amp;lt;ion-icon slot="icon-only" name="close-circle"&amp;gt;&amp;lt;/ion-icon&amp;gt;
      &amp;lt;/ion-button&amp;gt;

      &amp;lt;ion-button (click)="takePicture()" expand="block" id="capture"&amp;gt;
          &amp;lt;ion-icon slot="icon-only" name="camera"&amp;gt;&amp;lt;/ion-icon&amp;gt;
      &amp;lt;/ion-button&amp;gt;

      &amp;lt;ion-button (click)="flipCamera()" expand="block" id="flip"&amp;gt;
          &amp;lt;ion-icon slot="icon-only" name="repeat"&amp;gt;&amp;lt;/ion-icon&amp;gt;
      &amp;lt;/ion-button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/ion-content&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing is to add some styling to our buttons. Open &lt;strong&gt;preview.page.scss&lt;/strong&gt; file and the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ion-content {
  --background: transparent !important;
}

#capture {
  position: absolute;
  bottom: 30px;
  left: calc(50% - 25px);
  width: 50px;
  height: 50px;
  z-index: 99999;
}

#flip {
  position: absolute;
  bottom: 30px;
  left: calc(50% + 125px);
  width: 50px;
  height: 50px;
  z-index: 99999;
}

#close {
  position: absolute;
  bottom: 30px;
  left: calc(50% - 175px);
  width: 50px;
  height: 50px;
  z-index: 99999;
}

#capture::part(native) {
  border-radius: 30px;
}

#close::part(native) {
  border-radius: 30px;
}

#flip::part(native) {
  border-radius: 30px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's open the &lt;strong&gt;preview.page.ts&lt;/strong&gt; file and add it to our imports.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { CameraPreview } from '@capacitor/core';
import { CameraPreviewOptions, CameraPreviewPictureOptions } from '@capacitor-community/camera-preview';
import '@capacitor-community/camera-preview';
import { ModalController } from '@ionic/angular';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then inject the modal into the constructor. Also, we will declare two variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image = null;
cameraActive = false;
constructor(private modal: ModalController) {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we are using a modal, we need to launch the camera on the device whenever the &lt;strong&gt;Open Camera&lt;/strong&gt; button is clicked. Let's create a function called &lt;strong&gt;launchCamera()&lt;/strong&gt; and call it inside &lt;strong&gt;ngOnInit()&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngOnInit() {
   this.launchCamera()
}

launchCamera() {
    const cameraPreviewOptions: CameraPreviewOptions = {
      position: 'front', // front or rear
      parent: 'content', // the id on the ion-content
      className: '',
      width: window.screen.width, //width of the camera display
      height: window.screen.height - 200, //height of the camera
      toBack: false,
    };
    CameraPreview.start(cameraPreviewOptions);
    this.cameraActive = true;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create a function to take our picture. Once the picture is taken, we need to stop the camera and close the modal. The result is a base64 string which we will pass back when the modal is dismissed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async takePicture() {
    const cameraPreviewPictureOptions: CameraPreviewPictureOptions = {
      quality: 90
    };
    const result = await CameraPreview.capture(cameraPreviewPictureOptions);
    this.image = `data:image/jpeg;base64,${result.value}`;
    this.stopCamera();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to add the function to stop the camera and close the modal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async stopCamera() {
    await CameraPreview.stop();
    this.modal.dismiss(this.image);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to add the function to switch the camera from front to back and vice versa.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: this won't work if you test it in a browser.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async flipCamera() {
   await CameraPreview.flip();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's open our &lt;strong&gt;home.page.ts&lt;/strong&gt; file to listen to the modal close event. To do that we need to update the &lt;strong&gt;openCamera()&lt;/strong&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; modal.onDidDismiss().then((data) =&amp;gt; {
     if (data !== null) {
        this.image = data.data;
     }
 });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila!!! Let's test it in the browser. You can find the full code &lt;a href="https://github.com/dotmarn/ionic-capacitor-camera-preview-demo" rel="noopener noreferrer"&gt;here:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxc38u0bs15th00ztjonm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxc38u0bs15th00ztjonm.png" alt="Sample-one" width="398" height="715"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faw1bj444y1ee02yauxfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faw1bj444y1ee02yauxfz.png" alt="sample-two" width="398" height="715"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ionic</category>
      <category>angular</category>
      <category>capacitor</category>
      <category>hybrid</category>
    </item>
    <item>
      <title>Setting up TailwindCSS v3 with Laravel v8.8.1 &amp; later.</title>
      <dc:creator>Ridwan Kasim</dc:creator>
      <pubDate>Mon, 31 Jan 2022 07:52:01 +0000</pubDate>
      <link>https://dev.to/dotmarn/setting-up-tailwindcss-v3-with-laravel-v881-later-3o2</link>
      <guid>https://dev.to/dotmarn/setting-up-tailwindcss-v3-with-laravel-v881-later-3o2</guid>
      <description>&lt;p&gt;Tailwind is a popular utility-first CSS framework that helps developers build and design their products very fast without wasting much time.&lt;/p&gt;

&lt;p&gt;In this article, we'll be looking at how to configure &amp;amp; set up tailwind in a laravel project.&lt;/p&gt;

&lt;p&gt;Before moving along, make sure you have your development environment set up for &lt;a href="https://laravel.com" rel="noopener noreferrer"&gt;Laravel&lt;/a&gt;. &lt;br&gt;
Let's start by bootstrapping our laravel project with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;laravel new sample-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  OR
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer create-project laravel/laravel sample-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to the project directory by doing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd sample-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's bring our project up with the command below from the terminal:&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 serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will start up our project and keep it running. You can access it through your favourite browser on &lt;code&gt;http://127.0.0.1:8000&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjrzee44qk3gbb8kbofe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjrzee44qk3gbb8kbofe.png" alt="preview" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can install &lt;code&gt;tailwindcss&lt;/code&gt; in our already laravel project by doing:&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 -D tailwindcss postcss autoprefixer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we create the 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;npx tailwindcss init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a message like the one in the image below&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7st570xa0201ewe1opsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7st570xa0201ewe1opsu.png" alt="preview" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now open the project in your favourite code editor and add the following to the &lt;code&gt;tailwind.config.js&lt;/code&gt; file inside the &lt;code&gt;content&lt;/code&gt; array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'./resources/**/*.blade.php',
'./resources/**/*.js',
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to tell Laravel to compile our Tailwind resources using Laravel Mix. Open the &lt;code&gt;webpack.mix.js&lt;/code&gt; file in the root of our project &amp;amp; include tailwindcss as a postCss plugin as seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix.js('resources/js/app.js', 'public/js')
    .postCss('resources/css/app.css', 'public/css', [
        require("tailwindcss")
    ]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we need to import all &lt;a class="mentioned-user" href="https://dev.to/tailwindcss"&gt;@tailwindcss&lt;/a&gt; component layers into our project css. Open the &lt;code&gt;resources/css/app.css&lt;/code&gt; file and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@tailwind base;
@tailwind components;
@tailwind utilities;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! Configuration is done and you can watch for changes and compile assets in real-time during development.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx mix watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have something like the image below&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Freoc9nqasicbeofv97cd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Freoc9nqasicbeofv97cd.png" alt="preview" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's open our &lt;code&gt;welcome.blade.php&lt;/code&gt; file and replace everything there with the code below to test our set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="utf-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1"&amp;gt;
    &amp;lt;title&amp;gt;Laravel&amp;lt;/title&amp;gt;
    &amp;lt;link href="{{ asset('css/app.css') }}" rel="stylesheet"&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body class="bg-[#063970]"&amp;gt;
    &amp;lt;div class="text-center mt-12"&amp;gt;
        &amp;lt;h1 class="text-4xl text-white font-semibold"&amp;gt;Welcome!!!&amp;lt;/h1&amp;gt;
        &amp;lt;p class="text-xl text-white mt-4"&amp;gt;This is a tailwind page&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have a screen like the image below:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsmfe01wr62qnqzk8fdz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsmfe01wr62qnqzk8fdz.png" alt="preview" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all you need to do in order to set up tailwindCSS in your laravel project.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>laravel</category>
      <category>tailwindcss</category>
      <category>v3</category>
    </item>
    <item>
      <title>Ionic deeplink/universal link with Capacitor.</title>
      <dc:creator>Ridwan Kasim</dc:creator>
      <pubDate>Sun, 22 Nov 2020 03:31:47 +0000</pubDate>
      <link>https://dev.to/dotmarn/ionic-deeplink-universal-link-with-capacitor-2en1</link>
      <guid>https://dev.to/dotmarn/ionic-deeplink-universal-link-with-capacitor-2en1</guid>
      <description>&lt;p&gt;This article will assume you have already done the appropriate configurations for both android and ios but if you haven't then quickly check the steps &lt;a href="https://capacitorjs.com/docs/guides/deep-links" rel="noopener noreferrer"&gt;here:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code samples in this article will be strictly for Angular. Let's get started.&lt;/p&gt;

&lt;p&gt;Open your &lt;code&gt;app.component.ts&lt;/code&gt; file and import &lt;code&gt;NgZone&lt;/code&gt;, &lt;code&gt;Router&lt;/code&gt; from Angular, then &lt;code&gt;App&lt;/code&gt; from Capacitor at the beginning of the file as seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, NgZone } from '@angular/core';
import { Router } from '@angular/router';
import { Plugins } from '@capacitor/core';
const { App } = Plugins;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add &lt;code&gt;Router&lt;/code&gt; and &lt;code&gt;NgZone&lt;/code&gt; to the constructor as seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;constructor(private router: Router, private zone: NgZone) {
    this.initializeApp();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing is to listen to the &lt;code&gt;appUrlOpen&lt;/code&gt; event, and redirect when a deep link is found or matched.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initializeApp() {
    App.addListener('appUrlOpen', (data: any) =&amp;gt; {
        this.zone.run(() =&amp;gt; {
            // Example URL: https://example.com/signup?ref=1234           
            const slug = data.url.split("?")[0];
            if (slug == 'https://example.com/signup') {
                this.router.navigateByUrl('/signup');
            }
            // If there's no match do nothing
        });
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the snippet above, &lt;code&gt;data.url&lt;/code&gt; contains the original link that was clicked. But there's need to know what URL was returned by the &lt;code&gt;appUrlOpen&lt;/code&gt; event so as to be able to handle redirects to the appropriate screen within your app. So we split the URL into parts by using the &lt;code&gt;?&lt;/code&gt; as the point of separation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data.url.split("?")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above line gives an array as seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;["http://example.com/signup", "ref=1234"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we assign the item with the zero index to slug:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const slug = data.url.split("?")[0];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check if it matches before performing a redirect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (slug == 'https://example.com/signup') {
     this.router.navigateByUrl('/signup');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cool part is that using this technique, you can have other URLs like &lt;code&gt;https://example.com/reset-password&lt;/code&gt; which should take your users to the password reset screen within your app. To do this, modify your code 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;  // URL 1: https://example.com/signup?ref=1234
 //  URL 2: https://example.com/reset-password?email=test@gmail.com   
       const slug = data.url.split("?")[0];
       if (slug == 'https://example.com/signup') {
            this.router.navigateByUrl('/signup');
       } 
       else if (slug == 'https://example.com/reset-password') {
            this.router.navigateByUrl('/reset');
       }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Handling query params.
&lt;/h4&gt;

&lt;p&gt;It is possible sometimes we are not just redirecting but we need to get the query params and use it within the app. Let's use the signup link &lt;code&gt;https://example.com/signup?ref=1234&lt;/code&gt; as an example. This can be done with the help of this regex expression which returns value of &lt;code&gt;ref&lt;/code&gt; from the link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    getQueryParams(params, url) {
        let reg = new RegExp('[?&amp;amp;]' + params + '=([^&amp;amp;#]*)', 'i');
        let queryString = reg.exec(url);
        return queryString ? queryString[1] : null;
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can use it 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;let url = 'https://example.com/signup?ref=1234';
const params = this.getQueryParams('ref', url);
//params is 1234
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!!! I hope you had fun reading and learning from the article to continue the conversation you can follow me on Twitter: &lt;a href="https://twitter.com/oluwalosheyii" rel="noopener noreferrer"&gt;@oluwasheyii&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gracias!!!&lt;/p&gt;

</description>
      <category>ionic</category>
      <category>angular</category>
      <category>capacitor</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Useful Ionic + Capacitor commands</title>
      <dc:creator>Ridwan Kasim</dc:creator>
      <pubDate>Mon, 26 Oct 2020 18:47:01 +0000</pubDate>
      <link>https://dev.to/dotmarn/useful-ionic-capacitor-commands-4di</link>
      <guid>https://dev.to/dotmarn/useful-ionic-capacitor-commands-4di</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Run app with live reload (Android)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic cap run android -l --external
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run app with live reload (iOS)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic cap run ios -l --external
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;How to generate a release APK without opening the android studio
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic capacitor copy android --prod &amp;amp;&amp;amp; cd android &amp;amp;&amp;amp; ./gradlew assembleRelease &amp;amp;&amp;amp; cd ..     
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;How to generate a debug APK without opening the android studio
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic capacitor copy android &amp;amp;&amp;amp; cd android &amp;amp;&amp;amp; ./gradlew assembleDebug &amp;amp;&amp;amp; cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;How to generate icons &amp;amp; splash screen without specifying platform
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cordova-res --skip-config --copy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;How to build and run apk directly on the device from CLI
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic capacitor copy android &amp;amp;&amp;amp; cd android &amp;amp;&amp;amp; ./gradlew assembleDebug &amp;amp;&amp;amp; ./gradlew installDebug &amp;amp;&amp;amp; cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will be updating this post with more useful commands. Thank you for reading!!!&lt;/p&gt;

</description>
      <category>ionic</category>
      <category>capacitor</category>
      <category>angular</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
