<?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: Gabriel Alejandro López López</title>
    <description>The latest articles on DEV Community by Gabriel Alejandro López López (@glpzzz).</description>
    <link>https://dev.to/glpzzz</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%2F217905%2F4f4223ae-aa79-42a1-8660-5b3bc21b887d.jpg</url>
      <title>DEV Community: Gabriel Alejandro López López</title>
      <link>https://dev.to/glpzzz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/glpzzz"/>
    <language>en</language>
    <item>
      <title>Integrating Yii3 packages into WordPress</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Sun, 03 Mar 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/integrating-yii3-packages-into-wordpress-4oko</link>
      <guid>https://dev.to/glpzzz/integrating-yii3-packages-into-wordpress-4oko</guid>
      <description>&lt;p&gt;I was recently assigned with the task of integrating several extensive forms into a WordPress website. These forms comprised numerous fields, intricate validation rules, dynamic fields (one to many relationships) and even interdependencies, where employing PHP inheritance could mitigate code duplication.&lt;/p&gt;

&lt;p&gt;Upon initial exploration, it became evident that the conventional approach for handling forms in WordPress typically involves either installing a plugin or manually embedding markup using the editor or custom page templates. Subsequently, one largely relies on the plugin’s functionality to manage form submissions or resorts to custom coding.&lt;/p&gt;

&lt;p&gt;Given that part of my task entailed logging data, interfacing with API endpoints, sending emails, and more, I opted to develop the functionality myself, rather than verifying if existing plugins supported these requirements.&lt;/p&gt;

&lt;p&gt;Furthermore, considering the current landscape (as of March 2024) where most Yii 3 packages are deemed production-ready according to official sources, and being a long-time user of the Yii framework, I deemed it an opportune moment to explore and acquaint myself with these updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source code available
&lt;/h2&gt;

&lt;p&gt;You can explore the entire project and review the code by accessing it on &lt;a href="https://github.com/glpzzz/yii3press"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, you can deploy it effortlessly using Docker by simply executing &lt;code&gt;docker-compose up&lt;/code&gt; from the project’s root directory. Check the &lt;code&gt;Dockerfile&lt;/code&gt; for the WordPress setup and content generation which is done automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;My objective was to render and manage forms within a WordPress framework utilizing Yii3 packages. For demonstration purposes, I chose to implement a basic Rating Form, where the focus is solely on validating the data without executing further actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach
&lt;/h2&gt;

&lt;p&gt;To proceed, let’s start with a minimalistic classic theme as an example. I created a WordPress page named “The Rating Form” within the dashboard. Then, a file named &lt;code&gt;page-the-rating-form.php&lt;/code&gt; is to be created within the theme’s root folder to display this specific page.&lt;/p&gt;

&lt;p&gt;This designated file serves as the blueprint for defining our form’s markup.&lt;/p&gt;

&lt;p&gt;Adding Yii3 Packages to the Project:&lt;/p&gt;

&lt;p&gt;To harness Yii3’s functionalities, we’ll incorporate the following packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/yiisoft/form-model"&gt;yiisoft/form-model&lt;/a&gt;: For defining a model class representing the form’s fields and facilitating field rendering.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/yiisoft/form"&gt;yiisoft/form&lt;/a&gt;: To handle markup-related tasks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/yiisoft/validator"&gt;yiisoft/validator&lt;/a&gt;: For input validation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To begin, let’s initialize a Composer project in the root of our theme by executing &lt;code&gt;composer init&lt;/code&gt;. This process will generate a composer.json file. Subsequently, we’ll proceed to include the Yii3 packages in our project.&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 yiisoft/form-model:dev-master yiisoft/validator yiisoft/form:dev-master

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and instruct the theme to load the composer autoload by adding the following line to the &lt;code&gt;functions.php&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require __DIR__. '/vendor/autoload.php';

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create the form model
&lt;/h3&gt;

&lt;p&gt;Following the execution of the &lt;code&gt;composer init&lt;/code&gt; command, a &lt;code&gt;src&lt;/code&gt; directory has been created in the root directory of the theme. We will now proceed to add our form model class within this directory.&lt;/p&gt;

&lt;p&gt;Anticipating the expansion of the project, it’s imperative to maintain organization. Thus, we shall create the directory &lt;code&gt;src/Forms&lt;/code&gt; and place the &lt;code&gt;RatingForm&lt;/code&gt; class inside it.&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;?php

namespace Glpzzz\Yii3press\Forms;

use Yiisoft\FormModel\FormModel;

class RatingForm extends FormModel
{

    private ?string $name = null;
    private ?string $email = null;
    private ?int $rating = null;
    private ?string $comment = null;
    private string $action = 'the_rating_form';

    public function getPropertyLabels(): array
    {
        return [
            'name' =&amp;gt; 'Name',
            'email' =&amp;gt; 'Email',
            'rating' =&amp;gt; 'Rating',
            'comment' =&amp;gt; 'Comment',
        ];
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beyond the requisite fields for our rating use case, it’s crucial to observe the &lt;code&gt;action&lt;/code&gt; class attribute. This attribute is significant as it instructs WordPress on which theme hook should manage the form submission. Further elaboration on this will follow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Validation Rules to the Model:
&lt;/h3&gt;

&lt;p&gt;Now, let’s incorporate some validation rules into the model to ensure input integrity. Initially, we’ll configure the class to implement the &lt;code&gt;RulesProviderInterface&lt;/code&gt;. This enables the form package to access these rules and augment the HTML markup with native validation attributes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class RatingForm extends FormModel implements RulesProviderInterface

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to implement the &lt;code&gt;getRules()&lt;/code&gt; method on the class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function getRules(): iterable
{
    return [
        'name' =&amp;gt; [
            new Required(),
        ],
        'email' =&amp;gt; [
            new Required(),
            new Email(),
        ],
        'rating' =&amp;gt; [
            new Required(),
            new Integer(min: 0, max: 5),
        ],
        'comment' =&amp;gt; [
            new Length(min: 100),
        ],
    ];
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create the form markup
&lt;/h3&gt;

&lt;p&gt;To generate the form markup, we require an instance of &lt;code&gt;RatingForm&lt;/code&gt; to be passed to the template. In WordPress, the approach I’ve adopted involves creating a global variable (admittedly not the most elegant solution) prior to rendering the page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$hydrator = new Hydrator(
    new CompositeTypeCaster(
        new NullTypeCaster(emptyString: true),
        new PhpNativeTypeCaster(),
        new HydratorTypeCaster(),
    )
);

add_filter('template_redirect', function () use ($hydrator) {
    // Get the queried object
    $queried_object = get_queried_object();

    // Check if it's a page
    if ($queried_object instanceof WP_Post &amp;amp;&amp;amp; is_page()) {
        if ($queried_object-&amp;gt;post_name === 'the-rating-form') {
            global $form;
            if ($form === null) {
                $form = $hydrator-&amp;gt;create(RatingForm::class, []);
            }
        }
    }
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s worth noting that we’ve instantiated the &lt;code&gt;Hydrator&lt;/code&gt; class outside any specific function, enabling us to reuse it for all necessary callbacks. With the &lt;code&gt;RatingForm&lt;/code&gt; instance now available, we’ll proceed to craft the markup for the form within the &lt;code&gt;page-the-rating-form.php&lt;/code&gt; file.&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;?php

use Glpzzz\Yii3press\Forms\RatingForm;
use Yiisoft\FormModel\Field;
use Yiisoft\Html\Html;

/** @var RatingForm $form */
global $form;

?&amp;gt;

&amp;lt;?php get_header(); ?&amp;gt;

&amp;lt;h1&amp;gt;&amp;lt;?php the_title(); ?&amp;gt;&amp;lt;/h1&amp;gt;

&amp;lt;?php the_content(); ?&amp;gt;

&amp;lt;?= Html::form()
  -&amp;gt;post(esc_url(admin_url('admin-post.php')))
  -&amp;gt;open()
?&amp;gt;

&amp;lt;?= Field::hidden($form, 'action')-&amp;gt;name('action') ?&amp;gt;
&amp;lt;?= Field::text($form, 'name') ?&amp;gt;
&amp;lt;?= Field::email($form, 'email') ?&amp;gt;
&amp;lt;?= Field::range($form, 'rating') ?&amp;gt;
&amp;lt;?= Field::textarea($form, 'comment') ?&amp;gt;

&amp;lt;?= Html::submitButton('Send') ?&amp;gt;

&amp;lt;?= "&amp;lt;/form&amp;gt;" ?&amp;gt;

&amp;lt;?php get_footer(); ?&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the markup generation of our form, we’ve leveraged a combination of Yii3’s &lt;code&gt;Html&lt;/code&gt; helpers and the &lt;code&gt;Field&lt;/code&gt; class. Notable points include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The form employs the POST method with the action specified as the &lt;code&gt;admin-post.php&lt;/code&gt; WordPress endpoint.&lt;/li&gt;
&lt;li&gt;To include the &lt;code&gt;action&lt;/code&gt; value in the form submission, we utilized a hidden field named &lt;code&gt;'action'&lt;/code&gt;. We opted to rename the input to &lt;code&gt;'action'&lt;/code&gt; as the &lt;code&gt;Field::hidden&lt;/code&gt; method generates field names in the format &lt;code&gt;TheFormClassName[the_field_name]&lt;/code&gt;, whereas we required it to be simply named &lt;code&gt;'action'&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This adjustment facilitates hooking into a theme function to handle the form request, as elucidated in the subsequent section.&lt;/p&gt;

&lt;p&gt;Before delving further, let’s capitalize on Yii’s capabilities to enhance the form. Although we’ve already defined validation rules in the model for validating input post-submission, it’s advantageous to validate input within the browser as well. While we could reiterate defining these validation rules directly on the input elements, Yii offers a streamlined approach. By incorporating the following code snippet into the &lt;code&gt;functions.php&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add_action('init', function () {
    ThemeContainer::initialize([
            'default' =&amp;gt; [
                'enrichFromValidationRules' =&amp;gt; true,
            ]
        ], 'default', new ValidationRulesEnricher()
    );
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By implementing this code snippet, we activate the &lt;code&gt;ValidationRulesEnricher&lt;/code&gt; for the default form theme. Upon activation, we’ll notice that the form fields are now enriched with validation rules such as ‘required’, ‘min’, and ‘ max’, aligning with the validation rules previously defined in the model class. This feature streamlines the process, saving us valuable time and minimizing the need for manual code composition. Indeed, this showcases some of the remarkable functionality offered by Yii3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Process the POST request
&lt;/h3&gt;

&lt;p&gt;When the form is submitted, it is directed to &lt;code&gt;admin-post.php&lt;/code&gt;, an endpoint provided by WordPress. However, when dealing with multiple forms, distinguishing the processing of each becomes essential. This is where the inclusion of the &lt;code&gt;action&lt;/code&gt; value in the POST request proves invaluable.&lt;/p&gt;

&lt;p&gt;Take note of the initial two lines in the following code snippet: the naming convention for the hook is &lt;code&gt;admin_post_&amp;lt;action_name&amp;gt;&lt;/code&gt;. Therefore, if a form has &lt;code&gt;action = 'the-rating-form'&lt;/code&gt;, the corresponding hook name will be &lt;code&gt;admin_post_the_rating_form&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As for the inclusion of both &lt;code&gt;admin_post_&amp;lt;action_name&amp;gt;&lt;/code&gt; and &lt;code&gt;admin_post_nopriv_&amp;lt;action_name&amp;gt;&lt;/code&gt;, this is because WordPress allows for different handlers depending on whether the user is logged in or not. In our scenario, we require the same handler regardless of the user’s authentication status.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add_action('admin_post_the_rating_form', fn() =&amp;gt; handleForms($hydrator));
add_action('admin_post_nopriv_the_rating_form', fn() =&amp;gt; handleForms($hydrator));

function handleForms(Hydrator $hydrator): void
{
  global $form;
  $form = $hydrator-&amp;gt;create(RatingForm::class, $_POST['RatingForm']);
  $result = (new Yiisoft\Validator\Validator())-&amp;gt;validate($form);

  if ($form-&amp;gt;isValid()) {
    // handle the form
  }

  get_template_part('page-the-rating-form');
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returning to the Yii aspect: we instantiate and load the posted data into the form utilizing the &lt;code&gt;hydrator&lt;/code&gt;. We then proceed to validate the data. If the validation passes successfully, we can proceed with the intended actions using the validated data. However, if validation fails, we re-render the form, populating it with the submitted data and any error messages generated during validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This was my first attempt at mixing Yii3 packages with a WordPress site. While I’m satisfied with the result, I think it can be improved, especially regarding the use of global variables. Since I’m not very experienced with WordPress, &lt;strong&gt;I’d appreciate any suggestions for improvement&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The Yii3 packages I used are ready for real-world use and offer the same quality and features as their older versions.&lt;/li&gt;
&lt;li&gt;Now you can use these Yii packages independently. This means you can apply your Yii skills to any PHP project.&lt;/li&gt;
&lt;li&gt;This project shows how we can enhance a WordPress site by tapping into the powerful features of Yii, while still keeping the simplicity of the CMS.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>yii3</category>
      <category>php</category>
      <category>wordpress</category>
      <category>forms</category>
    </item>
    <item>
      <title>Step-by-Step Guide: Enabling WWAN on ThinkPad P50 Ubuntu</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Mon, 22 Jan 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/step-by-step-guide-enabling-wwan-on-thinkpad-p50-ubuntu-2d4e</link>
      <guid>https://dev.to/glpzzz/step-by-step-guide-enabling-wwan-on-thinkpad-p50-ubuntu-2d4e</guid>
      <description>&lt;p&gt;If you’ve encountered issues with the default deactivation of WWAN on your Lenovo ThinkPad P50 after a fresh Ubuntu install, this guide will walk you through the steps to activate it. This is a personal reminder on the commands required to activate this feature based on discussions in &lt;a href="https://askubuntu.com/a/1436705/1023633"&gt;this Ask Ubuntu post&lt;/a&gt; where it’s explained that WWAN is deactivated by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Activate the Modem
&lt;/h2&gt;

&lt;p&gt;To enable the Lenovo shipped EM7455, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ln -sft /etc/ModemManager/fcc-unlock.d /usr/share/ModemManager/fcc-unlock.available.d/1199:9079

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup the Mobile Broadband Connection
&lt;/h2&gt;

&lt;p&gt;The next step is to create the Mobile Broadband connection using Network Manager GUI or nmcli. In order to do it with nmcli, first we need to identify the available modems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mmcli -L
    /org/freedesktop/ModemManager1/Modem/0 [Sierra Wireless, Incorporated] Sierra Wireless EM7455 Qualcomm Snapdragon X7 LTE-A

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, there is only one modem (indexed as 0). Now, identify the device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mmcli -m 0 | grep "primary port"
           | primary port: cdc-wdm1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating the Connection with nmcli
&lt;/h3&gt;

&lt;p&gt;And now we are ready to create the connection. For my actual service provider the required command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nmcli connection add type gsm ifname cdc-wdm1 con-name Cubacel apn nauta
Connection 'Cubacel2' (906f5b4f-b37b-4eff-b8eb-5c13dc9c532b) successfully added.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Values of the command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;type &lt;strong&gt;gsm&lt;/strong&gt; : the connection type (gsm for mobile broadband)&lt;/li&gt;
&lt;li&gt;ifname &lt;strong&gt;cdc-wdm1&lt;/strong&gt; : the device ID&lt;/li&gt;
&lt;li&gt;apn &lt;strong&gt;nauta&lt;/strong&gt; : the APN value defined by the provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The name is just a friendly identifier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Activate/deactivate the connection
&lt;/h3&gt;

&lt;p&gt;To activate this connection the command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nmcli connection up Cubacel
    Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/21)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to deactivate the command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nmcli connection down Cubacel
    Connection 'Cubacel' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/21)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Remove the connection
&lt;/h3&gt;

&lt;p&gt;If you want to remove the connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nmcli connection delete Cubacel
    Connection 'Cubacel' (7478c2fb-6d85-443d-ab67-2b812b761460) successfully deleted.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We have addressed the issue of deactivated WWAN on Lenovo ThinkPad P50 running Ubuntu, providing clear steps to activate the modem, set up the mobile broadband connection, and achieve seamless connectivity. Following these steps ensures a successful configuration for utilizing mobile broadband on your ThinkPad P50.&lt;/li&gt;
&lt;li&gt;Consider also the usage of &lt;code&gt;modem-manager-gui&lt;/code&gt; to work with the modem, but my notes on that are for another post.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Using image from &lt;a href="https://commons.wikimedia.org/wiki/File:Lenovo%5C_thinkpad%5C_p50%5C_%2829237281256%29.jpg"&gt;https://commons.wikimedia.org/wiki/File:Lenovo\_thinkpad\_p50\_%2829237281256%29.jpg&lt;/a&gt; licensed with CC BY-SA 2.0.&lt;/p&gt;

</description>
      <category>ubuntu</category>
      <category>wwan</category>
      <category>network</category>
      <category>thinkpad</category>
    </item>
    <item>
      <title>Updating my website with htmx</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Fri, 29 Sep 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/updating-my-website-with-htmx-38kg</link>
      <guid>https://dev.to/glpzzz/updating-my-website-with-htmx-38kg</guid>
      <description>&lt;p&gt;I have been reading a lot about htmx.org on Twitter lately and also seen an increase of the videos related to it on Youtube.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is htmx?
&lt;/h2&gt;

&lt;p&gt;Basically it is a JavaScript library to extend HTML by adding functionality including certain attributes in the HTML markup.&lt;/p&gt;

&lt;p&gt;There is a lot to say about it but it will refer you to the 2 more important sources&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://htmx.org"&gt;htmx.org&lt;/a&gt; the official documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.toHypermedia%20Systems"&gt;https://hypermedia.systems/&lt;/a&gt; a book on the hypermedia concept (the basics of htmx) and a very good resource of simple (not basic) web development.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why to use htmx?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;You want to enhance the user experience of your website.&lt;/li&gt;
&lt;li&gt;You don’t want to setup a project with React/Angular/Vue or any other framework.&lt;/li&gt;
&lt;li&gt;You want to do it fast.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to (quickly) use htmx?
&lt;/h2&gt;

&lt;p&gt;I’ll use this website as an example.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By today (September 2023) it is an static website created using Jekyll.&lt;/li&gt;
&lt;li&gt;When you click a link the whole page is reloaded&lt;/li&gt;
&lt;li&gt;There are common elements that could be kept (the head tag, the footer)&lt;/li&gt;
&lt;li&gt;All the pages are using &lt;code&gt;_layouts/home.html&lt;/code&gt; as the layout&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  hx-boost
&lt;/h3&gt;

&lt;p&gt;From the official &lt;a href="https://dev.todocumentation"&gt;https://htmx.org/attributes/hx-boost/&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The hx-boost attribute allows you to “boost” normal anchors and form tags to use AJAX instead. This has the nice fallback that, if the user does not have javascript enabled, the site will continue to work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now the links, instead of triggering a regular GET request to the server, trigger an AJAX request and the content of the &lt;code&gt;body&lt;/code&gt; tag is the only thing refreshed when the response is received. All the common assets (css, js, fonts, images) are already loaded so&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the loading time is reduced&lt;/li&gt;
&lt;li&gt;the user experience is improved&lt;/li&gt;
&lt;li&gt;there is not flicker when the content changes&lt;/li&gt;
&lt;li&gt;the viewport automatically scrolls up when the new content is loaded&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;But there is a catch:&lt;/strong&gt; the tags in the &lt;code&gt;head&lt;/code&gt; are not updated. Title, description, OpenGraph nor Schema.org. How to solve?&lt;/p&gt;

&lt;h3&gt;
  
  
  The head-support Extension
&lt;/h3&gt;

&lt;p&gt;Again from the official &lt;a href="https://dev.todocumentation"&gt;https://htmx.org/extensions/head-support/#usage&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the htmx request is from a boosted element, then the following merge algorithm is used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elements that exist in the current head as exact textual matches will be left in place&lt;/li&gt;
&lt;li&gt;Elements that do not exist in the current head will be added at the end of the head tag&lt;/li&gt;
&lt;li&gt;Elements that exist in the current head, but not in the new head will be removed from the head&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a result just the desired tags in &lt;code&gt;head&lt;/code&gt; are updated (title, description, OpenGraph, Schema.org) and the rest stay the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  The actual changes
&lt;/h3&gt;

&lt;p&gt;Just two things where required:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;add the htmx and extension to the layout (&lt;code&gt;_layouts/home.html&lt;/code&gt;) of all the pages:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script src="https://unpkg.com/htmx.org@1.9.5" integrity="sha384-xcuj3WpfgjlKF+FXhSQFQ0ZNr39ln+hwjN3npfM9VBnUskLolQAcN80McRIVOPuO" crossorigin="anonymous"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="https://unpkg.com/htmx.org/dist/ext/head-support.js"&amp;gt;&amp;lt;/script&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;add the hx attributes to the body tag. Note that I used the &lt;code&gt;data-&lt;/code&gt; prefix for the &lt;strong&gt;hx&lt;/strong&gt; attributes in order to prevent issues with HTML validators
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body class="markdown-body" data-hx-boost="true" data-hx-ext="head-support"&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With this very simple change, the navigation and reading experience is way better.&lt;/p&gt;

&lt;p&gt;Also, as stated before, if the user don’t have JavaScript enabled, the site will continue to work with regular requests.&lt;/p&gt;

&lt;p&gt;We are loading new content using AJAX without writing a single JavaScript line.&lt;/p&gt;

&lt;p&gt;There is a lot more to say about htmx but this is enough to get started.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>New tool: Social Tags Generator</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Mon, 12 Apr 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/new-tool-social-tags-generator-i8e</link>
      <guid>https://dev.to/glpzzz/new-tool-social-tags-generator-i8e</guid>
      <description>&lt;p&gt;Check it out at &lt;a href="https://glpzzz.dev/social-tags-generator"&gt;https://glpzzz.dev/social-tags-generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://glpzzz.dev/social-tags-generator"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---tiInyNa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://glpzzz.dev/assets/2021-04-12-social-tags-generator.png" alt="glpzzz's Social Tags Generator" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Special links for our websites</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Sun, 21 Feb 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/special-links-for-our-websites-549l</link>
      <guid>https://dev.to/glpzzz/special-links-for-our-websites-549l</guid>
      <description>&lt;p&gt;Sometimes we need our links to do something else besides going to another http location. Perhaps we want to allow visitor to use other ways to interact with us using email, sms, a call, or others. Let’s se how to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Email
&lt;/h2&gt;

&lt;p&gt;Very easy! &lt;code&gt;&amp;lt;a href="mailto:me@domain.com"&amp;gt;Send me an email&amp;lt;/a&amp;gt;&lt;/code&gt; will generate an anchor that, when clicked, will tell the browser to open the application in charge of handling email on your system.&lt;/p&gt;

&lt;p&gt;More “complex” examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specify the subject: &lt;code&gt;&amp;lt;a href="mailto:me@domain.com?subject=Hello"&amp;gt;Send email&amp;lt;/a&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Specify the subject and body: &lt;code&gt;&amp;lt;a href="mailto:me@domain.com?subject=Hello&amp;amp;body=This%20is%20a%20message"&amp;gt;Send email&amp;lt;/a&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More details on &lt;a href="https://tools.ietf.org/html/rfc6068#section-6"&gt;RFC 6068 - The mailto URI Scheme&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  SMS
&lt;/h2&gt;

&lt;p&gt;A little different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just open the SMS app: &lt;code&gt;&amp;lt;a href="sms:"&amp;gt;Send SMS&amp;lt;/a&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open the SMS app for a certain number: &lt;code&gt;&amp;lt;a href="sms:+1-555-111-1111"&amp;gt;Send SMS&amp;lt;/a&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open the SMS app with custom message: &lt;code&gt;&amp;lt;a href="sms:+1-555-111-1111?body=I%20want%this%20product"&amp;gt;Request Product&amp;lt;/a&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More details on &lt;a href="https://tools.ietf.org/html/rfc5724#section-2.5"&gt;RFC 5724 - URI Scheme for Global System for Mobile Communications Short Message Service (SMS)&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phone Calls
&lt;/h2&gt;

&lt;p&gt;Same idea here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the dial app on the device: &lt;code&gt;&amp;lt;a href="tel:+1-555-111-1111"&amp;gt;Call me&amp;lt;/a&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More details on &lt;a href="https://tools.ietf.org/html/rfc3966#section-6"&gt;RFC 3966 - The tel URI for Telephone Numbers&lt;/a&gt; and in Section 8 is adviced to always enclose the phone number inside the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag, so the correct way for previous example should be something like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Call me at &amp;lt;a href="tel:+1-555-111-1111"&amp;gt;1-555-111-1111&amp;lt;a&amp;gt;.&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Locations
&lt;/h2&gt;

&lt;p&gt;If you want the link to open a map in a certain location:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;a href="geo:22.146147,-80.4426516"&amp;gt;Our Office&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More details on &lt;a href="https://tools.ietf.org/html/rfc5870#section-6.2"&gt;RFC 5870 - A Uniform Resource Identifier for Geographic Locations&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In all cases is required that your device have a correct user agent to handle this URI schemes. In PC the tel, sms, and geo will normally not work. But in smartphone the potencial of this feature is amazing. Use it!&lt;/p&gt;

</description>
      <category>html</category>
      <category>links</category>
      <category>mailto</category>
    </item>
    <item>
      <title>Modern JavaScript that Internet Explorer 11 dislikes</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Fri, 29 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/modern-javascript-that-internet-explorer-11-dislikes-1i8f</link>
      <guid>https://dev.to/glpzzz/modern-javascript-that-internet-explorer-11-dislikes-1i8f</guid>
      <description>&lt;p&gt;Yesterday I was call to fix some issues on a website I “fixed” some weeks ago. Main thing was to update the theme (Wordpress). They had a lot of old stuff, 3rd party libraries and the sort of stuff that you can expect of something written on 2017.&lt;/p&gt;

&lt;p&gt;The biggest change was migrating forms validation to checking values on change, and before submit to the native HTML5 validation techniques.&lt;/p&gt;

&lt;p&gt;And as part of the job I started to write the JavaScript code using the native features instead of jQuery or other “tricks”.&lt;/p&gt;

&lt;p&gt;Now, I have to fix some stuff again because on 2021 there is some people still using Internet Explorer 11 (IE11).&lt;/p&gt;

&lt;p&gt;Things that does not work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arrow functions 

&lt;ul&gt;
&lt;li&gt;changed to old &lt;code&gt;function()&lt;/code&gt; functions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{variable}&lt;/code&gt; interpolation 

&lt;ul&gt;
&lt;li&gt;changed to old &lt;code&gt;Array.prototype.replace()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;native &lt;code&gt;Array.prototype.forEach()&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;changed to &lt;code&gt;$.each()&lt;/code&gt; from jQuery (good in the context)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;native &lt;code&gt;String.prototype.replaceAll()&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;changed to &lt;code&gt;String.prototype.replace(RegExp, string)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list is in construction…&lt;/p&gt;

&lt;p&gt;PS: Thanks to my colleagues &lt;code&gt;epgeroy&lt;/code&gt; and &lt;code&gt;geekmidget&lt;/code&gt; for the remote debugging as I don’t have IE11 on my Ubuntu machine.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ie11</category>
      <category>jquery</category>
    </item>
    <item>
      <title>The 75% keyboard layout</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Wed, 02 Dec 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/the-75-keyboard-layout-47je</link>
      <guid>https://dev.to/glpzzz/the-75-keyboard-layout-47je</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fsk1fhcc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.redd.it/w4hr8572jcq01.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fsk1fhcc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.redd.it/w4hr8572jcq01.jpg" alt="Vortex Race 3" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a 75% keyboard, exactly the &lt;a href="https://mechanicalkeyboards.com/shop/index.php?l=product_detail&amp;amp;p=3917"&gt;Vortex Race 3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And why do I post about it? Because it’s the layout for my brand new Ajazz AK33 keyboard which I’m testing while writing this post.&lt;/p&gt;

&lt;p&gt;What’s special with this layout? Well, I’m very used to it because is the one on my Dell Inspiron 5523. As you can see in the picture It have all the keys except for the number keypad but arranged in a more compact way.&lt;/p&gt;

&lt;p&gt;So, when deciding which mechanical keyboard to buy, the safe choice was this one. Until now, the typing experience is very good: I’m getting use to the sound and to the tactile feedback. But yeah, it feels nice! Very different from the keyboard on my laptop or the external Logitech I bought and never used (impossible for me).&lt;/p&gt;

&lt;p&gt;Really I was scared. I wanted a more compact layout (there is 60% and even 45%) but the absence of arrow keys was the thing that stopped me.&lt;/p&gt;

&lt;p&gt;Let’s see if I’m more brave next time.&lt;/p&gt;

&lt;p&gt;With you, the Ajazz AK33:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wypHkSQS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://glpzzz.dev/assets/ajazz-ak33.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wypHkSQS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://glpzzz.dev/assets/ajazz-ak33.jpg" alt="My Ajazz AK33 keyboard" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to identify my public IP from Linux CLI</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Mon, 30 Nov 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/how-to-identify-my-public-ip-from-linux-cli-4gj6</link>
      <guid>https://dev.to/glpzzz/how-to-identify-my-public-ip-from-linux-cli-4gj6</guid>
      <description>&lt;p&gt;So easy!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dig +short myip.opendns.com @resolver1.opendns.com

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>How to toggle attribute values using jQuery</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Sat, 10 Oct 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/how-to-toggle-attribute-values-using-jquery-30d6</link>
      <guid>https://dev.to/glpzzz/how-to-toggle-attribute-values-using-jquery-30d6</guid>
      <description>&lt;p&gt;I just came across a very simple &lt;a href="https://stackoverflow.com/questions/64290056/how-to-use-button-action-to-toggle-between-two-states-of-a-textarea-using-jquery"&gt;question on StackOverflow&lt;/a&gt;. In the end is how to toggle the value of an attribute using jQuery.&lt;/p&gt;

&lt;h2&gt;
  
  
  The long version
&lt;/h2&gt;

&lt;p&gt;This is the explanatory version I created when the author of the question requested for an explanation of my original code. Most of the comments are obvious.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$('thebutton').click(function(){
   var currentRows = $('thetextarea').attr('rows'); //obtain the current number of rows in the textarea
   var newRows; //declare a variable to hold the new number of rows
   if(rows == 1){ //if just one...
       newRows = 5; // it should become 5
   }else{ 
       newRows = 1; //else, (not 1), become 1
   }   
   $('thetextarea').attr('rows', newRows); //assign the new value to the rows attribute of the textarea
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Short version version
&lt;/h2&gt;

&lt;p&gt;My original answer was...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//short version, the one in the answer
$('thebutton').click(function(){
   $('thetextarea').attr('rows',  $('thetextarea').attr('rows')==1?5:1);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've created a &lt;a href="https://gist.github.com/glpzzz/762afe32e8c245216869e9b1bd0aaac0"&gt;gist&lt;/a&gt; for this two versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fancy version (new for me)
&lt;/h2&gt;

&lt;p&gt;I still had the doubt if this could be done easier, and find the next way thanks to this &lt;a href="https://stackoverflow.com/questions/18665031/how-to-toggle-attr-in-jquery/18665152#18665152"&gt;answer&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$('thebutton').click(function(){
   $('thetextarea').attr('rows',  function(index, attr){
       return attr = 1 ? 5 : 1;
   });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just learnt a new thing today. I can sleep easy.&lt;/p&gt;

</description>
      <category>jquery</category>
      <category>toogle</category>
      <category>attribute</category>
    </item>
    <item>
      <title>How to redirect all emails to one inbox on Yii2 applications</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Fri, 02 Oct 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/glpzzz/how-to-redirect-all-emails-to-one-inbox-on-yii2-applications-5d9e</link>
      <guid>https://dev.to/glpzzz/how-to-redirect-all-emails-to-one-inbox-on-yii2-applications-5d9e</guid>
      <description>&lt;p&gt;&lt;a href="https://www.yiiframework.com/doc/api/2.0/yii-mail-basemailer#%24useFileTransport-detail"&gt;\yii\mail\BaseMailer::useFileTransport&lt;/a&gt; is a great tool. If you activate it, all emails sent trough this mailer will be saved (by default) on &lt;code&gt;@runtime/mail&lt;/code&gt;instead of being sent, allowing the devs to inspect thre result.&lt;/p&gt;

&lt;p&gt;But what happens if we want to actually receive the emails on our inboxes. When all emails are suppose to go to one account, there is no problem: setup it as a param and the modify it in the &lt;code&gt;params-local.php&lt;/code&gt; (assuming advaced application template).&lt;/p&gt;

&lt;p&gt;The big issue arises when the app is supposed to send emails to different accounts and make use of replyTo, cc and bcc fields. It’s almost impossible try to solve it with previous approach and without using a lot of &lt;code&gt;if(YII_DEBUG)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Well, next there is a solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'useFileTransport' =&amp;gt; true,
'fileTransportCallback' =&amp;gt; function (\yii\mail\MailerInterface $mailer, \yii\mail\MessageInterface $message) {
    $message-&amp;gt;attachContent(json_encode([
            'to' =&amp;gt; $message-&amp;gt;getTo(),
            'cc' =&amp;gt; $message-&amp;gt;getCc(),
            'bcc' =&amp;gt; $message-&amp;gt;getBcc(),
            'replyTo' =&amp;gt; $message-&amp;gt;getReplyTo(),
        ]), ['fileName' =&amp;gt; 'metadata.json', 'contentType' =&amp;gt; 'application/json'])
        -&amp;gt;setTo('debug@mydomain.com') // account to receive all the emails
        -&amp;gt;setCc(null)
        -&amp;gt;setBcc(null)
        -&amp;gt;setReplyTo(null);

    $mailer-&amp;gt;useFileTransport = false;
    $mailer-&amp;gt;send($message);
    $mailer-&amp;gt;useFileTransport = true;

    return $mailer-&amp;gt;generateMessageFileName();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How it works? &lt;code&gt;fileTransportCallback&lt;/code&gt; is the callback to specify the filename that should be used to create the saved email on &lt;code&gt;@runtime/mail&lt;/code&gt;. It “intercepts” the send email process, so we can use it for our porpuses.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attach a json file with the real recipients information so we can review it&lt;/li&gt;
&lt;li&gt;Set the recipient (TO) as the email address where we want to receive all the emails.&lt;/li&gt;
&lt;li&gt;Set the others recipients fields as null&lt;/li&gt;
&lt;li&gt;Deactivate &lt;code&gt;useFileTransport&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Send the email&lt;/li&gt;
&lt;li&gt;Activate &lt;code&gt;useFileTransport&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Return the defaut file name (datetime of the operation)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This way we both receive all the emails on the specified account and get them stored on &lt;code&gt;@runtime/mail&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pretty simple helper to review emails on Yii2 applications.&lt;/p&gt;

</description>
      <category>yii2</category>
      <category>email</category>
      <category>debug</category>
      <category>smtp</category>
    </item>
    <item>
      <title>Answer: CURL call is working fine directly in CURL but not in PHP 7.3</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Sat, 26 Sep 2020 00:29:50 +0000</pubDate>
      <link>https://dev.to/glpzzz/answer-curl-call-is-working-fine-directly-in-curl-but-not-in-php-7-3-2ifi</link>
      <guid>https://dev.to/glpzzz/answer-curl-call-is-working-fine-directly-in-curl-but-not-in-php-7-3-2ifi</guid>
      <description>&lt;p&gt;How to know why CURL is not working? Very easy:&lt;/p&gt;


&lt;div class="ltag__stackexchange--container"&gt;
  &lt;div class="ltag__stackexchange--title-container"&gt;
    
      &lt;div class="ltag__stackexchange--title"&gt;
        &lt;div class="ltag__stackexchange--header"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AoTUKOcU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/stackoverflow-logo-b42691ae545e4810b105ee957979a853a696085e67e43ee14c5699cf3e890fb4.svg" alt=""&gt;
          &lt;a href="https://stackoverflow.com/questions/64071385/curl-call-is-working-fine-directly-in-curl-but-not-in-php-7-3/64072213#64072213" rel="noopener noreferrer"&gt;
            &lt;span class="title-flare"&gt;answer&lt;/span&gt; re: CURL call is working fine directly in CURL but not in PHP 7.3
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="ltag__stackexchange--post-metadata"&gt;
          &lt;span&gt;Sep 25 '20&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;a class="ltag__stackexchange--score-container" href="https://stackoverflow.com/questions/64071385/curl-call-is-working-fine-directly-in-curl-but-not-in-php-7-3/64072213#64072213" rel="noopener noreferrer"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oeieW07A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/stackexchange-arrow-up-eff2e2849e67d156181d258e38802c0b57fa011f74164a7f97675ca3b6ab756b.svg" alt=""&gt;
        &lt;div class="ltag__stackexchange--score-number"&gt;
          1
        &lt;/div&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h2-sXgSn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/stackexchange-arrow-down-4349fac0dd932d284fab7e4dd9846f19a3710558efde0d2dfd05897f3eeb9aba.svg" alt=""&gt;
      &lt;/a&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--body"&gt;
    
&lt;p&gt;You can use&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$info = curl_getinfo($ch);
$error = curl_error($ch);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to see what happened.&lt;/p&gt;

    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--btn--container"&gt;
    &lt;a href="https://stackoverflow.com/questions/64071385/curl-call-is-working-fine-directly-in-curl-but-not-in-php-7-3/64072213#64072213" class="ltag__stackexchange--btn" rel="noopener noreferrer"&gt;Open Full Answer&lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>php</category>
      <category>curl</category>
    </item>
    <item>
      <title>Answer: How to toggle value in database on click of a button (YII2)</title>
      <dc:creator>Gabriel Alejandro López López</dc:creator>
      <pubDate>Fri, 25 Sep 2020 05:16:45 +0000</pubDate>
      <link>https://dev.to/glpzzz/answer-how-to-toggle-value-in-database-on-click-of-a-button-yii2-1olf</link>
      <guid>https://dev.to/glpzzz/answer-how-to-toggle-value-in-database-on-click-of-a-button-yii2-1olf</guid>
      <description>&lt;div class="ltag__stackexchange--container"&gt;
  &lt;div class="ltag__stackexchange--title-container"&gt;
    
      &lt;div class="ltag__stackexchange--title"&gt;
        &lt;div class="ltag__stackexchange--header"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AoTUKOcU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/stackoverflow-logo-b42691ae545e4810b105ee957979a853a696085e67e43ee14c5699cf3e890fb4.svg" alt=""&gt;
          &lt;a href="https://stackoverflow.com/questions/63825099/how-to-toggle-value-in-database-on-click-of-a-button-yii2/63878491#63878491" rel="noopener noreferrer"&gt;
            &lt;span class="title-flare"&gt;answer&lt;/span&gt; re: How to toggle value in database on click of a button (YII2)
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="ltag__stackexchange--post-metadata"&gt;
          &lt;span&gt;Sep 14 '20&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;a class="ltag__stackexchange--score-container" href="https://stackoverflow.com/questions/63825099/how-to-toggle-value-in-database-on-click-of-a-button-yii2/63878491#63878491" rel="noopener noreferrer"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oeieW07A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/stackexchange-arrow-up-eff2e2849e67d156181d258e38802c0b57fa011f74164a7f97675ca3b6ab756b.svg" alt=""&gt;
        &lt;div class="ltag__stackexchange--score-number"&gt;
          3
        &lt;/div&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h2-sXgSn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/stackexchange-arrow-down-4349fac0dd932d284fab7e4dd9846f19a3710558efde0d2dfd05897f3eeb9aba.svg" alt=""&gt;
      &lt;/a&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--body"&gt;
    
&lt;p&gt;This is just a soft delete then: no actual row is deleted but "marked". Two parts for this code:&lt;/p&gt;
&lt;p&gt;Controller&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
public function behaviors()
{
    return [
        //
        'verbs' =&amp;gt; [
            'class' =&amp;gt; \yii\filters\VerbFilter::className(),
            'actions' =&amp;gt; [
                'delete' =&amp;gt; ['POST'],
            ],
        ],
        // ....
    ];
}


public function actionDelete($id){
    $model&lt;/code&gt;&lt;/pre&gt;…
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--btn--container"&gt;
    &lt;a href="https://stackoverflow.com/questions/63825099/how-to-toggle-value-in-database-on-click-of-a-button-yii2/63878491#63878491" class="ltag__stackexchange--btn" rel="noopener noreferrer"&gt;Open Full Answer&lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;


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