Quick Tips

MySQL can be used in Laravel development to sort your data instead of the values() method to rekey your array when running sort operations. The approach below runs directly on a collection before returning your JSON response, to ensure you don’t get an Object response instead of the Array you’re looking for.

// Bad: returns object
$myCollection = MyModel::get();
return response()->json($myCollection->sortBy('name'), 200);
 
// Good: returns array
$myCollection = MyModel::get();
return response()->json($myCollection->sortBy('name')->values(), 200);
 
// Better: returns Array
$myCollection = MyModel::orderBy('name')->get();
return response()->json($myCollection, 200);

If your CSS animations are running a little choppy or slow, a one-line addition to your CSS code can offload processing of them to the GPU instead of the CPU to make your animations run buttery smooth.

// Plain CSS
transform: translateZ(0);
 
// Tailwind CSS class
transform-gpu

If you’re using a Redis Cluster with Predis (a behind-the-scenes Laravel tool), forcing multiple keys to be part of the same hash slot can make all the difference in streamlining your search indexes.

// Without a Redis Cluster
Redis::throttle('search.index');
 
// With a Redis Cluster
Redis::throttle('{search.index}');

Getting GPG errors after updating Big Sur and brew on your Mac? Updating your global git config or restarting your gpg-agent can help.

git config --global gpg.program [new executable name, gpg1 or gpg2]
 
or
 
gpgconf --kill gpg-agent

Use getSelect() when you want to designate a field to add to your query scope that won't override the predefined select() statement. PHP code workarounds like this ensure that the originally selected columns are honored without duplication of data.

// parent query
Model::select('id', 'title')->myScope()->get();
 
// inside your myScope() scope
$query->when(
! in_array('body', $query->getSelect()),
fn ($q) => $q->addSelect('body');
);

Want to leverage Laravel Eloquent scopes and skip model hydration for some extra performance and memory boost? Calling getQuery() before retrieving your results might be just what you’re looking for for your web application.

// Query time: 52 ms; Response time: 510 ms; Memory: 24 MB
Product::select('id', 'sku', 'name', 'created_at')->limit(5000)->get();
 
// Query time: 48 ms; Response time: 125 ms; Memory: 6 MB
Product::select('id', 'sku', 'name', 'created_at')->limit(5000)->getQuery()->get();

Need to perform a SQL INSERT INTO SELECT statement with Laravel? You can use the insertUsing builder method. This Laravel coding tip can be useful to avoid fetching records, then manipulating them to insert into a new table.

DB::table('employee_role')->insertUsing(
['employee_id', 'role_id', 'updated_at', 'created_at'],
fn ($query) => $query->table('employees')
->whereIn('id', $ids)
->select([
'id as employee_id',
DB::raw($roleId),
DB::raw('NOW() as created_at'),
DB::raw('NOW() as updated_at'),
])
);

If you need to ensure a Laravel Artisan command runs after another one completes, use the then() method.

$schedule->command(Command::class)
->hourly()
->then(function () {
$this->call(OtherCommand::class);
});

The isDirty() Laravel method lets you know if any properties in your data model have changed. Applying a getChanges() segment then identifies exactly which property has changed to drive clear program documentation.

$model = Model::first();
$model->isDirty(); // false
 
$model->property = 'newvalue';
 
$model->getChanges(); // [ 'property' => 'newvalue' ];
$model->isDirty(); // true

Need to create a new model from an existing one? Eloquent in Laravel has a built-in replicate() method that creates an unsaved copy of your model in a new instance.

$model = Model::first();
 
$newModel = $model->replicate();
$newModel->save();

Here’s a handy tip for setting LOG_LEVEL inside .env files in Laravel to determine what gets logged and what doesn’t. It’s especially useful for minimizing unnecessary alerting and logging used for debugging in your production environment.

// inside .env
LOG_LEVEL=warning
 
// inside your code
Log::info('This will not be logged');
Log::error('This will be logged');

Validate all items in an array quickly and easily using Laravel validation.

public function rules()
{
return [
// ...other rules
'attendees.*.name' => 'required|string',
];
}

Validating properties of array items in FormRequest classes.

public function rules()
{
return [
// ...other rules
'phone_numbers.*.number' => 'required|string',
];
}

Laravel Eloquent’s expressive syntax for where() clauses can help make your code more readable. Using this where() method can streamline the querying of any property to keep your code lean.

$model = Model::where('property', 'value')->get();
 
// expressive syntax
$model = Model::whereProperty('value')->get();

Nesting CRUD resource using Route::resource method. Example usage in a controller with a store method handler.

// routes/web.php
Route::resource('environments.deployments', DeploymentController::class)->only('store');
// => POST /environments/:id/deployments
 
// Project/Environment/DeploymentController.php
public function store(Request $request, Environment $environment)
{
$deployment = $environment->deployments()->create([
'name' => $request->input('name'),
]);
}

Use includeWhen() in your Blade views when you want to conditionally include a partial.

// good
@if ($someCondition)
@include('partials.some_partial')
@endif
 
// better
@includeWhen($someCondition, 'partials.some_partial')

The Blade @each directive can help cleanup loops in your templates.

// good
@foreach($items as $item)
<div>
<p>Name: {{ $item->name }}</p>
<p>Price: {{ $item->price }}</p>
</div>
@endforeach
 
// better (HTML extracted into partial)
@each('partials.item', $items, 'item')

When using eager loading and specifying a JSON column, you can use Laravel’s arrow syntax to only load the properties you need from the column instead of the entire object.

MyModel::query()->with([
'relationship:id,my_model_id',
'json_column->property_name as json_property',
])->first();
 
// output
{
id: 1,
// ... other model properties
relationship: {
id: 1,
my_model_id: 1,
json_property: (value of your JSON property)
}
}

You can use the where(‘parameter’, ‘.*’) method as a catch-all behavior for a route to send everything into your route parameter. Just be aware of the order you register the routes! If you have other routes and you don't want for the catch-all to interfere, you should put it in the end of the route list.

Route::get('/base-route/{parameter}', function (string $parameter) {
// $parameter will have everything after base-route/
})->where('parameter', '.*');
 
Route::get('base-route/demo', function () {
// This route is unreachable
});

Resolve models using a key other than ID when setting up your routes. Alternatively, if you always want to resolve a Laravel model by an alternate key, you can set the getRouteKeyname() directly on your model.

// Resolve using a key defined in route
Route::get('posts/{post:slug}', function (Post $post) {
return $post;
});
 
// Always resolve using an alternate key
// App/Models/Post
public function getRouteKeyName() {
return 'slug';
}

queue:monitor can be run alongside your queue workers to trigger the QueueBusy event when the number of jobs goes over the max threshold you set. This allows you to trigger alerts to your desired notification channels.

<span class="text-purple-600">php artisan queue:monitor</span> <span class="text-orange-500">--max=1000</span>
+------------+-----------+-------+--------+
| <span class="text-green-700">Connection</span> | <span class="text-green-700">Queue</span> | <span class="text-green-700">Size</span> | <span class="text-green-700">Status</span> |
+------------+-----------+-------+--------+
| sqs | app-queue | 54 | <span class="text-green-700">OK</span> |
+------------+-----------+-------+--------+
 
<span class="text-purple-600">php artisan queue:monitor</span> <span class="text-orange-500">--max=1000</span>
+------------+-----------+-------+--------+
| <span class="text-green-700">Connection</span> | <span class="text-green-700">Queue</span> | <span class="text-green-700">Size</span> | <span class="text-green-700">Status</span> |
+------------+-----------+-------+--------+
| sqs | app-queue | 5012 | <span class="text-red-600">ALERT</span> |
+------------+-----------+-------+--------+
 
<span class="text-red-600">// ALERT status will trigger the Illuminate\Queue\Events\QueueBusy event</span>

If you have scoped styles on Vue 3 or 2 that you also want to affect child components, you can use the :deep() pseudo-class.

Vue 3
<style scoped>
.foo :deep(.bar) {
/* */
}
</style>
 
Vue 2 with sass
<style scoped lang="scss">
.foo::v-deep .bar {
/* */
}
</style>
 
Vue 2 without sass
<style scoped>
.foo >>> .bar {
/* */
}
</style>

If you make use of Carbon::now() in your test suite data providers, you might run into an issue with diffInDays returning the wrong value when tests start late at night and end on the next day. Solve this by returning a callback instead of the Carbon instance.

public function providesDateScenarios()
{
yield 'original' => [Carbon::now()];
 
yield 'simple_fix' => [fn() => Carbon::now()];
}

To help you visualize your application debug logs, check out this tip for grouping them. It’s also possible to collapse them by replacing console.group() with console.groupCollapsed().

You can see the raw SQL your data migration generates using this handy pretend flag as an option in Laravel.

php artisan migrate --pretend
 
// Output
AddIndexToTableMigration:
 
alter table 'my_table' add index 'my_column_index' ('column')

Dates in Javascript can be tricky. The first two lines shown can generate different results, but appending a 'Z' to indicate time zone, can do the trick.

new Date('2021-04-15');
// Thu Apr 15 2021 03:00:00 GMT+0300 (Eastern European Summer Time)
new Date('2021-04-15 00:00:00');
// Thu Apr 15 2021 00:00:00 GMT+0300 (Eastern European Summer Time)
 
new Date('2021-04-15Z');
// Thu Apr 15 2021 03:00:00 GMT+0300 (Eastern European Summer Time)
new Date('2021-04-15 00:00:00Z');
// Thu Apr 15 2021 03:00:00 GMT+0300 (Eastern European Summer Time)

Factory classes are recursive state factories, not “builders.” You’ll need to reassign the state back to `$factory` for it to work like a builder.

$factory = ModelFactory::new()->state(['going_to_give_you_up' => 'never']);
$factory->state(['going_to_give_you_up' => 'frequently']);
$model = $factory->create();
echo $model->going_to_give_you_up; // never

Love destructuring Javascript objects? There are all sorts of places you can use this to make your code more readable, like with Axios responses!

// Without Javascript object destructuring
axios.get('/endpoint').then((response) => this.data = response.data);
 
// With Javascript object destructuring
axios.get('/endpoint').then(({ data }) => this.data = data);

If you need to make a table update setting the value of one column to another column, there's an eloquent way of doing it using DB::raw.

DB::table('employee_role')->insertUsing(
['employee_id', 'role_id', 'updated_at', 'created_at'],
fn ($query) => $query->table('employees')
->whereIn('id', $ids)
->select([
'id as employee_id',
DB::raw($roleId),
DB::raw('NOW() as created_at'),
DB::raw('NOW() as updated_at'),
])
);

Wish you could output the full, unparameterized query in Laravel so you can paste it right into your database GUI? Use this handy Laravel Macro to add a toRawSql() for easier query debugging.

use Illuminate\Database\Eloquent\Builder;
 
Builder::macro('toRawSql', function() {
return array_reduce($this-getBindings(), function($sql, $binding) {
return preg_replace('/\?/', is_numeric($binding)
? $binding
: "'{$binding}'", $sql, 1);
}, $this->toSql());
});
 
// usage
Model::where('foo', 'bar')->where('baz', 1)->toRawSql();
// output
select * from model where "foo" = 'bar' and "baz" = 1;

Want to avoid seeing certain files modified in git status? The "git update-index --assume-unchanged {file}" command will tell git to stop considering the file changed. Some git aliases you can put in your global .gitconfig file to do this

[alias]
hide = update-index --assume-unchanged
hide-all-modified = ! git ls-files -m | xargs git update-index --assume-unchanged --
unhide = update-index --no-assume-unchanged
unhide-all = ! git ls-files -v | grep '^[a-z]' | cut -c3- | xargs git unhide --
hidden = ! git ls-files -v | grep '^[a-z]' | cut -c3-

Need to assert in your tests that 2 arrays in PHP are the same without needing them to happen in a specific order? PHPUnit has a method for that.

$this->assertEqualsCanonicalizing($array1, $array2);

We discovered a fun “gotcha” with pivot model in Laravel called timestamps. If you don’t have `withTimestamps()` specified in the relationship, you can get some funny behavior with the timestamps--even if they’re specified on the pivot model itself.

$model->relationship->first()->pivot->updated_at; // Some date
$model->relationship->first()->pivot->updated_at = now();
$model->relationship->first()->pivot->save();
$model->relationship->first()->pivot->updated_at;
// withTimestamps defined on the relationship this will be saved correctly
// without withTimestamps defined on the relationship, you will get the old date!

Laravel Eloquent’s expressive syntax for where() clauses can help make your code more readable. Using this where() method can streamline the querying of any property to keep your code lean.

$model = Model::where('property', 'value')->get();
 
// expressive syntax
$model = Model::whereProperty('value')->get();

You can call getQuery() on a relationship to get the underlying Eloquent query builder for the Laravel relation and even call getBaseQuery() to get the base query builder driving the eloquent builder!

// Illuminate\Database\Eloquent\Relations\HasMany
$customer->orders();
 
// Illuminate\Database\Eloquent\Builder
$customer->orders()->$yourQueryScopes()->getQuery();
 
// Illuminate\Database\Query\Builder
$customer->orders()->$yourQueryScopes()->getBaseQuery();

If you are using namespaced class names as keys in a JSON column, you can query for them by double quoting the property name and escaping the slashes

SELECT id, status->>'$."Shipping\\\\Collected"' AS collected_date
FROM orders
WHERE status->>'$."Shipping\\\\Delivered"' IS NULL

Do you know you can proxy requests from NGINX to other ports in your server? This can be really helpful to set up HTTPS using Laravel PHP Forge and Let's Encrypt and then route it to a Node JS application, for example. The proxy_pass option can streamline your solution.

# Proxy the requests to the 3000 port
Location / {
Proxy_pass http://127.0.0.1:3000;
}

Phonetic spelling correction in PHP helps your search functions adapt to common spelling mistakes or typos. Typically you'd do this out of the DB such as (`SOUNDEX(cars.model)`), or in something like Elasticsearch, but incorporating this directly with PHP can keep your code agile.

if (metaphone($request->input('car_model')) === metaphone('Forester')) {
print_r("Yep that's still a Forester!");
}

Need to consolidate a ton of routes? You can specify the middleware to use on each method when defining Route::resource() or Route::apiResource() to streamline your Laravel web app.

Route::resource('photos', PhotoController::class)
->middleware([
'update' => 'can:update,photo',
'destroy' => 'can:delete,photo',
]);

When using dev tools, you can toggle classes on and off or add new classes with the .cls button in the sidebar. In Chrome, adding new Laravel .cls buttons has a type-ahead which works effectively in tandem with Tailwind CSS since you can preview the effects when you hover over each one.

If you have a named slot in Laravel wrapped up in a styled container, you can define the slot in your template by leveraging the $slots property.

<div v-if="!! $slots.slot_name" class="flex flex-row bg-gray-500">
<slot name="slot_name"></slot>
</div>

The load() method makes a query even if the relationship is already loaded. This method overwrites previously loaded nested relationships. A better solution is using loadMissing() instead - it avoids overriding important data by checking to see if anything is already loaded before doing anything.

// If you have this first in the call stack
$post = Post::first()->load(['comments.author', 'blog']);
 
// And eventually you hit this
$post = Post::first()->loadMissing(['comments']);
 
// $post still has the `comments` relationship with its author.

Interested in speaking with a developer?

Connect with us.
©2023 Kirschbaum Development Group LLC Privacy Policy Terms of Service