Naguel

I'm Nahuel, and these are my work experiences, ideas and thoughts as a web developer working on the eCommerce industry.

Create and apply a patch in Magento

Create and apply a patch in Magento

Magento usually has bugs (thank you, Captain Obvious) after the release of a version, that are later corrected on subsequent releases (known issues).

Using patches to change core files in Magento is not a bad practice when the goal behind it is to bring core fixes existing on newer versions to the one we have running, avoiding so a full upgrade.

How to apply a patch

I'm starting the other way around as applying a patch might be more common than actually creating one, specially because Magento itself releases patches for its own platform, third-party vendors release patches for their extensions, and the community also makes patches for others to use.

There's a well known Composer package named cweagans/composer-patches that handles the patches and applies them to the original Magento modules every time you run composer install and/or composer update.

Technically speaking, this tool installs all Composer packages required, then removes the Magento modules affected by the patches we are including, and re-install those modules with the code changes applied.

➜  ~ composer install
Gathering patches from patch file.
Removing package magento/module-customer so that it can be re-installed and re-patched.
  - Removing magento/module-customer (102.0.5)
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 1 install, 0 updates, 0 removals
Gathering patches from patch file.
Gathering patches for dependencies. This might take a minute.
  - Installing magento/module-customer (102.0.5): Loading from cache
  - Applying patches for magento/module-customer
    patches/composer/magento/module-customer/22952.patch (#22952 - Delegated account creation fails with custom attributes present in customer address)

For making this happen, first you need to add your .patch file in the patches/composer/magento/[module-name]/ folder (relative to the Magento root, at the same level your composer.json file lives).

The name of the .patch file doesn't really matter, but I personally like to use the number of the GitHub issue where the known issue was discussed, if that even exists. Otherwise, any descriptive name would do.

For the [module-name] folder name use the Composer package name containing the files you are patching.

As an example, the Composer package name for the Magento_Customer module is module-customer. This information is on the composer.json file of each package, inside the vendor folder.

Finally, on the root composer.json file, inside the extra node create the patches node and define the patch to apply as the following example.

"extra": {
    "composer-exit-on-patch-failure": true,
    "patches": {
        "magento/module-customer": {
            "#22952 - Delegated account creation fails with custom attributes present in customer address": "patches/composer/magento/module-customer/22952.patch"
        }
    }
}

See that I'm adding a description to what the patch does, and the GitHub issue number, followed by the relative path to the .patch file itself.

How to create a patch

Identify the core file you would like to change using a patch.

For the sake of an example, I'm going to patch the vendor/magento/module-customer/Model/Address.php file to apply a fix for the "Delegated account creation fails with custom attributes present in customer address" issue reported in the magento/magento2 repo itself.

Create an exact copy of the file, and make all the necessary changes.

If you are using PhpStorm, you can create a "scratch file" to hold any code temporary, like a draft, by pressing CMD + Shift + N.

Comparison between the original file and the one with the changes

Output the changes into a .patch file using the diff command on the Terminal while standing in the root of your Magento.

➜  ~ diff -Naur path/to/old/file.php path/to/new/file.php > example.patch

Following my example, I need to execute the following...

~ diff -Naur vendor/magento/module-customer/Model/Address.php /Users/nahuelsanchez/Library/Application\ Support/JetBrains/PhpStorm2021.1/scratches/scratch_113.php > example.patch

...in order to get my example.patch file.

My example.patch file generated before any manual intervention

Unfortunately, here's when we need to perform some manual intervention on the generated example.patch file.

First, remove the date and time appearing the end of the first two lines.

Second, you can see that the first path is the real path to the original file living in the vendor folder. Add a a/ prefix to it.

Third, replace the second path with the first path, but using the b/ prefix instead.

Fourth, and finally, add a new line on top of everything with diff --git a/vendor/core/file.php b/vendor/core/file.php.

Before and after the manual intervention on my example.patch file

Do not touch anything else there, not even the empty lines at the end (if any).

The resulting file ready to be used as a patch should look as the following example:

diff --git a/vendor/magento/module-customer/Model/Address.php b/vendor/magento/module-customer/Model/Address.php
--- a/vendor/magento/module-customer/Model/Address.php
+++ b/vendor/magento/module-customer/Model/Address.php
@@ -159,7 +159,9 @@
         $customAttributes = $address->getCustomAttributes();
         if ($customAttributes !== null) {
             foreach ($customAttributes as $attribute) {
-                $this->setData($attribute->getAttributeCode(), $attribute->getValue());
+                if (isset($attribute)) {
+                    $this->setData($attribute->getAttributeCode(), $attribute->getValue());
+                }
             }
         }

Lazyload post Feature Image from Unsplash in Ghost

Lazyload post Feature Image from Unsplash in Ghost

Unsplash is a great Ghost built-in integration that allows you to quickly add an image to your posts, and I personally use it every time to add the Feature Image to all my articles (the big one below the title, before the content).

Unfortunately, out of the box the image from Unsplash is really big (2000px wide) and impacts on the page speed of the site since the browser will download the image first then continue with the rest of the page.

There's no much we can do about the image size as we can't follow the "How to use responsive images in Ghost themes" official guide because that only applies to images you manually upload and not those coming from third-parties...

Dynamic image sizes are not compatible with externally hosted images. If you insert images from Unsplash or you store your image files on a third party storage adapter then the image url returned will be determined by the external source.

...but with a little bit of HTML and JavaScript we can lazy load them to prioritize the content over the image download.

Usually, the Feature Image in the Ghost theme will look something like:

<img src="{{feature_image}}" />

This is a classic img tag with the src containing the URL of the image. But we need to do some changes here first before moving to the JS side of this technique.

In the src we are going to put a placeholder image to avoid having a broken image while the rest of the page loads, we are going to move the actual image to the data-src attribute, and finally we'll add a new class to the element.

<img src="{{asset "images/placeholder.png"}}" data-src="{{feature_image}}" class="lazyload" />

The placeholder image should be a small image in terms of weight. I'm using an image with a solid colour of 183 bytes so I can "reserve" the space of the final Feature Image to avoid "jumps" in the browser while everything loads.

Finally, the JS is quite simple. We need to wait for the window to be loaded, get all the img elements with the lazyload class, and replace the src with what's on the data-src so we trigger the actual image download.

window.addEventListener('load', (event) => {
    let images = document.getElementsByClassName('lazyload');

    for (let i = 0; i < images.length; i++) {
        images[i].src = images[i].dataset.src;
    }
});

With this in place we should see that the content is prioritized over the Unsplash image, and if we are using a placeholder we should see that first in the "Network" tab of our browser's DevTools, with the actual image loading later.

Having a successfully work from home lifestyle

Having a successfully work from home lifestyle

This is the new normal, get used to it and get ready, because what's now (somehow still) a benefit from a company will be a requirement in the not too distant future. I wouldn't be surprised if working from home becomes a skill on a job offer rather than a perk.

Imagine listing on your resume not only your English level but also your work from home seniority.

All the lockdowns imposed around the globe due to the Covid-19 situation forced companies into a WFH scheme where everybody went remote from day to night.

I think this is here to stay in a combination of remote working and office space, resulting on a true flexible work from home scheme, because this is not only better for the employee but also cheaper for a company (no more rent?).

No more bs against working from home thanks to a pandemic
Companies were forced to reorganize quickly to continue working with their employees from home: the bs around this was cut immediately, the scepticism towards having people working from their homes disappeared. It had too, there was no other option.

I had the luxury of a WFH benefit on my last job and now, for the past two years, I became a full time remote employee to a London-based eCommerce agency so I sort of know how to work from home, and I don't see myself ever again going to an office Monday to Friday, so here's my take with three aspects on how to nail working from home.

Your space in the house

My first ever mistake (and probably everybody's first ever mistake) when I started to work from home everyday was to use the same table where I ate as my desk too.

The problem is not the table itself and the fact that the Mac shares it with a slice of pizza, but the inner feeling of being always on the same place, always, all the time, when working and when not doing it.

So even if you disconnect from Slack or close the lid, you are always at your working station, which is not good (mentally speaking).

Having a room in your house as the office is the main recommendation somebody could give you when diving into the work from home culture because it will easily allow you to "call it a day" when you have to, the same way you picked up your things from your desk at the company building and returned home.

Sometimes you'll need to isolate from the rest of the house when living with somebody else, on situations like having to concentrate on a task or having a Zoom meeting so here's where a door will come at handy, or some noise-cancelling headphones.

This leads us to having a set of house rules for all the house members for when work is happening, because not everybody is used to this work from home scheme and there was no reason at all until now to be aware of this new normal and having somebody in the house that now works from it.

For example, I tend to announce that I'm going to start a meeting, and that's enough for me. But you can set other rules too, like "Headphones means no interruptions", or guidelines for when the office door is closed.

Surely, I understand that having a spare room to be used as an office is usually a luxury, I'm no idiot.

For example, I rented my current place with this objective in mind, and I'm sure this will be something that's going to be considered, in the future, for when renting and/or moving.

But, still, there's always something you can do to mentally disconnect from work when you are done with it.

If you can't have a separate room, you maybe can have a specific place in the house to work, which is not the table where you eat. Like a small desk on the dinner or living room, that you know you use only for working.

Even if there's no physical space to do so, and you are forced no matter what to use the dinner table for working, then you can rely on environment settings to differentiate working hours from free time (like lighting).

Finally, something that works when there's no office room in the house is to close the computer and save it on a drawer, as a big gesture to call it a day.

A routine to avoid burnouts

One of the main problems of working from one, that we already mentioned as partially solvable by having a dedicated physical space to work, is the feeling of being on a constant work mode, on a state where work and life get mixed together and there's no clear differentiation between one and the other.

Having to go to an office imposed, at some capacity, a routine that you had to follow like waking up at a specific hour, having to take a shower for the sake of respecting your coworkers, having breakfast, etcetera.

Now you have to set your own routine, which is easy, and follow it, which is not.

This starts with having to follow regular hours every day, a routine. For example, I have set on my smartwatch reminders to have breakfast and lunch, which is a way to avoid losing track of time when I'm working.

Even if I do not actually follow them on a day because "I'm too busy" or because "I need to finish this first", it's a way to take awareness of "when are we".

You don't need to actually get up hours before work to take a shower, that clearly can be done later, but you shouldn't get up a minute before checking in at work. Allow you at least 15 minutes of being up and running before sitting on your desk.

I know that stay in bed for as much as we can is temping, and it's a clear benefit of working from home. But that's the benefit of not commuting, that's from where we gain sleeping hours.

So, 15 minutes of sleep won't make you any difference, but having 15 minutes for you before starting to work results on being more awake, therefore rested, through the entire day.

For a better working day, work on having a better wake up routine.

You don't have to have breakfast before work, that doesn't have to necessarily be part of your wake up routine, but instead you can have it later, during work, as a break.

Pause work during working hours to have breakfast? Isn't that against the rules? Please! When you were at the office you had some water cooler moments, or stop by the desk of a coworker to have some chat about whatever, or you made yourself five cups of coffee.

You had your breaks at the office and it's fine to have them now at home.

Call it a day

Avoid falling into an eternal working state of mind, or workaholism, is what you will be constantly fighting while working for home if you don't train yourself to be better at remote working.

Stop working is part of being good at it.

If the company you work for doesn't care for time tracking, you should track your time anyway, for yourself, to be aware of how much are you spending at work. And, as if you were going to an office, you should call it a day at some point, and don't work until the next day.

At the company I work for we have a Slack reminder with some stuff before we go, which also works as a reminder of what time is it (the same as the use of an alarm or the reminders I already mentioned I have on my smartwatch).

And when it's time to go. Go. No, really, go. Whatever it is, with the exception of an emergency, can be continued tomorrow... or next week.

If you can go out after calling it a day, even better. Leaving home is very good to clear your mind, even if it's for a short walk or for having a moment at a coffee store (which is my thing).


Working from home was always a luxury I can see becoming the new normal after this big social experiment we all suffered due to the pandemic.

Internet is full of tips and tricks on how to succeed at working from home. You just need to find those that suit you and get on with it.