Typically, you would do something like this with query builder.
$users = User::query()
->where('email', 'LIKE', $email)
->orWhere('username', 'LIKE', $email)
->first();
This works, but in a recent release of Laravel, a new method called whereAll
and whereAny
were introduced. These methods allow you to compare a value against multiple columns more concisely.
Here’s how you can rewrite the previous example using whereAny
.
$users = User::whereAny(['email', 'username'], 'LIKE', $email)
->first();
This essentially adds a “where” clause to the query for multiple columns with “or” conditions between them. In this case, it’s checking if the email or username is like the given value.
You can also use whereAll
to compare a value against multiple columns with “and” conditions between them.
$users = User::whereAll(['email', 'username'], 'LIKE', $email)
->first();
This is a small change, but it can make your code more readable and concise. It’s a nice addition to the query builder and can be quite helpful when you need to compare a value against multiple columns in the database.
]]>Matt Kingshott recently shared an interesting trick that can help you delete millions of records from the database efficiently.
Here’s how you can do it.
use App\Models\User;
$query = User::where('created_at', '<=', now()->subDays(30));
while ($query->exists()) {
$query->limit(5000)->delete();
sleep(3);
}
Essentially, the code above deletes 5000 records at a time and then sleeps for 3 seconds. And it continues to do so until there are no more records to delete.
This approach doesn’t make the database to fall over and it’s a lot more efficient than deleting all the records at once. I think this is genius and can be pretty helpful when you’re dealing with large datasets.
]]>This is where environment-aware favicons come into play. They help you distinguish between the environments by changing the favicon of the website based on the environment.
Josh Comeau recently tweeted about this idea and I found it quite interesting. He shared how he implemented this feature in his Next-powered blog with App Router. This is what it looks like.
He kept the light favicon for the local environment and the dark favicon for the production environment.
Here’s what the app/icon.tsx
file looks like in his blog.
import { readFile } from 'fs/promises';
import { NextResponse } from 'next/server';
export default async function Icon() {
try {
const image = await readFile(
process.env.NODE_ENV === 'production'
? './public/favicon.png'
: './public/favicon-dev.png'
);
return new NextResponse(image, {
headers: {
'Content-Type': 'image/png',
},
});
} catch (error) {
return new NextResponse('Internal Server Error', { status: 500 });
}
}
As you can tell, the code is pretty straightforward. It reads the favicon.png
file in the production environment and favicon-dev.png
in the development environment using the process.env.NODE_ENV
variable. And then, it returns the image as a response.
It’s pretty simple to implement in other frameworks as well. For instance, in Laravel, you can use the following code to achieve the same.
Route::get('/favicon.ico', function () {
$favicon = file_get_contents(
app()->environment('production')
? public_path('favicon.ico')
: public_path('favicon-dev.ico')
);
return response($favicon)
->header('Content-Type', 'image/x-icon');
});
I think this is a really cool feature to have configured on your website. It’s a small detail but it can make a big difference in making the development workflow less confusing.
]]>Essentially, the video explains how you can create a dynamic progress bar purely using conic gradients in CSS. Yep! No JavaScript is needed at all.
The end result will look something like this.
As you can tell, the blue line around the circle shows the progress of the video which is denoted by the number in the middle.
Let’s see how you can create this.
First, let’s create a simple HTML structure for our progress bar.
<div class="progress">01</div>
Now, let’s style it using CSS.
.progress {
width: 100px;
height: 100px;
border-radius: calc(infinity * 1px);
font-family: sans-serif;
display: flex;
align-items: center;
justify-content: center;
background-color: red;
}
This will create a simple red circle with the text “01” in the middle.
Now, we need to change the background color to a conic gradient. Here’s how you can do it.
.progress {
/* code commented for brevity */
background: conic-gradient(
red 50%,
transparent 50%,
);
}
This will create a conic gradient that is 50% red and 50% transparent. This will create a half-filled circle with the red color.
See the Pen Progress Bars with Conic Gradients by Amit Merchant (@amit_merchant) on CodePen.
To make it how we want, we need to put a child element inside the .progress
element which will be a circle but with a slightly smaller size (than the parent) and a gray background. This will create an illusion of a progress bar around the circle.
Here’s how you can do it.
<div class="progress">
<div class="number">01</div>
</div>
And here’s the CSS for the same.
.progress .number {
background: #e3e3e3;
width: 93%;
height: 93%;
color: var(--color, 'red');
border-radius: inherit;
margin: auto;
display: flex;
align-items: center;
justify-content: center;
}
As you can tell, we moved the centering styles to the .number
class and also added a --color
variable which will be used to change the color of the progress bar dynamically.
See the Pen Progress Bars with Conic Gradients - Part 2 by Amit Merchant (@amit_merchant) on CodePen.
We will also make the percentage dynamic using CSS variables. Here’s how you can do it.
.progress {
/* code commented for brevity */
background: conic-gradient(
var(--color, 'red') calc(var(--percentage, 1) * 1%),
transparent calc(var(--percentage, 1)* 1%)
);
}
Finally, to make the percentage and the progress color dynamic, you can change the --percentage
and --color
variables in the .progress
element using inline styles.
<div class="progress" style="--percentage: 75;--color: blue;">
<div class="number">01</div>
</div>
The percentages (and the color) can easily be changed in the HTML or dynamically using JavaScript or server-side rendering techniques.
The ability to change the progress bar color can help maintain a consistent color scheme throughout your application.
And that’s it! You’ve created a dynamic progress bar using only CSS.
Here’s the final code for the same. Go ahead and change the --percentage
and --color
variables to see the progress bar in action.
See the Pen Progress Bars with Conic Gradients by Amit Merchant (@amit_merchant) on CodePen.
If you prefer to watch the video, here’s the original video by Jeffery Way.
Attributes are great when you want to attach data to your classes that can be seen “at a glance” while still being able to access them programmatically.
You can read more about PHP 8’s Attributes in this article where I explained their inner workings and how you can use them in your code.
There are a couple of new features in Laravel 10.x now make use of this feature.
These are:
In this article, we’ll see how we can define these using PHP’s Attributes in Laravel.
Observers in Laravel are classes that listen for specific events on Eloquent models. They are used to group all the event listeners for a model into a single class.
Traditionally, you would define a model observer like so.
namespace App\Observers;
class UserObserver
{
public function creating(User $user)
{
//
}
}
And then you would attach this observer to the model like so.
use App\Observers\UserObserver;
class User extends Model
{
public function boot(): void
{
User::observe(UserObserver::class);
}
}
But with PHP 8’s Attributes, you can define the observer like so.
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use App\Observers\UserObserver;
#[ObservedBy(UserObserver::class)]
class User extends Model
{
//
}
As you can tell, Laravel provides an ObservedBy
attribute that you can use to define the observer for the model. You can pass the observer class to the ObservedBy
attribute.
So, now you don’t need to define the boot
method in the model to attach the observer. You can do it directly using the ObservedBy
attribute.
Global scopes allow you to add constraints to all queries for a given model.
Traditionally, you would define a global scope like so.
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
class AgeScope
{
public function apply(Builder $builder, $model)
{
$builder->where('age', '>', 30);
}
}
And then you would attach this global scope to the model like so.
use App\Scopes\AgeScope;
class User extends Model
{
protected static function booted()
{
static::addGlobalScope(new AgeScope);
}
}
PHP’s Attributes simplify this process.
With PHP 8’s Attributes, you can define the global scope like so.
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
use App\Scopes\AgeScope;
#[ScopedBy(AgeScope::class)]
class User extends Model
{
//
}
As you can tell, Laravel provides a ScopedBy
attribute that you can use to define the global scope for the model. You can pass the global scope class to the ScopedBy
attribute.
You can even pass multiple global scopes to the ScopedBy
attribute like so.
#[ScopedBy([AgeScope::class, CountryScope::class])]
So, now you don’t need to define the booted
method in the model to attach the global scope. You can do it directly using the ScopedBy
attribute.
I think Attributes help reduce a lot of boilerplate code and make the code more readable and maintainable. I love how Laravel is embracing PHP 8’s new features and making the development experience even better.
]]>only
method in Laravel Collections that allows you to retrieve a subset of the items from the collection?
For instance, if you have an array of data like so.
$collection = collect([
'name' => 'Amit',
'age' => 30,
'city' => 'Surat',
'country' => 'India'
]);
You can use the only
method to retrieve a subset of the items from the collection like so.
$filtered = $collection->only(['name', 'age']);
// ['name' => 'Amit', 'age' => 30]
Well, there’s a new method called select
in Laravel Collections that does the same thing as the only
method but for array of arrays.
For instance, if you have an array of arrays like so.
$collection = collect([
['name' => 'Amit', 'age' => 30, 'country' => 'India'],
['name' => 'John', 'age' => 25, 'country' => 'USA'],
['name' => 'Jane', 'age' => 35, 'country' => 'UK'],
]);
Now, if you want to retrieve a subset of the items, for example, name
and country
from the collection, you can use the select
method like so.
$filtered = $collection->select(['name', 'country']);
/*
[
['name' => 'Amit', 'country' => 'India'],
['name' => 'John', 'country' => 'USA'],
['name' => 'Jane', 'country' => 'UK'],
]
*/
For most of the commands, you can get the help page by passing the --help
option to the command. For instance, if you want to see the help page for the pwd
command, you can do so by running the following command.
pwd --help
This will show a description of the pwd
command along with the options it supports. But the problem with this is that the help page is usually very long and hard to parse. It’s just a wall of text.
The other way to get the help page is to use the man (short for manuals) command. For instance, if you want to see the help page for the pwd
command, you can do so by running the following command.
man pwd
Similar to the --help
option, this will also show a description of the pwd
command along with the options it supports. The format is kind of similar to the --help
option but it’s still not very user-friendly.
So, is there a better way to get the help pages for commands in the terminal? Yes, there is. It’s called tldr
.
tldr
to the rescuetldr is a simplified and community-driven help page for commands. This is a part of the tldr-pages project which shows popular commands with practical examples so you don’t have to look at the long and boring blob of text.
The best thing about tldr
is that it’s available for almost all platforms. The most common way to install tldr
is via npm. You can install it by running the following command.
npm install -g tldr
In my case, I installed it using Homebrew on Ubuntu.
brew install tldr
Once installed, you can use tldr
to get the help pages for commands. For instance, if you want to see the help page for the pwd
command, you can do so by running the following command.
tldr pwd
Here’s how the help page for the pwd
command looks like.
As you can tell, the help page is much more user-friendly and nicely structured format. You get examples of that command along with a short description of what it does. Everything is color-coded. So, it makes it much easier to understand.
Here’s what man pwd
looks like for comparison.
tldr
is not just limited to the usual commands. It also supports a wide range of commands including the development tools like git
, npm
, docker
, etc. So, you can use tldr
to get help pages for these commands as well.
For instance, if you want to see the help page for the docker
command, you can do so by running the following command.
tldr docker
Here’s how the help page for the docker
command looks like.
Or about Composer which is a dependency manager for PHP.
tldr composer
Here’s how the help page for the composer
command looks like.
I think tldr
is a great tool to have in your arsenal if you’re working with the terminal. It makes a great alternative to the traditional help pages and makes it much easier to understand the commands and their options. Give it a try and see if it fits your workflow.
We don’t have a Mac either so that option is also out of the equation. So, we were kinda stuck! But then I stumbled upon this seemingly “perfect solution” for our scenario recently that ended our misery. It’s an open-source app called LocalSend.
As the name suggests, LocalSend is a local file transfer tool that allows you to securely send files (and folders and text) from one device to another over your local network without the need for an internet connection. It uses RESTful API and HTTP encryption to transfer files between devices.
The best thing about LocalSend is that it’s cross-platform. It’s available on any platform you can think of. Be it Android, iOS, Windows, macOS, Linux, and even Fire OS.
The app is also very easy to use. You just need to install the app on both devices and then the app will automatically detect the devices on the same network and then you can start transferring files between them.
As you can tell, the app has a very minimalistic yet functional UI. The native apps available for Android and iOS follow the same design language which is a good thing.
The app assigns a random name to your device when you first install it but you can change this from the settings. You can also configure other things like the app theme, destination folder, app language, and more from the settings.
I think go, give LocalSend a try if you’re in a similar situation as mine. It’s certainly a tool that will be in my arsenal from now on.
]]>Dumpable
trait.
The Illuminate\Support\Traits\Dumpable
trait is a new trait that’s being introduced in Laravel 11. The trait provides dd
and dump
methods to the class where it’s being used.
This is particularly useful when you want to fluently call the dd
or dump
method directly on the object without having to use the dump
/dd
helper functions.
Here’s how you can use it.
use Illuminate\Support\Traits\Dumpable;
class User
{
use Dumpable;
public function __construct()
{
$this->name = 'Amit';
}
public function getName()
{
return $this->name;
}
}
$user = new User;
$user->getName()->dump();
$user->getName()->dd();
As you may presume, the main benefit this trait will bring is that the Laravel package authors can now leverage this trait to provide a better debugging experience to the users of their packages. This will also make the debugging process more convenient and intuitive.
]]>Essentially, the sticky scroll feature in the File Tree allows you to keep the opened folder in the view while you scroll through the files. This is particularly useful when you have a large number of files in a folder and you want to keep the folder in the view for the context while you scroll through the files.
The feature is not enabled by default. So, to enable this feature, you need to go to the settings and search for Tree: Enable Sticky Scroll
and enable it. Once enabled, you can see the sticky scroll in action.
Alternatively, you can also enable it by adding the following line to your settings.json
file.
"workbench.tree.enableStickyScroll": true,
Here’s how it looks in action.
]]>