Posts

Since 2024
New Array Find Functions in PHP 8.4
New Array Find Functions in PHP 8.4

Four new array functions are coming to PHP 8.4 which are helper functions for checking an array for the existence of elements matching a specific condition. The new functions are: array_find() array_find_key() array_any() array_all() The array_find() Function The array_find($array, $callback) function returns the first element for which the $callback returns true: $array = [ 'a' => 'dog', 'b' => 'cat', 'c' => 'cow', 'd' => 'duck', 'e' => 'goose', 'f' => 'elephant' ]; array_find($array, function (string $value) { return strlen($value) > 4; }); // string(5) "goose" array_find($array, function (string $value) { return str_starts_with($value, 'f'); }); // null // Find the first animal where the array key is the first symbol of the animal. array_find($array, function (string $value, $key) { return $value[0] === $key; }); Using Laravel's Arr or Collection you can get equivalent functionality with the first() method in combination with a closure: use Illuminate\Support\Arr; use Illuminate\Support\Collection; $array = [ 'a' => 'dog', 'b' => 'cat', 'c' => 'cow', 'd' => 'duck', 'e' => 'goose', 'f' => 'elephant' ]; new Collection($array) ->first(fn ($value) => strlen($value) > 4); // goose Arr::first( $array, fn ($value) => str_starts_with($value, 'f') ); // null new Collection($array) ->first(fn ($value, $key) => $value[0] === $key); // cow Note that we are demonstrating class instantiation without extra parenthesis, which should also be in PHP 8.4. The array_find_key() Function The array_find_key($array, $callback) function returns the key of the first element for which the $callback returns true. Like array_find(), it returns null if no matching element is found: $array = [ 'a' => 'dog', 'b' => 'cat', 'c' => 'cow', 'd' => 'duck', 'e' => 'goose', 'f' => 'elephant' ]; array_find_key($array, function (string $value) { return strlen($value) > 4; }); // string(1) "e" array_find_key($array, function (string $value) { return str_starts_with($value, 'f'); }); // null array_find_key($array, function (string $value, $key) { return $value[0] === $key; }); // string(1) "c" The RFC implementation for this function looks like the following: function array_find_key(array $array, callable $callback): mixed { foreach ($array as $key => $value) { if ($callback($value, $key)) { return $key; } }   return null; } Using Laravel's Collection, you can get functionality similar to the search() method in combination with a closure. However, search() returns false if the item is not found, not null: use Illuminate\Support\Arr; use Illuminate\Support\Collection; new Collection($array)->search(function (string $value) { return strlen($value) > 4; }); // string(1) "e" new Collection($array)->search(function (string $value) { return str_starts_with($value, 'f'); }); // false new Collection($array)->search(function (string $value, $key) { return $value[0] === $key; }); // string(1) "c" The array_any() and array_all() Functions The second part of the RFC (and a separate 2/3 vote) includes the array_any() and array_all() functions. You can use these functions if any of the items in array return true for array_any() and if all of the items in an array return true for array_all(), respectively. $array = [ 'a' => 'dog', 'b' => 'cat', 'c' => 'cow', 'd' => 'duck', 'e' => 'goose', 'f' => 'elephant' ]; // Check, if any animal name is longer than 5 letters. array_any($array, function (string $value) { return strlen($value) > 5; }); // bool(true) // Check, if any animal name is shorter than 3 letters. array_any($array, function (string $value) { return strlen($value) < 3; }); // bool(false) // Check, if all animal names are shorter than 12 letters. array_all($array, function (string $value) { return strlen($value) < 12; }); // bool(true)   // Check, if all animal names are longer than 5 letters. array_all($array, function (string $value) { return strlen($value) > 5; }); // bool(false) Learn More You can read all the details about this change in the RFC. This feature drops in PHP 8.4. The implementation for these functions can be found on GitHub. The post New Array Find Functions in PHP 8.4 appeared first on Laravel News. Join the Laravel Newsletter to get Laravel articles like this directly in your inbox.

The Ability to Prevent Destructive Commands From Running is Coming to Laravel 11
The Ability to Prevent Destructive Commands From Running is Coming to Laravel 11

In an upcoming Laravel release, you can prevent commands like database migrations from accidentally running in production environments. The next Laravel release should include the ability to use a framework Prohibitable trait to stop commands from running: use Illuminate\Console\Command; use Illuminate\Console\Prohibitable; class SomeDestructiveCommand extends Command { use Prohibitable; } // SomeDestructiveCommand::prohibit($this->app->isProduction()); The Laravel framework includes some database commands that include the Prohibitable trait, such as db:wipe, migrate:fresh, migrate:refresh, and migrate:reset: public function boot(): void { FreshCommand::prohibit(); RefreshCommand::prohibit(); ResetCommand::prohibit(); WipeCommand::prohibit(); } Using the DB Facade, you can prohibit destructive database commands built into Laravel: // Prohibits: db:wipe, migrate:fresh, migrate:refresh, and migrate:reset DB::prohibitDestructiveCommands($this->app->isProduction()); The prohibit() method accepts a Boolean argument that defaults to true, and you can conditionally prevent commands from running using whatever logic you need, so that you can still run them in development environments: public function boot(): void { YourCommand::prohibit($this->app->isProduction()); } We don't know when the next version of Laravel 11.x will be released, but we should get this feature in the next release since it's been merged into the 11.x branch. You can learn more about this upcoming feature in the merged Pull Request #51376 by Jason McCreary. The post The Ability to Prevent Destructive Commands From Running is Coming to Laravel 11 appeared first on Laravel News. Join the Laravel Newsletter to get Laravel articles like this directly in your inbox.

Configuring Laravel With Additional Environment Files
Configuring Laravel With Additional Environment Files

In Laravel, you can configure additional environment files that will load instead of the .env file. This feature is helpful for testing, where you can load a .env.testing environment file instead of the default. You typically don't need to reach for this feature, but it's nice to know that by setting the APP_ENV environment variable, Laravel can detect custom configurations. CLI Example The most straightforward example of this feature is using a different environment file when running Laravel with the Artisan console or even the phpunit CLI. Using the Artisan command, you can also use a different .env file using the --env flag or defining an APP_ENV. For example, running the following, Laravel will look for .env.demo: # Set up `.env.demo` cp .env .env.demo echo "\nEXAMPLE_SETTING=demo" >> .env.demo # Use the `demo` env php artisan tinker --env=demo # Or set APP_ENV APP_ENV=demo php artisan tinker If found, Laravel won't load the .env file but instead load .env.demo: Example using .env.demo instead of .env Using .env.testing for PHPUnit Tests Building on what we know about the Laravel framework loading a specific ENV file if it exists, running Laravel feature tests in PHPUnit will use the .env file by default. Using .env for tests and local development could quickly cause issues such as configuring a separate database for testing. You could define database connection details in phpunit.xml, but let's also look at setting them in .env.testing. PHPUnit defines an APP_ENV environment variable in phpunit.xml, which means that Laravel looks for a .env.testing file when bootstrapping Feature tests because the phpunit.xml file defines APP_ENV before the Laravel framework gets bootstrapped in Feature tests: <env name="APP_ENV" value="testing"/> That means we can copy the stock .env file to .env.testing and avoid mixing the two files during testing: cp .env .env.testing echo "\nEXAMPLE_SETTING=testing" >> .env.testing You can configure environment variables in phpunit.xml. However, I like using the .env.testing file to ensure a clean environment specifically for testing. It's also up to you whether you version control .env.testing or ignore it in .gitignore. After copying the .env file, you can verify that .env.testing is loaded by adding the following to a test in your tests/Feature folder. Tests in the tests/Unit folder won't bootstrap the Laravel framework: /** * A basic test example. */ public function test_the_application_returns_a_successful_response(): void { logger('Which environment file is Laravel using?', [ 'file' => $this->app->environmentFile() ]); $response = $this->get('/'); $response->assertStatus(200); } When I run phpunit, I get the following log confirming that I'm using the .env.testing file: [2024-05-24 00:22:42] testing.DEBUG: Which environment file is Laravel using? {"file":".env.testing"} If you ignore this file in your VCS, you could add an example file .env.testing.example with your team's conventions or let them decide how to configure tests locally. I recommend setting system-level environment variables in CI to configure things like test databases. Check out the Laravel Documentation for more details on environment configuration. If you're curious how this works at the framework level, check out the setEnvironmentFilePath method and checkForSpecificEnvironmentFile in the Laravel framework source code. The post Configuring Laravel With Additional Environment Files appeared first on Laravel News. Join the Laravel Newsletter to get Laravel articles like this directly in your inbox.

New Proposed Array Find Functions in PHP 8.4
New Proposed Array Find Functions in PHP 8.4

Four new array functions are likely coming to PHP 8.4 that are still in the RFC voting stage. We're encouraged that the voting is already 100% "yes" votes thus far, with voting ending May 29, 2024. While the RFC acceptance of these functions is pending, it seems likely that these functions are coming to PHP 8.4: array_find() array_find_key() array_any() array_all() The array_find() Function The array_find($array, $callback) function returns the first element for which the $callback returns true: $array = [ 'a' => 'dog', 'b' => 'cat', 'c' => 'cow', 'd' => 'duck', 'e' => 'goose', 'f' => 'elephant' ]; array_find($array, function (string $value) { return strlen($value) > 4; }); // string(5) "goose" array_find($array, function (string $value) { return str_starts_with($value, 'f'); }); // null // Find the first animal where the array key is the first symbol of the animal. array_find($array, function (string $value, $key) { return $value[0] === $key; }); Using Laravel's Arr or Collection you can get equivalent functionality with the first() method in combination with a closure: use Illuminate\Support\Arr; use Illuminate\Support\Collection; $array = [ 'a' => 'dog', 'b' => 'cat', 'c' => 'cow', 'd' => 'duck', 'e' => 'goose', 'f' => 'elephant' ]; new Collection($array) ->first(fn ($value) => strlen($value) > 4); // goose Arr::first( $array, fn ($value) => str_starts_with($value, 'f') ); // null new Collection($array) ->first(fn ($value, $key) => $value[0] === $key); // cow Note that we are demonstrating class instantiation without extra parenthesis, which should also be in PHP 8.4. The array_find_key() Function The array_find_key($array, $callback) function returns the key of the first element for which the $callback returns true. Like array_find(), it returns null if no matching element is found: $array = [ 'a' => 'dog', 'b' => 'cat', 'c' => 'cow', 'd' => 'duck', 'e' => 'goose', 'f' => 'elephant' ]; array_find_key($array, function (string $value) { return strlen($value) > 4; }); // string(1) "e" array_find_key($array, function (string $value) { return str_starts_with($value, 'f'); }); // null array_find_key($array, function (string $value, $key) { return $value[0] === $key; }); // string(1) "c" The RFC implementation for this function looks like the following: function array_find_key(array $array, callable $callback): mixed { foreach ($array as $key => $value) { if ($callback($value, $key)) { return $key; } }   return null; } Using Laravel's Collection, you can get functionality similar to the search() method in combination with a closure. However, search() returns false if the item is not found, not null: use Illuminate\Support\Arr; use Illuminate\Support\Collection; new Collection($array)->search(function (string $value) { return strlen($value) > 4; }); // string(1) "e" new Collection($array)->search(function (string $value) { return str_starts_with($value, 'f'); }); // false new Collection($array)->search(function (string $value, $key) { return $value[0] === $key; }); // string(1) "c" The array_any() and array_all() Functions The second part of the RFC (and a separate 2/3 vote) includes the array_any() and array_all() functions. You can use these functions if any of the items in array return true for array_any() and if all of the items in an array return true for array_all(), respectively. $array = [ 'a' => 'dog', 'b' => 'cat', 'c' => 'cow', 'd' => 'duck', 'e' => 'goose', 'f' => 'elephant' ]; // Check, if any animal name is longer than 5 letters. array_any($array, function (string $value) { return strlen($value) > 5; }); // bool(true) // Check, if any animal name is shorter than 3 letters. array_any($array, function (string $value) { return strlen($value) < 3; }); // bool(false) // Check, if all animal names are shorter than 12 letters. array_all($array, function (string $value) { return strlen($value) < 12; }); // bool(true)   // Check, if all animal names are longer than 5 letters. array_all($array, function (string $value) { return strlen($value) > 5; }); // bool(false) Learn More You can read all the details about this proposed change in the RFC. This feature likely drops in PHP 8.4. The implementation for these functions is currently in draft and can be found on GitHub. The post New Proposed Array Find Functions in PHP 8.4 appeared first on Laravel News. Join the Laravel Newsletter to get Laravel articles like this directly in your inbox.

A New Validation Rule and the Ability to Manually Fail a Command in Laravel 11.8
A New Validation Rule and the Ability to Manually Fail a Command in Laravel 11.8

This week, the Laravel team released v11.8, with a new validation rule, the ability to fail a command outside the handle() method, create a view during make:mail, and more. Show Events in the model:show Command Wendell Adriel contributed an Events section to the model:show command that displays any events defined on the $dispatchesEvents property: New contains Validation Rule Andrew Brown contributed a contains validation rule that checks to make sure expected values are included in the given array of input: return [ 'allowed_ips' => ['present', 'nullable', 'array', 'contains:' . $request->ip()], 'allowed_ips.*' => ['required', 'ip'], ]; In the PR's description, this example ensures that the user's IP is in the allowed_ips array. You can also pass multiple parameters, which would require that all parameters are present in the array of data. See Pull Request #51348 for more details. Ability to Manually Fail a Command Len Woodward contributed the ability to manually fail an Artisan command outside of the handle() method. Like the Queue's $this->fail() convenience method, commands can now manually fail a job: public function handle() { $this->trigger_failure(); } protected function trigger_failure() { $this->fail('Whoops!'); } See Pull Request #51435 for implementation details and examples of how this method could be useful over a few other existing approaches to failing early in a command. Create a Blade View With make:mail Ryan Chandler contributed a --view flag to the make:mail command that will create an empty Blade file and configure the created Mailable to use it by default. It works the same way as the existing --markdown option and saves the manual step of creating and wiring up a Blade mail template. php artisan make:mail OrderShipped --view=mail.orders.shipped Release notes You can see the complete list of new features and updates below and the diff between 11.7.0 and 11.8.0 on GitHub. The following release notes are directly from the changelog: v11.8.0 [11.x] Update PendingRequest.php by @foremtehan in https://github.com/laravel/framework/pull/51338 Add unshift method to Collection by @timkelty in https://github.com/laravel/framework/pull/51344 [11.x] Synchronizing cache configuration file with updated laravel v11.0.7 by @dvlpr91 in https://github.com/laravel/framework/pull/51336 [11.x] Utilize null-safe operator instead of conditional check by @saMahmoudzadeh in https://github.com/laravel/framework/pull/51328 [11.x] Add the events to be displayed on the model:show command by @WendellAdriel in https://github.com/laravel/framework/pull/51324 [11.x] fix: remove use of Redis::COMPRESSION_ZSTD_MIN by @calebdw in https://github.com/laravel/framework/pull/51346 [10.x] Backport: Fix SesV2Transport to use correct EmailTags argument by @Tietew in https://github.com/laravel/framework/pull/51352 [11.x] feat: use phpredis 6 in ci by @calebdw in https://github.com/laravel/framework/pull/51347 [11.x] create new "has" validation rule by @browner12 in https://github.com/laravel/framework/pull/51348 [11.x] Add support for previous apps keys in signed URL verification by @Krisell in https://github.com/laravel/framework/pull/51222 [11.x] Allow setting exit code in migrate:status --pending by @brecht-vermeersch in https://github.com/laravel/framework/pull/51341 [11.x] Fix array rule typehint by @erik-perri in https://github.com/laravel/framework/pull/51372 [11.x] Test Improvements by @crynobone in https://github.com/laravel/framework/pull/51365 [10.x] Fix PHPDoc typo by @staudenmeir in https://github.com/laravel/framework/pull/51390 [11.x] Fix return type hint of resolveRouteBindingQuery by @philbates35 in https://github.com/laravel/framework/pull/51392 [11.x] Allow adding array or string for web and api routes in bootstrap/app.php by @mrthito in https://github.com/laravel/framework/pull/51356 [ 11.x ] Adds ability to manually fail a command from outside the handle() method by @ProjektGopher in https://github.com/laravel/framework/pull/51435 [10.x] Fix apa on non ASCII characters by @faissaloux in https://github.com/laravel/framework/pull/51428 [11.x] Compare lowercased column names in getColumnType by @chady in https://github.com/laravel/framework/pull/51431 [11.x] Use contracts instead of concrete type for resolveRouteBindingQuery() by @crynobone in https://github.com/laravel/framework/pull/51425 [11.x] Set the value of $this in macro closures by @simonwelsh in https://github.com/laravel/framework/pull/51401 [11.x] Add missing roundrobin transport driver config by @u01jmg3 in https://github.com/laravel/framework/pull/51400 [11.x] Remove unused namespace by @saMahmoudzadeh in https://github.com/laravel/framework/pull/51436 [11.x] Fixes doc block in Connector.php by @saMahmoudzadeh in https://github.com/laravel/framework/pull/51440 [10.x] Fixes view engine resolvers leaking memory by @nunomaduro in https://github.com/laravel/framework/pull/51450 [11.x] Add some tests to SupportStrTest by @saMahmoudzadeh in https://github.com/laravel/framework/pull/51437 [11.x] Add isCurrentlyOwnedBy function to lock by @gazben in https://github.com/laravel/framework/pull/51393 [11.x] Collection average/avg optimization by @bert-w in https://github.com/laravel/framework/pull/51512 [11.x] Introduce MixManifestNotFoundException for handling missing Mix manifests by @xurshudyan in https://github.com/laravel/framework/pull/51502 [11.x] MailMakeCommand: Add new --view option by @ryangjchandler in https://github.com/laravel/framework/pull/51411 [11.x] Replace all backed enums with values when building URLs by @stefanvdlugt in https://github.com/laravel/framework/pull/51524 [10.x] Do not use app() Foundation helper on ViewServiceProvider by @rodrigopedra in https://github.com/laravel/framework/pull/51522 Fixes explicit route binding with BackedEnum by @crynobone in https://github.com/laravel/framework/pull/51525 [11.x] Add query method to UrlGenerator contract docblock by @hjanos-bc in https://github.com/laravel/framework/pull/51515 The post A New Validation Rule and the Ability to Manually Fail a Command in Laravel 11.8 appeared first on Laravel News. Join the Laravel Newsletter to get Laravel articles like this directly in your inbox.