https://i.ytimg.com/vi/eTxRz1Z1cGI/maxresdefault.jpgHere, we will be looking at 3 new things that are added to the latest version of Laravel which is v9.36.0Laravel News Links
Laravel’s Safety Mechanisms
https://planetscale.com/images/blog/content/laravel-safety-mechanisms/laravel-safety-mechanisms-social.png
Laravel is a mature PHP web application framework with built-in support for almost everything modern applications need. But we’re not going to cover all of those features here! Instead, we’ll look at a topic that doesn’t get talked about nearly enough: Laravel’s many safety features that can help prevent painful mistakes.
We’ll take a look at the following safety mechanisms:
Each of these protections is configurable, and we’ll recommend how and when to configure them.
Many ORMs, Eloquent included, offer a “feature“ that allows you to lazy load a model’s relationship. Lazy loading is convenient because you don’t have to think upfront about which relationships to select from the database, but it often leads to a performance nightmare known as the “N+1 problem.”
The N+1 problem is one of the most common problems people run into when using an ORM, and it’s often a reason people cite for avoiding ORMs altogether. That’s a bit of an overcorrection, as we can simply disable lazy loading altogether!
Imagine a naive listing of blog posts. We’ll show the blog’s title and the author’s name.
$posts = Post::all();
foreach($posts as $post) {
// `author` is lazy loaded.
echo $post->title . ' - ' . $post->author->name;
}
This is an example of the N+1 problem! The first line selects all of the blog posts. Then, for every single post, we run another query to get the post’s author.
SELECT * FROM posts;
SELECT * FROM users WHERE user_id = 1;
SELECT * FROM users WHERE user_id = 2;
SELECT * FROM users WHERE user_id = 3;
SELECT * FROM users WHERE user_id = 4;
SELECT * FROM users WHERE user_id = 5;
The “N+1“ notation comes from the fact that an additional query is run for each of the n-many records returned by the first query. One initial query plus n-many more. N+1.
Even though each individual query is probably quite fast, in aggregate, you can see a huge performance penalty. And because each individual query is fast, this isn’t something that would show up in your slow query log!
With Laravel, you can use the preventLazyLoading
method on the Model
class to disable lazy loading altogether. Problem solved! Truly, it is that simple.
You can add the method in your AppServiceProvider
:
use Illuminate\Database\Eloquent\Model;
public function boot()
{
Model::preventLazyLoading();
}
Every attempt to lazy load a relationship will now throw a LazyLoadingViolationException
exception. Instead of lazy loading, you’ll need to explicitly eager load your relationships.
// Eager load the `author` relationship.
$posts = Post::with('author')->get();
foreach($posts as $post) {
// `author` is already loaded.
echo $post->title . ' - ' . $post->author->name;
}
Lazy loading relationships does not affect the correctness of your application, merely the performance of it. Ideally, all the relations you need are eager loaded, but if not, it simply falls through and lazy loads the required relationships.
For that reason, we recommend disallowing lazy loading in every environment except production. Hopefully, all lazy loads will be caught in local development or testing, but in the rare case that a lazy load makes its way into production, your app will continue to work just fine, if a bit slower.
To prevent lazy loading in non-production environments, you can add this to your AppServiceProvider
:
use Illuminate\Database\Eloquent\Model;
public function boot()
{
// Prevent lazy loading, but only when the app is not in production.
Model::preventLazyLoading(!$this->app->isProduction());
}
If you want to log errant lazy loading in production, you can register your own lazy load violation handler using the static handleLazyLoadingViolationUsing
method on the Model class.
In the example below, we will disallow lazy loading in every environment, but in production, we log the violation rather than throwing an exception. This ensures that our application continues to work as intended, but we can go back and fix our lazy load mistakes.
use Illuminate\Database\Eloquent\Model;
public function boot()
{
// Prevent lazy loading always.
Model::preventLazyLoading();
// But in production, log the violation instead of throwing an exception.
if ($this->app->isProduction()) {
Model::handleLazyLoadingViolationUsing(function ($model, $relation) {
$class = get_class($model);
info("Attempted to lazy load [{$relation}] on model [{$class}].");
});
}
}
In almost every book about SQL, one of the performance recommendations that you’ll see is to “select only the columns that you need.” It’s good advice! You only want the database to fetch and return the data that you’re actually going to use because everything else is simply discarded.
Until recently, this has been a tricky (and sometimes dangerous!) recommendation to follow in Laravel.
Laravel’s Eloquent models are an implementation of the active record pattern, where each instance of a model is backed by a row in the database.
To retrieve the user with an ID of 1, you can use Eloquent’s User::find()
method, which runs the following SQL query:
SELECT * FROM users WHERE id = 1;
Your model will be fully hydrated, meaning that every column from the database will be present in the in-memory model representation:
$user = User::find(1);
// -> SELECT * FROM users where id = 1;
// Fully hydrated model, every column is present as an attribute.
// App\User {#5522
// id: 1,
// name: "Aaron",
// email: "aaron@example.com",
// is_admin: 0,
// is_blocked: 0,
// created_at: "1989-02-14 08:43:00",
// updated_at: "2022-10-19 12:45:12",
// }
Selecting all of the columns, in this case, is probably fine! But if your users
table is extremely wide, has LONGTEXT
or BLOB
columns, or you’re selecting hundreds or thousands of rows, you probably want to limit the columns to just the ones you plan on using.
You can control which columns are selected using the select
method, which leads to a partially hydrated model. The in-memory model contains a subset of attributes from the row in the database.
$user = User::select('id', 'name')->find(1);
// -> SELECT id, name FROM users where id = 1;
// Partially hydrated model, only some attributes are present.
// App\User {
// id: 1,
// name: "Aaron",
// }
Here’s where things get dangerous.
If you access an attribute that was not selected from the database, Laravel simply returns null
. Your code will think an attribute is null
, but really it just wasn’t selected from the database. It might not be null
at all!
In the following example, a model is partially hydrated with only id
and name
, then the is_blocked
attribute is accessed further down. Because is_blocked
was never selected from the database, the attribute’s value will always be null
, treating every blocked user as if they aren’t blocked.
// Partially hydrate a model.
$user = User::select('id', 'name')->find(1);
// is_blocked was not selected! It will always be `null`.
if ($user->is_blocked) {
throw new \Illuminate\Auth\Access\AuthorizationException;
}
This exact example probably (probably) wouldn’t happen, but when data retrieval and usage are spread across multiple files, something like this will happen. There is no warning anywhere that a model is partially hydrated, and as requirements evolve, you may end up accessing attributes that were never loaded.
With extreme care and 100% test coverage, you might be able to prevent this from ever happening, but it’s still a loaded gun pointed straight at your foot. For that reason, we’ve recommended never modifying the SELECT
statement that populates an Eloquent model.
Until now!
The release of Laravel 9.35.0 brings us a new safety feature to prevent this from happening.
In 9.35.0 you can call Model::preventAccessingMissingAttributes()
to prevent accessing attributes that were not loaded from the database. Instead of returning null
, an exception will be thrown, and everything will grind to a halt. This is a very good thing.
You can enable this new behavior by adding this to your AppServiceProvider
:
use Illuminate\Database\Eloquent\Model;
public function boot()
{
Model::preventAccessingMissingAttributes();
}
Notice that we enabled this protection across the board, regardless of environment! You could enable this protection only in local development, but the most important place for it to be enabled is production.
Unlike N+1 protection, preventing access to missing attributes is not a performance issue, it’s an application correctness issue. Enabling it prevents your application from behaving in unexpected and incorrect ways.
Accessing attributes that weren’t selected could lead to all sorts of catastrophic behavior:
- Data loss
- Overwriting data
- Treating free users as paid
- Treating paid users as free
- Sending factually incorrect emails
- Sending the same email dozens of times
The list goes on and on.
While throwing exceptions in production is inconvenient, it’s much worse to have silent failures that could lead to data corruption. Better to face the exceptions and fix them.
This is a continuation of the previous section and another plea to turn on Model::preventAccessingMissingAttributes()
in your production environments.
We just spent a long time looking at how preventAccessingMissingAttributes()
protects you from partially hydrated models, but there are two other scenarios where this method can protect you!
The first is typos.
Continuing with the is_blocked
scenario from above, if you accidentally misspell “blocked,” Laravel will just return null
instead of letting you know about your mistake.
// Fully hydrated model.
$user = User::find(1);
// Oops! Spelled "blocked" wrong. Everyone gets through!
if ($user->is_blokced) {
throw new \Illuminate\Auth\Access\AuthorizationException;
}
This particular example would likely be caught in testing, but why risk it?
The second scenario is renamed columns. If your column started out named blocked
and then later you decide it makes more sense for it to be named is_blocked
, you’d need to make sure to go back through your code and update every reference to blocked
. And if you miss one? It just becomes null
.
// Fully hydrated model.
$user = User::find(1);
// Oops! Used the old name. Everyone gets through!
if ($user->blocked) {
throw new \Illuminate\Auth\Access\AuthorizationException;
}
Turning on Model::preventAccessingMissingAttributes()
would turn this silent failure into an explicit one.
A mass assignment is a vulnerability that allows users to set attributes that they shouldn’t be allowed to set.
For example, if you have an is_admin
property, you don’t want users to be able to arbitrarily upgrade themselves to an admin! Laravel prevents this by default, requiring you to explicitly allow attributes to be mass assigned.
In this example, the only attributes that can be mass assigned are name
and email
.
class User extends Model
{
protected $fillable = [
'name',
'email',
];
}
It doesn’t matter how many attributes you pass in when creating or saving the model. Only name
and email
will get saved:
// It doesn't matter what the user passed in, only `name`
// and `email` are updated. `is_admin` is discarded.
User::find(1)->update([
'name' => 'Aaron',
'email' => 'aaron@example.com',
'is_admin' => true
]);
Many Laravel developers opt to turn off mass assignment protection altogether and rely on request validation to exclude attributes. That’s totally reasonable! You just need to ensure you never pass $request->all()
into your model persistence methods.
You can add this to your AppServiceProvider
to turn off mass assignment protection altogether.
use Illuminate\Database\Eloquent\Model;
public function boot()
{
// No mass assignment protection at all.
Model::unguard();
}
Remember: you’re taking a risk when you unguard your models! Be sure to never blindly pass in all of the request data.
// Only update `name` and `email`.
User::find(1)->update($request->only(['name', 'email']));
If you decide to keep mass assignment protection on, there is one other method that you’ll find helpful: the Model::preventSilentlyDiscardingAttributes()
method.
In the case where your fillable attributes are only name
and email
, and you try to update birthday
, then birthday
will be silently discarded with no warning.
// We're trying to update `birthday`, but it won't persist!
User::find(1)->update([
'name' => 'Aaron',
'email' => 'aaron@example.com',
'birthday' => '1989-02-14'
]);
The birthday
attribute gets thrown away because it’s not fillable. This is mass assignment protection in action, and it’s what we want! It’s just a little bit confusing because it’s silent instead of explicit.
Laravel now provides a way to make that silent error explicit:
use Illuminate\Database\Eloquent\Model;
public function boot()
{
// Warn us when we try to set an unfillable property.
Model::preventSilentlyDiscardingAttributes();
}
Instead of silently discarding the attributes, a MassAssignmentException
will be thrown, and you’ll immediately know what’s happening.
This protection is very similar to the preventAccessingMissingAttributes
protection. It is primarily about application correctness versus application performance. If you’re expecting that data is saved, but it is not saved, that’s an exception and should never be silently ignored, regardless of environment.
For that reason, we recommend keeping this protection on in all environments!
use Illuminate\Database\Eloquent\Model;
public function boot()
{
// Warn us when we try to set an unfillable property,
// in every environment!
Model::preventSilentlyDiscardingAttributes();
}
Laravel 9.35.0 provides a helper method called Model::shouldBeStrict()
that controls the three Eloquent “strictness” settings:
Model::preventLazyLoading()
Model::preventSilentlyDiscardingAttributes()
Model::preventsAccessingMissingAttributes()
The idea here is that you could put the shouldBeStrict()
call in your AppServiceProvider
and turn all three settings on or off with one method call. Let’s quickly recap our recommendations for each setting:
preventLazyLoading
: Primarily for application performance. Off for production, on locally. (Unless you’re logging violations in production.)preventSilentlyDiscardingAttributes
: Primarily for application correctness. On everywhere.preventsAccessingMissingAttributes
: Primarily for application correctness. On everywhere.
Considering this, if you’re planning on logging lazy loading violations in production, you could configure your AppServiceProvider
like this:
use Illuminate\Database\Eloquent\Model;
public function boot()
{
// Everything strict, all the time.
Model::shouldBeStrict();
// In production, merely log lazy loading violations.
if ($this->app->isProduction()) {
Model::handleLazyLoadingViolationUsing(function ($model, $relation) {
$class = get_class($model);
info("Attempted to lazy load [{$relation}] on model [{$class}].");
});
}
}
If you’re not planning on logging lazy load violations (which is a reasonable decision!), then you would configure your settings this way:
use Illuminate\Database\Eloquent\Model;
public function boot()
{
// As these are concerned with application correctness,
// leave them enabled all the time.
Model::preventAccessingMissingAttributes();
Model::preventSilentlyDiscardingAttributes();
// Since this is a performance concern only, don't halt
// production for violations.
Model::preventLazyLoading(!$this->app->isProduction());
}
A polymorphic relationship is a special type of relationship that allows many types of parent models to share a single type of child model.
For example, a blog post and a user may both have images, and instead of creating a separate image model for each, you can create a polymorphic relationship. This lets you have a single Image
model that serves both the Post
and User
models. In this example, the Image
is the polymorphic relationship.
In the images
table, you’ll see two columns that Laravel uses to locate the parent model: an imageable_type
and an imageable_id
column.
The imageable_type
column stores the model type in the form of the fully qualified class name (FQCN), and the imageable_id
is the model’s primary key.
mysql> select * from images;
+----+-------------+-----------------+------------------------------+
| id | imageable_id | imageable_type | url |
+----+-------------+-----------------+------------------------------+
| 1 | 1 | App\Post | https://example.com/1001.jpg |
| 2 | 2 | App\Post | https://example.com/1002.jpg |
| 3 | 3 | App\Post | https://example.com/1003.jpg |
| 4 | 22001 | App\User | https://example.com/1004.jpg |
| 5 | 22000 | App\User | https://example.com/1005.jpg |
| 6 | 22002 | App\User | https://example.com/1006.jpg |
| 7 | 4 | App\Post | https://example.com/1007.jpg |
| 8 | 5 | App\Post | https://example.com/1008.jpg |
| 9 | 22003 | App\User | https://example.com/1009.jpg |
| 10 | 22004 | App\User | https://example.com/1010.jpg |
+----+-------------+-----------------+------------------------------+
This is Laravel’s default behavior, but it’s not a good practice to store FQCNs in your database. Tying the data in your database to the particular class name is very brittle and can lead to unforeseen breakages if you ever refactor your classes.
To prevent this, Laravel gives us a way to control what values end up in the database with the Relation::morphMap
method. Using this method, you can give every morphed class a unique key that never changes, even if the class name does change:
use Illuminate\Database\Eloquent\Relations;
public function boot()
{
Relation::morphMap([
'user' => \App\User::class,
'post' => \App\Post::class,
]);
}
Now we’ve broken the association between our class name and the data stored in the database. Instead of seeing \App\User
in the database, we’ll see user
. A good start!
We’re still exposed to one potential problem, though: this mapping is not required. We could create a new Comment
model and forget to add it to the morphMap
, and Laravel will default to the FQCN, leaving us with a bit of a mess.
mysql> select * from images;
+----+-------------+-----------------+------------------------------+
| id | imageable_id | imageable_type | url |
+----+-------------+-----------------+------------------------------+
| 1 | 1 | post | https://example.com/1001.jpg |
| 2 | 2 | post | https://example.com/1002.jpg |
| .. | ... | .... | . . . . . . . . . . . . . . |
| 10 | 22004 | user | https://example.com/1010.jpg |
| 11 | 10 | App\Comment | https://example.com/1011.jpg |
| 12 | 11 | App\Comment | https://example.com/1012.jpg |
| 13 | 12 | App\Comment | https://example.com/1013.jpg |
+----+-------------+-----------------+------------------------------+
Some of our imageable_type
values are correctly decoupled, but because we forgot to map the App\Comment
model to a key, the FQCN still ends up in the database!
Laravel has our back (again) by providing us a method to enforce that every morphed model is mapped. You can change your morphMap
call to an enforceMorphMap
call, and the fall-through-to-FQCN behavior is disabled.
use Illuminate\Database\Eloquent\Relations;
public function boot()
{
// Enforce a morph map instead of making it optional.
Relation::enforceMorphMap([
'user' => \App\User::class,
'post' => \App\Post::class,
]);
}
Now, if you try to use a new morph that you haven’t mapped, you’ll be greeted with a ClassMorphViolationException
, which you can fix before the bad data makes it to the database.
The most pernicious failures are the silent ones; it’s always better to have explicit failures!
While testing your application, it’s common to fake outgoing requests to third parties so you can control the various testing scenarios and not spam your providers.
Laravel has offered us a way to do that for a long time by calling Http::fake()
, which fakes all outgoing HTTP requests. Most often, though, you want to fake a specific request and provide a response:
use Illuminate\Support\Facades\Http;
// Fake GitHub requests only.
Http::fake([
'github.com/*' => Http::response(['user_id' => '1234'], 200)
]);
In this scenario, outgoing HTTP requests to any other domain will not be faked and will be sent out as regular HTTP requests. You may not notice this until you realize that specific tests are slow or you start hitting rate limits.
Laravel 9.12.0 introduced the preventStrayRequests
method to protect you from making errant requests.
use Illuminate\Support\Facades\Http;
// Don't let any requests go out.
Http::preventStrayRequests();
// Fake GitHub requests only.
Http::fake([
'github.com/*' => Http::response(['user_id' => '1234'], 200)
]);
// Not faked, so an exception is thrown.
Http::get('https://planetscale.com');
This is another good protection to always enable. If your tests need to reach external services, you should explicitly allow that. If you have a base test class, I recommend putting it in the setUp
method of that base class:
protected function setUp(): void
{
parent::setUp();
Http::preventStrayRequests();
}
In any tests where you need to allow non-mocked requests to go out, you can re-enable that by calling Http::allowStrayRequests()
in that particular test.
These last few methods aren’t about preventing discrete, incorrect behaviors but rather monitoring the entire application. These methods can be helpful if you don’t have an application performance monitoring tool.
Long database queries
Laravel 9.18.0 introduced the DB::whenQueryingForLongerThan()
method, which allows you to run a callback when cumulative runtime across all of your queries exceeds a certain threshold.
use Illuminate\Support\Facades\DB;
public function boot()
{
// Log a warning if we spend more than a total of 2000ms querying.
DB::whenQueryingForLongerThan(2000, function (Connection $connection) {
Log::warning("Database queries exceeded 2 seconds on {$connection->getName()}");
});
}
If you want to run a callback when a single query takes a long time, you can do that with a DB::listen
callback.
use Illuminate\Support\Facades\DB;
public function boot()
{
// Log a warning if we spend more than 1000ms on a single query.
DB::listen(function ($query) {
if ($query->time > 1000) {
Log::warning("An individual database query exceeded 1 second.", [
'sql' => $query->sql
]);
}
});
}
Again, these are helpful methods if you do not have an APM tool or a query monitoring tool like PlanetScale’s Query Insights.
Request and command lifecycle
Similar to long-running query monitoring, you can monitor when your request or command lifecycle takes longer than a certain threshold. Both of these methods are available beginning with Laravel 9.31.0.
use Illuminate\Contracts\Http\Kernel as HttpKernel;
use Illuminate\Contracts\Console\Kernel as ConsoleKernel;
public function boot()
{
if ($this->app->runningInConsole()) {
// Log slow commands.
$this->app[ConsoleKernel::class]->whenCommandLifecycleIsLongerThan(
5000,
function ($startedAt, $input, $status) {
Log::warning("A command took longer than 5 seconds.");
}
);
} else {
// Log slow requests.
$this->app[HttpKernel::class]->whenRequestLifecycleIsLongerThan(
5000,
function ($startedAt, $request, $response) {
Log::warning("A request took longer than 5 seconds.");
}
);
}
}
Many of these Laravel safety features take implicit behaviors and turn them into explicit exceptions. In the early days of a project, it’s easy to keep all of the implicit behaviors in your head, but as time goes on, it’s easy to forget one or two of them and end up in a situation where your application is not behaving as you’d expect.
You have enough things to worry about. Take some off your plate by enabling these protections!
Want a powerful and performant database that doesn’t slow you down?
Laravel News Links
Northland’s NEW Elite Series Weedless Cabbage Crusher Jig
https://www.alloutdoor.com/wp-content/uploads/2022/10/unnamed-67.jpg
Largemouth bass love grass and vegetation, they will just cruise along the weedlines looking for a quick and easy meal. They also will lurk deeper in cabbage, coontail, and milfoil beds and depth breaks doing the same thing. So while these fish are willing to eat, the problem is often the inability to get a lure into the jungle of grass the bass are living in. That’s where Northland comes in with their new Elite Series Cabbage Crusher weedless jig. It is a slender upturned bullet-shaped weedless jig built specifically to operate in vegetation.
The guys at Northland put a lot of thought and effort into the new jigs. With lots of testing and re-testing of the designs until the final retail-ready Cabbage Crusher was complete. The jig features a 60-degree tie eye which easily slips through the weeds and heavy cover. The eye itself was also designed with a larger gap to fit heavier fluorocarbon that is often used by bass anglers plying vegetation. The next feature is the weed guard, a piece of titanium chosen for both its strength and flexibility. A dual wire weed guard, instead of a single grass guard the bait can glide easily through heavy cover without having to sacrifice any of the hook gap. To round off the jig a molded-in bait holder and wire keeper combine to keep plastics and skirts in place.
Looking for a way to get more bites in the vegetation-filled bass lakes, rivers, and reservoirs you fish? Give the new Cabbage Crusher a shot, either with a big swimming plastic, a Beaver-style bait, or dress it up as a jig with your own favorite skirt and tip it with the plastic of your choice. The options are endless…
Northland’s Cabbage Crusher will be available in four sizes – 3/16-, 1/8-, 3/8- and ½-ounce – and four colors: RUSTY CRAW, BLACK, GREEN PUMPKIN, and SILVER SHINER, two jigs per pack. MSRP $6.49
Available late 2022.
The post Northland’s NEW Elite Series Weedless Cabbage Crusher Jig appeared first on AllOutdoor.com.
AllOutdoor.com
New MySQL HeatWave capabilities released in 8.0.31
New MySQL HeatWave capabilities released in 8.0.31Planet MySQL
Achieve Real-Time Marketing Analytics with MySQL HeatWave
Many companies and digital marketing agencies want to aggregate data from various sources in real-time to build rich, highly segmented customer profiles to send the right offer to the right prospect, via the right channel, at the right time—and are struggling. MySQL HeatWave helps solve this problem.Planet MySQL
Learn New Old Recipes From This Free Collection of 12,000 Vintage Cookbooks
https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_675,pg_1,q_80,w_1200/540dea093f2e7b6b5cc9b214453ab56b.jpg
Today, cookbooks are a dime a dozen, with every celebrity chef—and celebrity-turned-home-chef—coming out with their own (usually accompanied by a line of kitchen-related products). But we only have to go back a generation or two to get to a time when cookbooks had an indispensable role in most American households—not only for display in kitchen, but used on a regular (if not daily) basis.
Regardless of why and when they were written, cookbooks provide an interesting glimpse into the past, including when certain foods became available in various areas, disappearing regional cuisine, and what was eaten on special occasions.
Fortunately, you don’t need to criss-cross the country to find a vast selection of the cookbooks used throughout postcolonial American history. There is a free (and constantly growing) online archive containing nearly 12,300 American cookbooks and other home economics texts. Here’s what to know.
How to access the free online collection of vintage cookbooks
Longtime Lifehacker readers know how much we love the Internet Archive. Whether you’re looking for webpages that no longer exist, want to watch VHS recordings of your favorite 1990s TV shows and commercials, or play long-abandoned versions of computer games, this online tool has come in handy on many occasions, and served as the gateway to countless research rabbit holes.
G/O Media may get a commission
Though the Internet Archive’s Cookbook and Home Economics Collection has been around since 2007, it has grown considerably in recent years: From roughly 3,000 volumes in 2016, to 12,297 as of this writing.
As you’d imagine, most cookbooks in the archive—and in general—were written for home cooks, which, until relatively recently, were almost exclusively women. In fact, starting around the mid-1800s, it became common to gift cookbooks and household manuals (which were often one and the same) to young brides to assist them in setting up their own homes.
In addition to cookbooks and household manuals, you’ll also find some books (and their covers) that haven’t aged well—many of which introduce white Americans to regional or international cuisine, often relying on racist, xenophobic, classist, and cultural stereotypes to do so.
You’ll also find all the usual suspects—Fannie Farmer, Betty Crocker (who, by the way, is a fictional character), and the experts at Better Homes and Gardens—and their classic recipes.
Lifehacker
Laravel Tip – Benchmarking In Laravel
https://i.ytimg.com/vi/ubYl20CG_MM/maxresdefault.jpgHere, we will be looking at a very simple tip in Laravel which is recently added. It is Benchmark class. We can use it to get how long a code took to execute.Laravel News Links
15 Best EDC Pistols [2022]
https://i0.wp.com/www.personaldefenseworld.com/wp-content/uploads/sites/6/2021/10/N8-Tactical-Xecutive.jpg?w=1086&ssl=1
While some defense-minded handgun carriers are more than happy to pack medium- to large-sized pistols and revolvers for their everyday carry (EDC) guns, in my estimation it is the smaller compact and subcompact pistols and revolvers that predominate. Certainly, there could be seasonal considerations—it’s easier to conceal a large handgun under a winter coat. But you will carry what you will carry and, in most cases, size matters. So, we take a look at the top 15 EDC pistols for 2022.

RELATED STORY
The N8 Tactical Xecutive Delivers a True All-in-One Holster for EDC
15 Top EDC Pistols for 2022
Weight matters, too. One must also consider extra ammunition, a tactical light and/or a practical knife. As a retired law enforcement officer (LEO), I am going to carry a concealed handgun, no doubt about it. However, as I age, I’m less inclined to carry 5 pounds of gun and gear in close proximity to my waistline. I want something effective, but at the same time, I don’t want to come home following an outing and have to rub on pain-soothing ointment or pop several acetaminophen tablets. The most important rule is to have a gun. So, here are some that I’ve found for 2022 that fill the bill.
Beretta APX A1 Carry

- Overall Length: 5.63″
- Barrel Length: 3″
- Weight (unloaded): 19.8 ounces
- Magazine Capacity: 6/8
- Caliber: 9mm
- MSRP: $499
The Beretta APX A1 Carry continues to uphold the reputation of reliability and quality engineering that the APX group is known for. The striker-fired action allows for a trigger pull that is shorter and lighter, the slide readily welcomes red-dot optics, and the modularity is enhanced to allow shooters to make the APX A-1 Carry truly their own.
CZ P-01

- Overall Length: 7.2″
- Barrel Length: 3.75″
- Weight (unloaded): 28.1 ounces
- Magazine Capacity: 10
- Caliber: 9mm
- MSRP: $779
The CZ P-01 was originally designed for military and law enforcement but thanks to its compact aluminum frame, its an excellent choice for concealed carry. The P-01 offers a decocker for shooters who opt for hammer-down carry. While the first round has a hefty trigger pull, the remaining shots are released with a light but sharp single action. CZ enthusiasts will appreciate that the components of the P-01/P-06 are fully interchangeable with every other P-01/P-06, with no individual fitting required. Thanks to an integral accessory rail on its dust cover, the P-01 welcomes industry-standard lights and lasers.
FN 509 Compact

- Overall Length: 6.8″
- Barrel Length: 3.7″
- Weight (unloaded): 25.5 ounces
- Magazine Capacity: 10/12/15
- Caliber: 9mm
- MSRP: $719
This FN 509 Compact model features a design around deep concealment. A low-profile blackout rear sight mates with a high-visibility dot front sight. This striker-fired, double-action (DA) includes a flush-fit magazine and can support a 15-round extended magazine. There are also two interchangeable backstraps and advanced grip texturing, plus an integral accessory rail on the dust cover. The slide stop and magazine catch are ambidextrous.
HK VP9SK

- Overall Length: 6.61″
- Barrel Length: 3.39″
- Weight (unloaded): 23.07 ounces
- Magazine Capacity: 10/13/15
- Caliber: 9mm
- MSRP: $726.83
This version of the VP9SK has a push-button magazine catch (in place of a paddle catch) that’s also reversible, an adjustable grip frame, and an interchangeable backstrap, allowing up to 27 configurations. Sights are fixed with optional night sights. There’s also an accessory rail, and the striker-fired trigger is the best in its class. Slide finish is Black HE with a textured polymer frame.
Kimber Micro 9 Rapide (Black Ice)

- Overall Length: 6.4″
- Barrel Length: 3.15″
- Weight (unloaded): 15.6 ounces
- Magazine Capacity: 7+1
- Caliber: 9mm
- MSRP: $899.99
The Micro 9 is hammer-fired with a single-action (SA) mechanism, plus ambidextrous manual safeties. The steel slide has stepped cocking serrations and cuts to reduce weight. It’s mated to an aluminum frame, with both in a two-tone KimPro finish. Tru-Glo TFX night sights are standard, as are black textured G10 grips. The stainless match barrel allows for reliable operation round after round.
Magnum Research Baby Eagle III

- Overall Length: 7.825″
- Barrel Length: 4.43” (Full Size), 3.85” (Semi-Compact)
- Weight (unloaded): 35.52 ounces, 33.6 ounces, 32 ounces, 30.4 ounces, 28.16 ounces, 26.4 ounces, 25.92 ounces
- Magazine Capacity: 10/12/15
- Caliber: .45 ACP, .40 S&W, 9mm
- MSRP: $739/$840
The Baby III comes in both steel and polymer frames with a black oxide finish. The polymer version has a slim, textured grip frame, with a finger groove frontstrap and accessory rail, plus three-dot fixed sights. This is a double-action/single-action (DA/SA), hammer-fired pistol, with a slide-mounted manual safety/decocker.
Ruger LCP II Lite Rack .22

- Overall Length: 5.20″
- Barrel Length: 2.75″
- Weight (unloaded): 11.4 ounces
- Magazine Capacity: 10+1
- Caliber: .22LR
- MSRP: $369
Not everyone can manage difficult gun manipulation and recoil. Now, Ruger has the LCP II Lite Rack chambered in .22 Long Rifle. With a steel slide and polymer frame, this striker-fired DA has the Lite Rack System, with refined serrations and ears on the slide, a push-forward safety option, plus a Hogue HandALL grip sleeve. While set up for high-velocity .22 ammo, it has low recoil.
SAR 9C

- Overall Length: 7.5″
- Barrel Length: 4.4″
- Weight (unloaded): 27.8 ounces
- Magazine Capacity: 17+1
- Caliber: 9mm
- MSRP: $429
Made by Sarsilmaz of Turkey, the SAR 9C is a striker-fired, safety-trigger-equipped, polymer-framed pistol with a steel slide and fixed-dot sights. Good hand fit is assured with interchangeable backstraps and side panels. The grip frame has textured panels, and there’s an accessory rail on the dust cover. Recoil is tamed with a low bore axis and 20-degree grip angle.
SCCY CPX-2 GEN3

- Overall Length: 6″
- Barrel Length: 3.1″
- Weight (unloaded): 15 ounces
- Magazine Capacity: 10+1
- Caliber: 9mm
- MSRP: $309.95 (red-dot-ready version is $339.95)
The SCCY CPX-2 GEN3 is perfect for new and advanced shooters alike thanks to its ergonomic and easy-to-use design. This compact, hammer-fired, DAO pistol includes a Picatinny rail to support accessories, upgraded sights for rapid target acquisition, and an enhanced grip system for an optimal hold. The SCCY CPX-2 GEN3 is available in a variety of colors to suit just about any preference.
Sig Sauer P365 Nitron

- Overall Length: 5.8″
- Barrel Length: 3.1″
- Weight (unloaded): 17.8 ounces
- Magazine Capacity: 10
- Caliber: 9mm
- MSRP: $499.99
SIG’s P365 Nitron offers all the reliability and quality that SIG firearms are known for in a compact EDC pistol. One shot of this striker-fired handgun will show how its smooth, consistent trigger and quick, controlled firing can be counted on in any shooting situation. Even more so is the presence of the ergonomic textured grip on the durable polymer frame for a secure and dependable hold. SIG’s own X-RAY3, high-visibility, 3-dot tritium sights aid shooters in rapid target acquisition. Frame includes an integral slim-line rail that is compatible with SIG Sauer light or laser accessories. A corrosion-resistant, Nitron coated stainless steel slide features front and rear serrations to a shooter’s ability to effortlessly rack the slide back for loading and clearing the action.
Springfield Armory Hellcat Pro

- Overall Length: 6.6″
- Barrel Length: 3.7″
- Weight (unloaded): 21 ounces
- Magazine Capacity: 15+1
- Caliber: 9mm
- MSRP: $634
The Springfield Hellcat Pro packs all the punch of a large handgun into an ultra-concealable compact pistol thanks to its intimidating 15+1 capacity plus a bevy of other game-changing features. This EDC pistol is optics-ready with its OSP (Optical Sight Pistol) configuration and the slide is milled with the Springfield Micro
footprint which accommodates the smallest micro red dots on the market. To add to this, the Hellcat Pro includes a high-visibility tritium and luminescent front sight paired with a Tactical Rack U-Dot
rear sight to aid shooters in any lighting situation. The inclusion of a Picatinny rail allows for the addition of a light or laser. Slide and barrel are coated in an ultradurable Melonite® finish to withstand years of hard use. For ease of mind, the engineers at Springfield included a loaded chamber indicator to showcase the condition of the pistol.
Stoeger STR-9S Combat Pistol

- Overall Length: 7.9″
- Barrel Length: 4.7″
- Weight (unloaded): 28 ounces
- Magazine Capacity: 20+1
- Caliber: 9mm
- MSRP: $549
Some folks don’t mind extra bulk in their EDC. If this is the case, you might like the STR-9S Combat Pistol. It’s set up with co-witness/suppressor fiber-optic sights, threaded barrel with cap, flared mag well, three interchangeable backstraps, and optics-ready slide. This striker-fired pistol has a polymer frame, a textured, finger-groove grip, and an accessory rail. The steel slide features front and rear serrations and has a Black Nitride finish.
Smith & Wesson M&P 9 M2.0 Metal

- Overall Length: 7.4″
- Barrel Length: 4.25″
- Weight (unloaded): 30 ounces
- Magazine Capacity: 17+1
- Caliber: 9mm
- MSRP: $899
The M&P 9 M2.0 Metal manages to offer a lightweight and high-performing firearm despite its rigid metal frame. Built with all shooters in mind, the M&P 9 M2.0 Metal possesses an 18-degree grip angle for a natural point of aim, four interchangeable palmswell grip inserts to suit all hand sizes, a textured polymer front strap, an M2.0 flat face trigger for more spot-on shooting, a Picatinny-style accessory rail for lights and optics, and a low barrel bore axis to reduce muzzle rise and maintaining target engagement.
Taurus GX4XL

- Overall Length: 6.43″
- Barrel Length: 3.71″
- Weight (unloaded): 20 ounces
- Magazine Capacity: 10/11/13
- Caliber: 9mm
- MSRP: $429 ($459 for the T.O.R.O. optics-ready version)
The Taurus GX4XL makes for quite the workhorse thanks to its increased muzzle velocity and sight radius. While it has grown slightly from its predecessor, the GX4, by 20mm, it still remains an excellent choice for a compact EDC pistol. The GX4XL’s standard backstrap features a slight palm swell for improved grip. The DLC-coated stainless steel barrel resists corrosion to withstand demanding environments while the carbon steel slide is gas-nitride coated for added protection. The GX4XL’s sight system consists of a blackout steel serrated drift adjustable rear sight and fixed front sight for rapid target acquisition. The flat-face trigger has a responsive sear break with a short and tactile reset. Like the Springfield Hellcat Pro, there is a visual loaded chamber indicator for safer operation.
Walther PDP Compact 4-inch

- Overall Length: 7.5″
- Barrel Length: 4″
- Weight (unloaded): 24.4 ounces
- Magazine Capacity: 15+1
- Caliber: 9mm
- MSRP: $699
This Performance Duty Pistol has Super Terrain slide serrations and a distinctive Performance Duty trigger action with a 5.6-pound pull. The steel slide has a white-dot adjustable rear sight and post front sight and is optics-ready. The polymer grip frame has a Performance texture, and there’s an accessory rail for mounting lights or lasers.
The post 15 Best EDC Pistols [2022] appeared first on Personal Defense World.
Personal Defense World
Are You Nuts? Know your Fishing Knots! – The Trilene Knot
https://www.alloutdoor.com/wp-content/uploads/2022/10/20221020_164530.jpg
This week we are going to cover another line to hook or lure knot again this week with the Trilene Knot. Considered a very strong and reliable connection for tying monofilament or fluorocarbon to hooks, snaps, swivels, and lures, the Trilene knot, also known as the Two Turn Clinch Knot, is considered a “100% Knot”. This is because when tied properly it is often the line breaking, not the knot itself failing. The Trilene Knot has comparable knot strength to the Palomar Knot but isn’t recommended for braided lines due to not being a double line. So stick with other options if you’re planning to use straight braid. An interesting fact about this knot is while it was created by pro anglers by professional anglers Jimmy Houston and Ricky Green in the late 1970s, Trilene stepped and named the knot after itself.
Step 1
Run the line through the eye of the hook and bring the tag end of the line back along the mainline.
Step 2
Run the tag end of the line through the eye of the hook once more to create loop behind the hook eye,
Step 3
Take the tag end of the line and make five to six wraps around the main line.
Step 4
Taking the tag end of the line, while holding the line wraps so they don’t slide and clump, run the tag end through both the loops of the line that you created earlier.
Step 5
Wet the line and then pull on both the main line and tag end of the line to tighten down the Trilene Knot. Make sure everything has set evenly then cut off the tag end of the line. leave about 1/4″ of a tag just in case the knot wasn’t tightened enough and slips. To keep such things from happening make sure to give the knot a good hard pull before use.
The post Are You Nuts? Know your Fishing Knots! – The Trilene Knot appeared first on AllOutdoor.com.
AllOutdoor.com
A Lion Bonks a Tree and More in the 2022 Comedy Wildlife Photo Awards
https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_675,pg_1,q_80,w_1200/5c82ef56cac875ac6429401962bf72c4.jpg
“I was following a group of meerkats on foot in the Kalahari Trails Game Reserve, in South Africa. Most individuals, including adults, were in a playful mood. It gave me a unique opportunity to capture very interesting and dynamic interactions between some members of the group. In the photo that I have selected, there is no aggression between individuals, but rather an interaction that reminds us of humans when one of your friends jokes about you and you pretend to strangle them and, in response, they open their mouth like a simpleton,” said photographer Emmanuel Do Linh San.
Gizmodo