Make Your Excel Spreadsheets Smarter With Dropdown Lists

https://static1.makeuseofimages.com/wordpress/wp-content/uploads/2024/08/a-computer-screen-showing-dropdown-lists-in-excel-alongisde-the-excel-logo.jpg

Dropdown lists are the secret weapon against data inconsistency and typos, making data entry easier and more accurate. Despite their power, they’re often overlooked in Excel’s UI, leaving many users missing out on their benefits. Ready to make your spreadsheets smarter? Here’s how you can use dropdown lists in Excel

How to Create Dropdown Lists in Excel

Excel’s dropdown lists are rightly categorized under the Data Validation tab, as they not only streamline data entry but also enhance the reliability of your formulas.

For this example, we’ll use a task tracker with a Status column that provides dropdown lists for each task. The list items will include Not Started, In Progress, Completed, and Blocked.

Unlike Google Sheets, Excel requires the list values to exist somewhere in your workbook. To avoid cluttering your task tracker, it’s best to create a separate sheet to store these values. Once the dropdown lists are created, you can hide the cells or the entire sheet to keep your tracker tidy.

Here’s how to set up the dropdown list:

  1. Prepare your list values by entering the list items (e.g., Not Started, In Progress, Completed, Blocked) in a column on a separate sheet.
  2. Highlight the cells where you want the dropdown lists to appear (e.g., B2:B5).
  3. Go to the Data tab on the ribbon, then click Data Validation in the Data Tools section.
  4. In the Data Validation window, select List under the Allow dropdown.
  5. Click the upward arrow in the Source field, and select the range containing your list items.
  6. Click OK to apply the dropdown list to the selected cells.

The selected cells should now display a dropdown arrow, allowing you to choose from the predefined items.

How to Customize Excel Dropdown Lists

While your dropdown list is functional, it may not look as visually appealing as you’d like, especially if you’re used to the colorful dropdowns in Google Sheets. Fortunately, with a touch of Excel’s conditional formatting, you can enhance the appearance of your dropdown list in Excel.

To apply conditional formatting to your dropdown list, follow these steps:

  1. Highlight the cells with dropdown lists (e.g., B2:B5).
  2. Go to the Home tab, click Conditional Formatting, and select New Rule.
  3. In the New Formatting Rule window, choose Format only cells that contain.
  4. In the rule description, set the first dropdown to Specific Text and leave the second field as is.
  5. Enter the text you want to format (e.g., Completed).
  6. Click Format next to the preview. In the Format Cells window, set the Font color to white, go to the Fill tab, and choose a deep green color for the background.
  7. Click OK twice to apply the rule.

Now, any task marked as Completed will have a green background, making it easy to identify at a glance. Repeat these steps for the other list items and assign each a unique color. This will significantly improve visual clarity.

Dropdown lists eliminate the risk of typos and variations—no more Complete vs. Finished vs. Done. This consistency is crucial when analyzing data with formulas; for instance, if a formula tracks Completed tasks, it will miss tasks marked as Finished.

Now with your dropdown lists in place, your Excel sheet is not only easier to use but also primed for advanced data analysis. You can filter tasks by status, such as showing only In Progress tasks, or use the COUNTIF function to count how many tasks are Blocked.

MakeUseOf

Laravel Model Tips

https://picperf.io/https://laravelnews.s3.amazonaws.com/featured-images/laravel-model-tips.png

Laravel Model Tips

Laravel provides a huge amount of cool features that help improve our development experience (DX). But with the regular releases, stresses of day-to-day work, and the vast amount of features available, it’s easy to miss some of the lesser-known features that can help improve our code.

In this article, I’m going to cover some of my favourite tips for working with Laravel models. Hopefully, these tips will help you write cleaner, more efficient code and help you avoid common pitfalls.

Spotting and Preventing N+1 Issues

The first tip we’ll look at is how to spot and prevent N+1 queries.

N+1 queries are a common issue that can occur when lazy loading relationships, where N is the number of queries that are run to fetch the related models.

But what does this mean? Let’s take a look at an example. Imagine we want to fetch every post from the database, loop through them, and access the user that created the post. Our code might look something like this:

$posts = Post::all();

foreach ($posts as $post) {
    // Do something with the post...

    // Try and access the post's user
    echo $post->user->name;
}

Although the code above looks fine, it’s actually going to cause an N+1 issue. Say there are 100 posts in the database. On the first line, we’ll run a single query to fetch all the posts. Then inside the foreach loop when we’re accessing $post->user, this will trigger a new query to fetch the user for that post; resulting in an additional 100 queries. This means we’d run 101 queries in total. As you can imagine, this isn’t great! It can slow down your application and put unnecessary strain on your database.

As your code becomes more complex and features grow, it can be hard to spot these issues unless you’re actively looking out for them.

Thankfully, Laravel provides a handy Model::preventLazyLoading() method that you can use to help spot and prevent these N+1 issues. This method will instruct Laravel to throw an exception whenever a relationship is lazy-loaded, so you can be sure that you’re always eager loading your relationships.

To use this method, you can add the Model::preventLazyLoading() method call to your App\Providers\AppServiceProvider class:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}

Now, if we were to run our code from above to fetch every post and access the user that created the post, we’d see an Illuminate\Database\LazyLoadingViolationException exception thrown with the following message:

Attempted to lazy load [user] on model [App\Models\Post] but lazy loading is disabled.

To fix this issue, we can update our code to eager load the user relationship when fetching the posts. We can do this by using the with method:

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // Do something with the post...

    // Try and access the post's user
    echo $post->user->name;
}

The code above will now successfully run and will only trigger two queries: one to fetch all the posts and one to fetch all the users for those posts.

Prevent Accessing Missing Attributes

How often have you tried to access a field that you thought existed on a model but didn’t? You might have made a typo, or maybe you thought there was a full_name field when it was actually called name.

Imagine we have an App\Models\User model with the following fields:

  • id
  • name
  • email
  • password
  • created_at
  • updated_at

What would happen if we ran the following code?:

$user = User::query()->first();
    
$name = $user->full_name;

Assuming we don’t have a full_name accessor on the model, the $name variable would be null. But we wouldn’t know whether this is because the full_name field actually is null, because we haven’t fetched the field from the database, or because the field doesn’t exist on the model. As you can imagine, this can cause unexpected behaviour that can sometimes be difficult to spot.

Laravel provides a Model::preventAccessingMissingAttributes() method that you can use to help prevent this issue. This method will instruct Laravel to throw an exception whenever you try to access a field that doesn’t exist on the current instance of the model.

To enable this, you can add the Model::preventAccessingMissingAttributes() method call to your App\Providers\AppServiceProvider class:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventAccessingMissingAttributes();
    }
}

Now if we were to run our example code and attempt to access the full_name field on the App\Models\User model, we’d see an Illuminate\Database\Eloquent\MissingAttributeException exception thrown with the following message:

The attribute [full_name] either does not exist or was not retrieved for model [App\Models\User].

An additional benefit of using preventAccessingMissingAttributes is that it can highlight when we’re trying to read a field that exists on the model but that we might not have loaded. For example, let’s imagine we have the following code:

$user = User::query()
    ->select(['id', 'name'])
    ->first();

$user->email;

If we have prevented missing attributes from being accessed, the following exception would be thrown:

The attribute [email] either does not exist or was not retrieved for model [App\Models\User].

This can be incredibly useful when updating existing queries. For example, in the past, you may have only needed a few fields from a model. But maybe you’re now updating the feature in your application and need access to another field. Without having this method enabled, you might not realise that you’re trying to access a field that hasn’t been loaded.

It’s worth noting that the preventAccessingMissingAttributes method has been removed from the Laravel documentation (commit), but it still works. I’m not sure of the reason for its removal, but it’s something to be aware of. It might be an indication that it will be removed in the future.

Prevent Silently Discarding Attributes

Similar to preventAccessingMissingAttributes, Laravel provides a preventSilentlyDiscardingAttributes method that can help prevent unexpected behaviour when updating models.

Imagine you have an App\Models\User model class like so:

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    protected $fillable = [
        'name',
        'email',
        'password',
    ];
    
    // ...
}

As we can see, the name, email, and password fields are all fillable fields. But what would happen if we tried to update a non-existent field on the model (such as full_name) or a field that exists but isn’t fillable (such as email_verified_at)?:

$user = User::query()->first();

$user->update([
    'full_name' => 'Ash', // Field does not exist
    'email_verified_at' => now(), // Field exists but isn't fillable
    // Update other fields here too...
]);

If we were to run the code above, both the full_name and email_verified_at fields would be ignored because they haven’t been defined as fillable fields. But no errors would be thrown, so we would be unaware that the fields have been silently discarded.

As you’d expect, this could lead to hard-to-spot bugs in your application, especially if any other in your "update" statement were in fact updated. So we can use the preventSilentlyDiscardingAttributes method which will throw an exception whenever you try to update a field that doesn’t exist on the model or isn’t fillable.

To use this method, you can add the Model::preventSilentlyDiscardingAttributes() method call to your App\Providers\AppServiceProvider class:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventSilentlyDiscardingAttributes();
    }
}

The above would force an error to be thrown.

Now if we were to try and run our example code from above and update the user’s first_name and email_verified_at fields, an Illuminate\Database\Eloquent\MassAssignmentException exception would be thrown with the following message:

Add fillable property [full_name, email_verified_at] to allow mass assignment on [App\Models\User].

It’s worth noting that the preventSilentlyDiscardingAttributes method will only highlight unfillable fields when you’re using a method such as fill or update. If you’re manually setting each property, it won’t catch these errors. For example, let’s take the following code:

$user = User::query()->first();

$user->full_name = 'Ash';
$user->email_verified_at = now();

$user->save();

In the code above, the full_name field doesn’t exist in the database, so rather than Laravel catching it for us, it would be caught at the database level. If you were using a MySQL database, you’d see an error like this:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'full_name' in 'field list' (Connection: mysql, SQL: update `users` set `email_verified_at` = 2024-08-02 16:04:08, `full_name` = Ash, `users`.`updated_at` = 2024-08-02 16:04:08 where `id` = 1)

Enable Strict Mode for Models

If you’d like to use the three methods that we’ve mentioned so far, you can enable them all at once using the Model::shouldBeStrict() method. This method will enable the preventLazyLoading, preventAccessingMissingAttributes, and preventSilentlyDiscardingAttributes settings.

To use this method, you can add the Model::shouldBeStrict() method call to your App\Providers\AppServiceProvider class:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::shouldBeStrict();
    }
}

This is the equivalent of:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
        Model::preventSilentlyDiscardingAttributes();
        Model::preventAccessingMissingAttributes();
    }
}

Similar to the preventAccessingMissingAttributes method, the shouldBeStrict method has been removed from the Laravel documentation (commit) but still works. This might be an indication that it will be removed in the future.

Using UUIDs

By default, Laravel models use auto-incrementing IDs as their primary key. But there may be times when you’d prefer to use universally unique identifiers (UUIDs).

UUIDs are 128-bit (or 36-character) alphanumeric strings that can be used to uniquely identify resources. Due to how they’re generated, it’s highly unlikely that they’ll collide with another UUID. An example UUID is: 1fa24c18-39fd-4ff2-8f23-74ccd08462b0.

You may want to use a UUID as the primary key for a model. Or, you might want to keep your auto-incrementing IDs for defining relationships within your application and database, but use UUIDs for public-facings IDs. Using this approach can add an extra layer of security by making it harder for attackers to guess the IDs of other resources.

For example, say we are using auto-incrementing IDs in a route. We might have a route for accessing a user like so:

use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::get('/users/{user}', function (User $user) {
    dd($user->toArray());
});

An attacker could loop through the IDs (e.g. – /users/1, /users/2, /users/3, etc.) in an attempt to try and access other users’ information if the routes aren’t secure. Whereas if we used UUIDs, the URLs might look more like /users/1fa24c18-39fd-4ff2-8f23-74ccd08462b0, /users/b807d48d-0d01-47ae-8bbc-59b2acea6ed3, and /users/ec1dde93-c67a-4f14-8464-c0d29c95425f. As you can imagine, these are much harder to guess.

Of course, just using UUIDs isn’t enough to protect your applications, they’re just an additional step you can take to improve the security. You need to make sure you’re also using other security measures like rate limiting, authentication, and authorization checks.

Use UUIDs as the Primary Key

We’ll first start by looking at how to change the primary key to UUIDs.

To do this, we’ll need to make sure our table has a column that’s capable of storing UUIDs. Laravel provides a handy $table->uuid method that we can use in our migrations.

Imagine we have this basic migration that creates a comments table:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->uuid();
            $table->foreignId('user_id');
            $table->foreignId('post_id');
            $table->string('content');
            $table->timestamps();
        });
    }

    // ...
}

As we can see in the migration, we’ve defined a UUID field. By default, this field will be called uuid, but you can change this by passing a column name to the uuid method if you’d like.

We then need to instruct Laravel to use the new uuid field as the primary key for our App\Models\Comment model. We also need to add a trait that will allow Laravel to generate UUIDs automatically for us. We can do this by overriding the $primaryKey property on our model and using the Illuminate\Database\Eloquent\Concerns\HasUuids trait:

namespace App\Models;

use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    use HasUuids;

    protected $primaryKey = 'uuid';
}

The model should now be configured and ready to use UUIDs as the primary key. Take this example code:

use App\Models\Comment;
use App\Models\Post;
use App\Models\User;

$user = User::first();
$post = Post::first();

$comment = new Comment();
$comment->content = 'The comment content goes here.';
$comment->user_id = $user->id;
$comment->post_id = $post->id;
$comment->save();

dd($comment->toArray());

// [
//     "content" => "The comment content goes here."
//     "user_id" => 1
//     "post_id" => 1
//     "uuid" => "9cb16a60-8c56-46f9-89d9-d5d118108bc5"
//     "updated_at" => "2024-08-05T11:40:16.000000Z"
//     "created_at" => "2024-08-05T11:40:16.000000Z"
// ]

We can see in the dumped model that the uuid field has been populated with a UUID.

Add a UUID Field to a Model

If you’d prefer to keep your auto-incrementing IDs for internal relationships but use UUIDs for public-facing IDs, you can add a UUID field to your model.

We’ll assume your table has id and uuid fields. Since we’ll be using the id field as the primary key, we won’t need to define the $primaryKey property on our model.

We can override the uniqueIds method that’s made available via the Illuminate\Database\Eloquent\Concerns\HasUuids trait. This method should return an array of the fields that should have UUIDs generated for them.

Let’s update our App\Models\Comment model to include the field that we’ve called uuid:

namespace App\Models;

use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    use HasUuids;

    public function uniqueIds(): array
    {
        return ['uuid'];
    }
}

Now if we were to dump a new App\Models\Comment model, we’d see that the uuid field has been populated with a UUID:

// [
//     "id" => 1
//     "content" => "The comment content goes here."
//     "user_id" => 1
//     "post_id" => 1
//     "uuid" => "9cb16a60-8c56-46f9-89d9-d5d118108bc5"
//     "updated_at" => "2024-08-05T11:40:16.000000Z"
//     "created_at" => "2024-08-05T11:40:16.000000Z"
// ]

We’ll take a look later in this article at how you can update your models and routes to use these UUIDs as your public-facing IDs in your routes.

Using ULIDs

Similar to using UUIDs in your Laravel models, you may sometimes want to use universally unique lexicographically sortable identifiers (ULIDs).

ULIDs are 128-bit (or 26-character) alphanumeric strings that can be used to uniquely identify resources. An example ULID is: 01J4HEAEYYVH4N2AKZ8Y1736GD.

You can define ULID fields in the exact same as you would UUID fields. The only difference is that instead of updating your model to use the Illuminate\Database\Eloquent\Concerns\HasUuids trait, you should use the Illuminate\Database\Eloquent\Concerns\HasUlids trait.

For example, if we wanted to update our App\Models\Comment model to use ULIDs as the primary key, we could do so like this:

namespace App\Models;

use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    use HasUlids;
}

Changing the Field Used for Route Model Binding

You’ll likely already know what route model binding is. But just in case you don’t, let’s quickly go over it.

Route model binding allows you to automatically fetch instances of models based on data passed to your Laravel app’s routes.

By default, Laravel will use your model’s primary key field (typically an id field) for route model binding. For example, you might have a route for displaying the information for a single user:

use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::get('/users/{user}', function (User $user) {
    dd($user->toArray());
});

The route defined in the example above will attempt to find a user that exists in the database with the provided ID. For example, let’s say a user with an ID of 1 exists in the database. When you visit the URL /users/1, Laravel will automatically fetch the user with an ID of 1 from the database and pass it to the closure function (or controller) for acting on. But if a model doesn’t exist with the provided ID, Laravel will automatically return a 404 Not Found response.

But there may be times when you’d like to use a different field (other than your primary key) to define how a model is retrieved from the database.

For example, as we’ve previously mentioned, you may want to use auto-incrementing IDs as your model’s primary keys for internal relationships. But you might want to use UUIDs for public-facing IDs. In this case, you might want to use the uuid field for route model binding instead of the id field.

Similarly, if you’re building a blog, you may want to fetch your posts based on a slug field instead of the id field. This is because a slug field is more human-readable and SEO-friendly than an auto-incrementing ID.

Changing the Field for All Routes

If you’d like to define the field that should be used for all routes, you can do so by defining a getRouteKeyName method on your model. This method should return the name of the field you’d like to use for route model binding.

For example, imagine we want to change all route model binding for an App\Models\Post model to use the slug field instead of the id field. We can do this by adding a getRouteKeyName method to our Post model:

namespace App\Models;

use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    public function getRouteKeyName()
    {
        return 'slug';
    }

    // ...
}

This means we could now define our routes like so:

use App\Models\Post;
use Illuminate\Support\Facades\Route;

Route::get('/posts/{post}', function (Post $post) {
    dd($post->toArray());
});

And when we visit the URL /posts/my-first-post, Laravel will automatically fetch the post with a slug of my-first-post from the database and pass it to the closure function (or controller) for acting on.

Changing the Field for Single Routes

However, there may be times when you only want to change the field used in a single route. For example, you might want to use the slug field for route model binding in one route, but the id field in all other routes.

We can do this by using the :field syntax in our route definition. For example, let’s say we want to use the slug field for route model binding in a single route. We can define our route like so:

Route::get('/posts/{post:slug}', function (Post $post) {
    dd($post->toArray());
});

This now means in this specific route, Laravel will attempt to fetch the post with the provided slug field from the database.

Use Custom Model Collections

When you fetch multiple models from the database using a method such as App\Models\User::all(), Laravel will typically put them inside an instance of the Illuminate\Database\Eloquent\Collection class. This class provides a lot of useful methods for working with the returned models. However, there may be times when you want to return a custom collection class instead of the default one.

You might want to create a custom collection for a few reasons. For instance, you might want to add some helper methods that are specific to dealing with that type of model. Or, maybe you want to use it for improved type safety and be sure that the collection will only contain models of a specific type.

Laravel makes it really easy to override the type of collection that should be returned.

Let’s take a look at an example. Let’s imagine we have an App\Models\Post model and when we fetch them from the database, we want to return them inside an instance of a custom App\Collections\PostCollection class.

We can create a new app/Collections/PostCollection.php file and define our custom collection class like so:

declare(strict_types=1);

namespace App\Collections;

use App\Models\Post;
use Illuminate\Support\Collection;

/**
 * @extends Collection<int, Post>
 */
class PostCollection extends Collection
{
    // ...
}

In the example above, we’ve created a new App\Collections\PostCollection class that extends Laravel’s Illuminate\Support\Collection class. We’ve also specified that this collection will only contain instances of the App\Models\Post class using the docblock. This is great for helping your IDE understand the type of data that will be inside the collection.

We can then update our App\Models\Post model to return an instance of our custom collection class by overriding the newCollection method like so:

namespace App\Models;

use App\Collections\PostCollection;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    // ...

    public function newCollection(array $models = []): PostCollection
    {
        return new PostCollection($models);
    }
}

In the example, we’ve taken the array of App\Models\Post models that are passed to the newCollection method and returned a new instance of our custom App\Collections\PostCollection class.

Now we can fetch our posts from the database using our custom collection class like so:

use App\Models\Post;

$posts = Post::all();

// $posts is an instance of App\Collections\PostCollection

Comparing Models

A common issue that I see when working on projects is how models are compared. This is usually within authorization checks when you want to check whether a user can access a resource.

Let’s look at some of the common gotchas and why you should probably avoid using them.

You should avoid using === when checking if two models are the same. This is because the === check, when comparing objects, will check if they are the same instance of the object. This means that even if two models have the same data, they won’t be considered the same if they are different instances. So you should avoid doing this, as it will likely return false.

Assuming a post relationship exists on an App\Models\Comment model and that the first comment in the database belongs to the first post, let’s look at an example:

// ⚠️ Avoid using `===` to compare models

$comment = \App\Models\Comment::first();
$post = \App\Models\Post::first();

$postsAreTheSame = $comment->post === $post;

// $postsAreTheSame will be false.

You should also avoid using == when checking if two models are the same. This is because the == check, when comparing objects, will check if they are an instance of the same class and if they have the same attributes and values. However, this can lead to unexpected behaviour.

Take this example:

// ⚠️ Avoid using `==` to compare models

$comment = \App\Models\Comment::first();
$post = \App\Models\Post::first();

$postsAreTheSame = $comment->post == $post;

// $postsAreTheSame will be true.

In the example above, the == check will return true because $comment->post and $post are the same class and have the same attributes and values. But what would happen if we changed the attributes in the $post model so they were different?

Let’s use the select method so we only grab the id and content fields from the posts table:

// ⚠️ Avoid using `==` to compare models

$comment = \App\Models\Comment::first();
$post = \App\Models\Post::query()->select(['id', 'content'])->first();

$postsAreTheSame = $comment->post == $post;

// $postsAreTheSame will be false.

Even though $comment->post is the same model as $post, the == check will return false because the models have different attributes loaded. As you can imagine, this can lead to some unexpected behaviour that can be pretty difficult to track down, especially if you’ve retrospectively added the select method to a query and your tests start failing.

Instead, I like to use the is and isNot methods that Laravel provides. These methods will compare two models and check they belong to the same class, have the same primary key value, and have the same database connection. This is a much safer way to compare models and will help to reduce the likelihood of unexpected behaviour.

You can use the is method to check if two models are the same:

$comment = \App\Models\Comment::first();
$post = \App\Models\Post::query()->select(['id', 'content'])->first();

$postsAreTheSame = $comment->post->is($post);

// $postsAreTheSame will be true.

Similarly, you can use the isNot method to check if two models are not the same:

$comment = \App\Models\Comment::first();
$post = \App\Models\Post::query()->select(['id', 'content'])->first();

$postsAreNotTheSame = $comment->post->isNot($post);

// $postsAreNotTheSame will be false.

Use whereBelongsTo When Building Queries

This last tip is more of a personal preference, but I find that it makes my queries easier to read and understand.

When attempting to fetch models from the database, you might find yourself writing queries that filter based on relationships. For example, you might want to fetch all comments that belong to a specific user and post:

$user = User::first();
$post = Post::first();

$comments = Comment::query()
    ->where('user_id', $user->id)
    ->where('post_id', $post->id)
    ->get();

Laravel provides a whereBelongsTo method that you can use to make your queries more readable (in my opinion). Using this method, we could rewrite the query above like so:

$user = User::first();
$post = Post::first();

$comments = Comment::query()
    ->whereBelongsTo($user)
    ->whereBelongsTo($post)
    ->get();

I like this syntactic sugar and feel like it makes the query more human-readable. It’s also a great way to ensure that you’re filtering based on the correct relationship and field.

You, or your team, may prefer to use the more explicit approach of writing out the where clauses. So this tip might not be for everyone. But I think as long as you’re consistent with your approach, either way is perfectly fine.

Conclusion

Hopefully, this article should have shown you some new tips for working with Laravel models. You should now be able to spot and prevent N+1 issues, prevent accessing missing attributes, prevent silently discarding attributes, and change the primary key type to UUIDs or ULIDs. You should also know how to change the field used for route model binding, specify the type of collection returned, compare models, and use whereBelongsTo when building queries.


The post Laravel Model Tips appeared first on Laravel News.

Join the Laravel Newsletter to get all the latest
Laravel articles like this directly in your inbox.

Laravel News

New Ryobi Cordless Butt Warmer!

https://i0.wp.com/toolguyd.com/blog/wp-content/uploads/2024/08/Ryobi-USB-Lithium-Heated-Cushion-Used-by-Construction-Worker.jpg?resize=600%2C450&ssl=1

Ryobi USB Lithium Heated Cushion Used by Construction Worker

Ryobi is about to launch a new battery-powered cordless butt warmer!

Officially called a Heated Cushion Kit, the new tush heater (model FVT51K) will be part of their USB lithium line of cordless tools and accessories.

The Ryobi heated seat warmer features 3 temperature settings and up to 5 hours or charge on 2x 2Ah batteries set to low.

Ryobi USB Lithium Heated Cushion Used at Stadium

It measures 3″ thick, for padded comfort in different environments, from jobsites to bleacher seats.

Ryobi USB Lithium Heated Cushion X-Ray View

Ryobi says that the cordless heated cushion can a temperature of up to 150°.

Ryobi USB Lithium Heated Cushion Power Pack

The included power pack works with 2x Ryobi Lithium USB batteries and has a built-in fuel gauge. It looks like there’s also a hole for a lanyard strap.

Ryobi USB Lithium Heated Cushion Power Pack Battery Configuration

Here are expected runtimes for the 3 temperature settings when the cushion is powered by 2x 2Ah batteries:

  • High (150°) – 2 hours
  • Medium (130°) – 3.5 hours
  • Low (110°) – 5 hours
Ryobi USB Lithium Heated Cushion and Power Pack Charging Phone

The power adapter has a USB-C output and doubles as a mobile device charger.

Ryobi USB Lithium Heated Cushion Kit FVT51K

The kit comes with the heated cushion, power pack, 2x 2Ah batteries, and a charging cable.

Price: $89
ETA: October 2024

The heated seat warmer will be available exclusively at Home Depot.

Discussion

A heated butt warmer…??

Makita Cordless Heated Jacket DCB200A Worn Over Pants

It’s not exactly unprecedented. Makita was first to tackle this type of product, with their heated blanket.

Ryobi’s new heated cushion makes sense. I wonder if it’s suitable for use in other environments, outside of broad jobsites, tailgating, and stadiums, such as outdoors for camping.

Will its 2-5 hrs runtime be a downside?

This looks to be Ryobi’s first dual battery USB Lithium product, and one big question comes to mind – what else might the new mobile-charging-capable power back be used for?

ToolGuyd

Receive inbound email with Laravel

https://opengraph.githubassets.com/2305774d1659683786b6e15037504edf7c06cfafa867d39ae79ad7ef401b55f1/proxied-mail/laravel-receive-email

ProxiedMail Client | Receive email via webhook Laravel

ProxiedMail 👷‍♀️ is a simple package for the base library to create proxy emails and receive webhooks or simply browse email list.
You can find the base PHP library at https://github.com/proxied-mail/proxiedmail-php-client

You’re welcome to visit the docs.

ProxiedMail is a tool that brings the email experience to a new level because it was built around the privacy first concept that enhances using a unique email each time which makes it a second password, but also allows you more control over your correspondence.
Additionally, it gives you the advantage of moving to another email provider just in a few seconds.
Because we have this kind of system we also aim to bring more into the experience of development using emails.

🛠 Creating endless proxy emails with one of ProxiedMail domains (i.e abc@proxiedmail.com, abcd@pxdmail.com, abcde@pxdmail.net)

🛠 Setting up forwarding email or disabling forwarding

🛠 Setting up a callback to your URL

🛠 Browsing received emails on the received emails endpoint

🛠 Setting up custom domains. You can do everything using your domain as well.

🛠 Domain-to-domain forwarding. Just in case you need it we can forward emails by mask, like *@domainhostedatproxiedmail.com -> *someotherdomain.com. In this case, the MX of the first domain should be pointed to ProxiedMail and the second domain should be verified by TXT record.

Via composer

$ composer require proxiedmail/laravel-receive-email

This package provide auto-discovery for service provider

If Laravel package auto-discovery is disabled, add service providers manually to /config/app.php. There are service provider you must add:

\ProxiedMail\Client\Providers\ProxiedMailServiceProvider::class

Publish client configuration:

php artisan vendor:publish --tag=proxiedmail

Configure ProxiedMail client:

Put your ProxiedMail API token in /config/proxiedmail.php. You can find this token in ProxiedMail API Settings.

return [
    'apiToken' => 'YOUR API TOKEN',
    'host' => 'https://proxiedmail.com',
];

This example demonstrates create proxy emails, browse received emails and receive emails via webhook.

use ProxiedMail\Client\Bridge\ProxiedMailClient;
use ProxiedMail\Client\Facades\ApiFacade;

class ExampleController
{
    public function browseReceivedEmails(ProxiedMailClient $proxiedMailClient)
    {
        /**
 * @var ApiFacade $api
 */
        $api = $proxiedMailClient->getClient();

        $proxyEmail = $api->createProxyEmail(
            [],
            null,
            null,
            null,
            true
        );


        // while (true) with 100 seconds limit
        foreach (range(0, 180) as $non) {
            echo "PROXY-EMAIL: " . $proxyEmail->getProxyAddress() . "\n";
            echo "Time limit is 3 mins \n";
            echo "Send the email to this proxy-email to get email payload printed here \n";

            //checking webhook receiver

            $receivedEmails = $api->getReceivedEmailsLinksByProxyEmailId($proxyEmail->getId())->getReceivedEmailLinks();
            echo "Amount of received emails: " . count($receivedEmails) . "\n";
            foreach ($receivedEmails as $receivedEmail) {
                echo "Have received email: \n";
                var_dump($receivedEmail);

                echo "\n";
            }

            echo "\n";

            sleep(1);
        }
    }


    public function receiveEmailViaWebhook(ProxiedMailClient $proxiedMailClient)
    {
        /**
 * @var ApiFacade $api
 */
        $api = $proxiedMailClient->getClient();

        $wh = $api->createWebhook(); //creating webhook-receiver
        $proxyEmail = $api->createProxyEmail(
            [],
            null,
            $wh->getCallUrl() //specifying webhook url
        );


        // while (true) with 100 seconds limit
        foreach (range(0, 100) as $non) {
            echo "PROXY-EMAIL: " . $proxyEmail->getProxyAddress() . "\n";
            echo "Send the email to this proxy-email to get email payload printed here";

            //checking webhook receiver
            $whStatus = $api->statusWebhook($wh->getId());

            echo "Webhook STATUS: \n";
            echo "Received: " . ($whStatus->isReceived() ? 'yes' : 'no') . "\n"; //printing webhook status

            //printing payload if received
            if ($whStatus->isReceived()) {
                echo "WEBHOOK PAYLOAD: \n";
                echo json_encode($whStatus->getPayload());
                break;
            }


            echo "\n";

            sleep(1);
        }
    }
}

You can create find the UI on ProxiedMail to manage your domains, emails, and webhooks.

Please feel free to fork and sending Pull Requests. This project follows Semantic Versioning 2 and PSR-2.

GPL3. Please see License File for more information.

For any questions please contact laraclient@pxdmail.com

Also please check out the article how to receive emails in Laravel in our blog.
If you’re interested in receiving emails in PHP use the library for pure PHP.

Article: how to receive emails in PHP

Laravel News Links

How to Tie a Lasso

https://content.artofmanliness.com/uploads/2024/08/Tie-a-Lasso-2.jpg

What man hasn’t imagined what it would be like to be a cowboy on the open range?

And when you think about being a cowboy, you probably imagine yourself swinging a lasso above your head to round up wayward dogies

The lasso, or lariat, that we know today originated with Mexican vaqueros back in the 18th and 19th centuries. In the fluid social world of the American West, American cowboys picked up the lasso from their Mexican counterparts to aid them in their own cow punching.

North America isn’t the only place where the lasso has been used. Ancient Egyptians and Mongolians used lassos to herd animals, and ancient Persian warriors employed them in battle.

Yes, the lasso is indeed a manly implement. And today we’re going to show you how to tie one.

At the heart of every lasso is the honda knot. It’s a knot that creates a small, secure loop through which you pass the rope in order to create a large loop that can be tightened and loosened easily.

The rope you use for lassos needs to be a bit stiff so that the loop maintains its shape when you throw it. Traditionally, lassos were made with stiff rawhide or manila rope (check out our article on rope material!). Today, cowboys use nylon or polyester ropes which offer great durability.

Follow our illustrated guide and soon you’ll be ready to hit the Lonesome Dove trail with Gus and Woodrow.

Help support independent publishing. Make a donation to The Art of Manliness! Thanks for the support!

The Art of Manliness

Block Known Spam IPs from Your Laravel App with the Abuse IP Package

https://picperf.io/https://laravelnews.s3.amazonaws.com/featured-images/laravel-abuse-ip-featured.png

Block Known Spam IPs from Your Laravel App with the Abuse IP Package

The Laravel Abuse IP community package by Rahul Alam adds a layer of protection to your Laravel application from known spam IPs. This package provides an Artisan command to keep your IP list in sync with the Aggregated AbuseIPDB blocklist and middleware to check requests against the list.

To start using this package, you need sync the blocklist file of IPs. If you run your application on multiple servers, your storage drive will need to be centralized, or you’ll need to sync and store the IP list data on each server.

Next, the package’s AbuseIp middleware will check requests against the block list to prevent IPs on the list from accessing your application. To configure this middleware, you can add it to your Laravel project’s bootstrap/app.php file or add it to routes directly as desired:

->withMiddleware(function (Middleware $middleware) {
    $middleware->append(\App\Http\Middleware\AbuseIp::class);
});

// Or via an individual route (or group of routes)
Route::middleware(AbuseIp::class)->get('/', function () {
    return view('welcome');
});

The AbuseIPDB list is updated multiple times a day, so you’ll also want to schedule an update to the blocklist (which is then cached) to run daily:

$schedule->command('abuseip:update')->daily();

You are free to update the source of the IP blocklist via the package’s configuration. You can learn more about this package, get full installation instructions, and view the source code on GitHub.


The post Block Known Spam IPs from Your Laravel App with the Abuse IP Package appeared first on Laravel News.

Join the Laravel Newsletter to get all the latest
Laravel articles like this directly in your inbox.

Laravel News

DIY PVC Slingbow

https://theawesomer.com/photos/2024/08/diy_pvc_slingbow_t.jpgMaker Lis X has created some interesting weapons using unconventional materials. He used PVC tubing to build the frame for this unique slingbow and provided step-by-step directions so you can make your own. It&#8217;s designed to fire arrows and has a sturdy handgrip underneath for stability and aiming accuracy. Here&#8217;s another video showing it in [&#8230;]The Awesomer

Rebel Ridge (Trailer)

https://theawesomer.com/photos/2024/08/rebel_ridge_trailer_t.jpg(PG-13: Language) A man on his way to post bail for his cousin is assaulted and robbed by the local police themselves. Unfortunately for the crooked cops, their &#8220;victim&#8221; is a former Marine, and they&#8217;re about to reenact Rambo. Writer and director Jeremy Saulnier may have cooked a sleeper in this thrilling action flick. Premieres [&#8230;]The Awesomer