Our Global Presence
Canada
57 Sherway St,
Stoney Creek, ON
L8J 0J3
India
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
USA
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
This transition is intended to ease the maintenance burden on the community and challenge our development team to ship amazing, powerful new features without introducing breaking changes. Therefore, we have shipped a variety of robust features to Laravel 8 without breaking backwards compatibility, such as parallel testing support, improved Breeze starter kits, HTTP client improvements, and even new Eloquent relationship types such as “has one of many”.
Therefore, this commitment to ship great new features during the current release will likely lead to future “major” releases being primarily used for “maintenance” tasks such as upgrading upstream dependencies, which can be seen in these release notes.
Laravel 9 continues the improvements made in Laravel 8.x by introducing support for Symfony 6.0 components, Symfony Mailer, Flysystem 3.0, improved route:list output, a Laravel Scout database driver, new Eloquent accessor / mutator syntax, implicit route bindings via Enums, and a variety of other bug fixes and usability improvements.
Laravel 9.x requires a minimum PHP version of 8.0.
Laravel 9.x upgrades our upstream Flysystem dependency to Flysystem 3.x. Flysystem powers all of filesystem interactions offered by the Storage facade.
Please review the upgrade guide to learn more about ensuring your application is compatible with Flysystem 3.x.
Laravel 9.x offers a new way to define Eloquent accessors and mutators. In previous releases of Laravel, the only way to define accessors and mutators was by defining prefixed methods on your model like so:
public function getNameAttribute($value) { return strtoupper($value); } public function setNameAttribute($value) { $this->attributes['name'] = $value; }
However, in Laravel 9.x you may define an accessor and mutator using a single, non-prefixed method by type-hinting a return type of Illuminate\Database\Eloquent\Casts\Attribute:
use Illuminate\Database\Eloquent\Casts\Attribute; public function name(): Attribute { return new Attribute( get: fn ($value) => strtoupper($value), set: fn ($value) => $value, ); }
In addition, this new approach to defining accessors will cache object values that are returned by the attribute, just like custom cast classes:
use App\Support\Address; use Illuminate\Database\Eloquent\Casts\Attribute; public function address(): Attribute { return new Attribute( get: fn ($value, $attributes) => new Address( $attributes['address_line_one'], $attributes['address_line_two'], ), set: fn (Address $value) => [ 'address_line_one' => $value->lineOne, 'address_line_two' => $value->lineTwo, ], ); }
Enum casting is only available for PHP 8.1+.
Eloquent now allows you to cast your attribute values to PHP “backed” enums. To accomplish this, you may specify the attribute and enum you wish to cast in your model’s $casts property array:
use App\Enums\ServerStatus; /** * The attributes that should be cast. * * @var array */ protected $casts = [ 'status' => ServerStatus::class, ];
Once you have defined the cast on your model, the specified attribute will be automatically cast to and from an enum when you interact with the attribute:
if ($server->status == ServerStatus::provisioned) { $server->status = ServerStatus::ready; $server->save(); }
PHP 8.1 introduces support for Enums. Laravel 9.x introduces the ability to type-hint an Enum on your route definition and Laravel will only invoke the route if that route segment is a valid Enum value in the URI. Otherwise, an HTTP 404 response will be returned automatically. For example, given the following Enum:
enum Category: string { case Fruits = 'fruits'; case People = 'people'; }
You may define a route that will only be invoked if the {category} route segment is fruits or people. Otherwise, an HTTP 404 response will be returned:
Route::get('/categories/{category}', function (Category $category) { return $category->value; });
In previous releases of Laravel, you may wish to scope the second Eloquent model in a route definition such that it must be a child of the previous Eloquent model. For example, consider this route definition that retrieves a blog post by slug for a specific user:
use App\Models\Post; use App\Models\User; Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) { return $post; });
When using a custom keyed implicit binding as a nested route parameter, Laravel will automatically scope the query to retrieve the nested model by its parent using conventions to guess the relationship name on the parent. However, this behavior was only previously supported by Laravel when a custom key was used for the child route binding.
However, in Laravel 9.x, you may now instruct Laravel to scope “child” bindings even when a custom key is not provided. To do so, you may invoke the scopeBindings method when defining your route:
use App\Models\Post; use App\Models\User; Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) { return $post; })->scopeBindings();
Or, you may instruct an entire group of route definitions to use scoped bindings:
Route::scopeBindings()->group(function () { Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) { return $post; }); });
You may now use the controller method to define the common controller for all of the routes within the group. Then, when defining the routes, you only need to provide the controller method that they invoke:
use App\Http\Controllers\OrderController; Route::controller(OrderController::class)->group(function () { Route::get('/orders/{id}', 'show'); Route::post('/orders', 'store'); });
When using MySQL or PostgreSQL, the fullText method may now be added to column definitions to generate full text indexes:
$table->text('bio')->fullText();
In addition, the whereFullText and orWhereFullText methods may be used to add full text “where” clauses to a query for columns that have full text indexes. These methods will be transformed into the appropriate SQL for the underlying database system by Laravel. For example, a MATCH AGAINST clause will be generated for applications utilizing MySQL:
$users = DB::table('users') ->whereFullText('bio', 'web developer') ->get();
If your application interacts with small to medium sized databases or has a light workload, you may now use Scout’s “database” engine instead of a dedicated search service such as Algolia or MeiliSearch. The database engine will use “where like” clauses and full text indexes when filtering results from your existing database to determine the applicable search results for your query.
Sometimes you may need to transform a raw Blade template string into valid HTML. You may accomplish this using the render method provided by the Blade facade. The render method accepts the Blade template string and an optional array of data to provide to the template:
use Illuminate\Support\Facades\Blade; return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);
Similarly, the renderComponent method may be used to render a given class component by passing the component instance to the method:
use App\View\Components\HelloComponent; return Blade::renderComponent(new HelloComponent('Julian Bashir'));
In previous releases of Laravel, slot names were provided using a name attribute on the x-slot tag:
<x-alert> <x-slot name="title"> Server Error </x-slot> <strong>Whoops!</strong> Something went wrong! </x-alert>
However, beginning in Laravel 9.x, you may specify the slot’s name using a convenient, shorter syntax:
<x-slot:title> Server Error </x-slot>
For convenience, you may now use the @checked directive to easily indicate if a given HTML checkbox input is “checked”. This directive will echo checked if the provided condition evaluates to true:
<input type="checkbox" name="active" value="active" @checked(old('active', $user->active)) />
Likewise, the @selected directive may be used to indicate if a given select option should be “selected”:
<select name="version"> @foreach ($product->versions as $version) <option value="{{ $version }}" @selected(old('version') == $version)> {{ $version }} </option> @endforeach </select>
Laravel now includes pagination views built using Bootstrap 5. To use these views instead of the default Tailwind views, you may call the paginator’s useBootstrapFive method within the boot method of your App\Providers\AppServiceProvider class:
use Illuminate\Pagination\Paginator; /** * Bootstrap any application services. * * @return void */ public function boot() { Paginator::useBootstrapFive(); }
For more information and to develop web applications using Laravel, Hire Laravel Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”.
To develop custom web apps using Laravel, please visit our technology page.
Content Source:
Laravel Forge launched their first official command-line tool that gives you a nice set of commands to manage your Forge servers, sites, and more.
The first release (v1.0) of the Forge CLI contains around thirty commands, including initiating deployments, viewing application logs, configuring SSH key authentication, and more.
You may install the Forge CLI as a global Composer dependency:
composer global require laravel/forge-cli
After it’s installed you can forge from your terminal and see usage:
To view a list of all available Forge CLI commands and view the current version of your installation, you may run the forge
command from the command-line:
forge
You will need to generate an API token to interact with the Forge CLI. Tokens are used to authenticate your account without providing personal details. API tokens can be created from Forge’s API dashboard (opens new window).
After you have generated an API token, you should authenticate with your Forge account using the login command:
forge login
When managing Forge servers, sites, and resources via the CLI, you will need to be aware of your currently active server. You may view your current server using the server:current
command. Typically, most of the commands you execute using the Forge CLI will be executed against the active server.
forge server:current
Of course, you may switch your active server at any time. To change your active server, use the server:switch
command:
forge server:switch forge server:switch staging
To view a list of all available servers, you may use the server:list
command:
forge server:list
Before performing any tasks using the Forge CLI, you should ensure that you have added an SSH key for the forge
user to your servers so that you can securely connect to them. You may have already done this via the Forge UI. You may test that SSH is configured correctly by running the ssh:test
command:
forge ssh:test
To configure SSH key authentication, you may use the ssh:configure
command. The ssh:configure
command accepts a --key
option which instructs the CLI which public key to add to the server. In addition, you may provide a --name
option to specify the name that should be assigned to the key:
forge ssh:configure forge ssh:configure --key=/path/to/public/key.pub --name=sallys-macbook
After you have configured SSH key authentication, you may use the ssh
command to create a secure connection to your server:
forge ssh forge ssh server-name
To view the list of all available sites, you may use the site:list
command:
forge site:list
One of the primary features of Laravel Forge is deployments. Deployments may be initiated via the Forge CLI using the deploy
command:
forge deploy forge deploy example.com
You may update a site’s environment variables using the env:pull
and env:push
commands. The env:pull
command may be used to pull down an environment file for a given site:
forge env:pull forge env:pull pestphp.com forge env:pull pestphp.com .env
Once this command has been executed the site’s environment file will be placed in your current directory. To update the site’s environment variables, simply open and edit this file. When you are done editing the variables, use the env:push
command to push the variables back to your site:
forge env:push forge env:push pestphp.com forge env:push pestphp.com .env
If your site is utilizing Laravel’s “configuration caching” feature or has queue workers, the new variables will not be utilized until the site is deployed again.
You may also view a site’s logs directly from the command-line. To do so, use the site:logs
command:
forge site:logs forge site:logs --follow # View logs in realtime forge site:logs example.com forge site:logs example.com --follow # View logs in realtime
When a deployment fails, you may review the output / logs via the Forge UI’s deployment history screen. You may also review the output at any time on the command-line using the deploy:logs
command. If the deploy:logs
command is called with no additional arguments, the logs for the latest deployment will be displayed. Or, you may pass the deployment ID to the deploy:logs
command to display the logs for a particular deployment:
forge deploy:logs forge deploy:logs 12345
Sometimes you may wish to run an arbitrary shell command against a site. The command
command will prompt you for the command you would like to run. The command will be run relative to the site’s root directory.
forge command forge command example.com forge command example.com --command="php artisan inspire"
As you may know, all Laravel applications include “Tinker” by default. To enter a Tinker environment on a remote server using the Forge CLI, run the tinker
command:
forge tinker forge tinker example.com
Forge provisions servers with a variety of resources and additional software, such as Nginx, MySQL, etc. You may use the Forge CLI to perform common actions on those resources.
To check the current status of a resource, you may use the {resource}:status
command:
forge daemon:status forge database:status forge nginx:status forge php:status # View PHP logs (default PHP version) forge php:status 8.0 # View PHP 8.0 logs
You may also view logs directly from the command-line. To do so, use the {resource}:logs
command:
forge daemon:logs forge daemon:logs --follow # View logs in realtime forge database:logs forge nginx:logs # View error logs forge nginx:logs access # View access logs forge php:logs # View PHP logs (default PHP version) forge php:logs 8.0 # View PHP 8.0 logs
Resources may be restarted using the {resource}:restart
command:
forge daemon:restart forge database:restart forge nginx:restart forge php:restart # Restarts PHP (default PHP version) forge php:restart 8.0 # Restarts PHP 8.0
You may use the {resource}:shell
command to quickly access a command line shell that lets you interact with a given resource:
forge database:shell forge database:shell my-database-name forge database:shell my-database-name --user=my-user
For more information and to develop web applications using Laravel, Hire Laravel Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”.
To develop custom web apps using Laravel, please visit our technology page.
Content Source:
In the next release of Laravel 8, you can strictly disable lazy loading entirely, resulting in an exception:
Preventing lazy loading in development can help you catch N+1 bugs earlier on in the development process. The Laravel ecosystem has various tools to identify N+1 queries. However, this approach brings the issue front-and-center by throwing an exception.
Let’s walk through this feature real quick by spinning up a development version of the framework 8.x branch since this feature is not out yet at the time of writing. Once released, you will have this feature without switching to the latest 8.x branch.
First, create a new application:
laravel new strict-lazy-demo
Next, we’ll update the laravel/framework version in composer.json to make sure we have this feature (if you’re trying it out before the next release) by adjusting the version to 8.x-dev:
{ "require": { "laravel/framework": "8.x-dev" } }
Next, run composer update to make sure you get the latest version of the code for this branch:
composer update laravel/framework
At this point, you should set up your preferred database. We like running a local MySQL instance using Laravel’s defaults of using the root user without a password. We find it convenient to use the default .env values locally to get started quickly without any configuration.
mysql -uroot -e"create database strict_lazy_demo"
Once you configure your database of choice, make sure you can migrate:
php artisan migrate:fresh
We’ll create a Post model and define a one-to-many relationship from the User model to demonstrate this feature. We’ll start by creating the Post model and accompanying files:
# Create a model with migration and factory php artisan make:model -mf Post
First, let’s define our Post migration and factory configuration:
// Your filename will differ based on when you create the file. // 2021_05_21_000013_create_posts_table.php Schema::create('posts', function (Blueprint $table) { $table->id(); $table->foreignIdFor(\App\Models\User::class); $table->string('title'); $table->longText('body'); $table->timestamps(); });
Next, define your PostFactory definition method based on the above schema:
/** * Define the model's default state. * * @return array */ public function definition() { return [ 'user_id' => \App\Models\User::factory(), 'title' => $this->faker->sentence(), 'body' => implode("\n\n", $this->faker->paragraphs(rand(2,5))), ]; }
Finally, open up the DatabaseSeeder file and add the following in the run() method:
/** * Seed the application's database. * * @return void */ public function run() { \App\Models\User::factory() ->has(\App\Models\Post::factory()->count(3)) ->create() ; }
Now that we have the migration, seeder, and model created, we are ready to associate a User with the Post model to demo this feature.
Add the following method to the User model to give the user an association with Posts:
// app/Models/User.php /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function posts() { return $this->hasMany(Post::class); }
With that in place, we can migrate and seed the database:
php artisan migrate:fresh --seed
If all went well, we should see something like the following in the console:
We can now using tinker to inspect our seeded data and relationship:
php artisan tinker >>> $user = User::first() => App\Models\User {#4091 id: 1, name: "Nedra Hayes", email: "bruen.marc@example.com", email_verified_at: "2021-05-21 00:35:59", created_at: "2021-05-21 00:35:59", updated_at: "2021-05-21 00:35:59", } >>> $user->posts => Illuminate\Database\Eloquent\Collection {#3686 all: [ App\Models\Post {#3369 id: 1, ...
The $user->posts
property actually calls the database, thus is “lazy” but is not optimized. The convenience of lazy-loading is nice, but it can come with heavy performance burdens in the long-term.
Now that we have the models set up, we can disable lazy loading across our application. You’d likely want to only disable in non-production environments, which is easy to achieve! Open up the AppServiceProvider class and add the following to the boot() method:
// app/Providers/AppServiceProvider.php public function boot() { Model::preventLazyLoading(! app()->isProduction()); }
If you run a php artisan tinker session again, this time you should get an exception for a lazy loading violation:
php artisan tinker >>> $user = \App\Models\User::first() => App\Models\User {#3685 id: 1, name: "Nedra Hayes", email: "bruen.marc@example.com", email_verified_at: "2021-05-21 00:35:59", #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi", #remember_token: "jHSxFGKOdw", created_at: "2021-05-21 00:35:59", updated_at: "2021-05-21 00:35:59", } >>> $user->posts Illuminate\Database\LazyLoadingViolationException with message 'Attempted to lazy load [posts] on model [App\Models\User] but lazy loading is disabled.'
If you want to visualize what happens if you use lazy loading in a view file, modify the default route as follows:
Route::get('/', function () { return view('welcome', [ 'user' => \App\Models\User::first() ]); });
Next, add the following somewhere in the welcome.blade.php file:
<h2>Posts</h2> @foreach($user->posts as $post) <h3>{{ $post->title }}</h3> <p> {{ $post->body }} </p> @endforeach
If you load up your application through Valet or artisan serve, you should see something like the following error page:
Though you’ll get exceptions during development, accidentally deploying code that triggers lazy-loading will continue to work as long as you set environment checking correctly in the service provider.
For more information and to develop web applications using Laravel, Hire Laravel Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”.
To develop custom web apps using Laravel, please visit our technology page.
Content Source:
Application Performance Monitoring (APM), as the name suggests, is the process of monitoring the performance of the many aspects of your application.
When an end-user logs into your application, for even just one web page to load on their device, there are very many backstage components that need to come together and operate in synchrony to ensure a smooth and fast experience. These include network components (that carry the bytes of data), software components (e.g., server-side frameworks, front-end code, and other dependencies), and hardware components (i.e., CPU processors, memory, and storage of machines that host your web servers, APIs, databases, file systems, etc.) It can become overwhelming to manually keep track of your application performance on all these different levels and across all components. This is even truer when you ideally want monitoring and checks to happen all the time, in real-time!
Well, this is precisely the problem that APM solutions target. APM tools, like ScoutAPM, allow organizations to get a detailed analysis of the performance of your applications, in real-time. This includes critical information about server requests, response times, time-consuming methods and end-points, errors and their root cause analysis, and lots more – presented in a way that is easy to understand and troubleshoot.
These performance insights provide a lot of valuable information about optimizing resource allocations and effective cost reductions while surfacing other issues that could potentially fail your application – and all before the user gets a hint of anything being amiss.
Apart from presenting a bird’s eye view of what is happening within your application as a whole, APM tools provide you with your application’s score on particular metrics that quantify its performance along different grounds.
They provide metrics like request rates, response times, server load, CPU and memory usage, application throughput, server health status, and lots more, enabling organizations to understand what drives their application’s performance or failures.
They bring to light and help you identify performance bottlenecks, memory leaks, bloat, slow database queries, wasted execution cycles, and much more in your application. Additionally, tools like ScoutAPM enable teams to trace the cause of these issues to the specific line of the code causing them so that developers need to spend less time debugging and more time building.
Different platforms, frameworks, and APIs allow you to monitor the performance of a few of your applications’ components – for example, your cloud service provider could provide information about resource usage, logging frameworks could help you capture backend errors and processing times, etc. But wouldn’t it be much more useful to have everything you need under one roof – as a one-stop platform to provide all the information about everything you might need to know about your application’s performance.
Different organizations might want to optimize their application’s performance on different metrics. Some teams might want to prioritize more reliability and uptime, over other applications that might want to focus on higher speeds and lower response times. In this regard, equally important is the amount of flexibility that many of these tools offer in creating customizable dashboards – allowing you to focus on aspects of performance that matter the most to your application.
APM tools, therefore, can go a long way in resolving issues faster, preventing interruptions, boosting performance, increasing business and revenue, and understanding customer interactions.
Let us look at some common use cases of APM solutions to get a pragmatic understanding of how helpful they can be for developers and organizations to ensure that everything about their application is on track.
Application development involves a lot of code tweaking, solving bugs, adding features, experimenting with different libraries and frameworks, refactoring, and so on. This can lead to minor fluctuations in performance that developers might want to track and monitor throughout the development lifecycle and in the staging and production environments.
Therefore, application development can benefit a great deal from the insights provided by APM tools. These could be insights about the application’s performance or an in-depth analysis of issues down to the code level. By highlighting the source of the problem and isolating issues to specific lines (or methods) in the code causing them, these tools narrow down the areas of the project that they should be focusing more on.
Below is an example of code traceability in ScoutAPM, with Github integration enabled.
A bottleneck in software engineering refers to the negative effect on performance caused by the limited ability or capacity of one component of the system – similar to impeding water flow caused near a bottle’s constricted neck. A bottleneck is like the slower car on a single-track road that keeps everyone else waiting.
Even with the best software and hardware infrastructure in place, all it takes is one sub-optimal component to make your application crawl when it could be flying. APM tools help you identify performance bottlenecks with accuracy. These range from bottlenecks in disk usage, CPU utilization, memory to software and network components. APM platforms like Scout provide a complete analysis of several metrics like the memory allocation, response times, throughput, and error rates corresponding to each end-point in your application. Metrics like these provide insights into the long-term performance of these applications and help highlight where such bottlenecks lie.
It is important to note that if you are just starting out with web development, and working on smaller, personal projects, understanding the importance of APM tools might not come easily or seem super relevant. However, these tools become exponentially more valuable as your application(s) scale-up and cater to hundreds or thousands of users.
For more information and to develop web applications using Laravel, Hire Laravel Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”.
To develop custom web apps using Laravel, please visit our technology page.
Content Source:
PHP 8 is here! PHP 8 is a new major improved version, which means that it will introduce performance improvements and lots of new features such as the JIT compiler, union types, attributes, and more.
Let’s start with all new features, it’s quite a list!
Given the dynamically typed nature of PHP, there are lots of cases where union types can be useful. Union types are a collection of two or more types which indicate that either one of those can be used.
public function foo(Foo|Bar $input): int|float;
Note that void can never be part of a union type, since it indicates “no return value at all”. Furthermore, nullable unions can be written using |null, or by using the existing ? notation:
public function foo(Foo|null $foo): void; public function bar(?Bar $bar): void;
The JIT — just in time — compiler promises significant performance improvements, albeit not always within the context of web requests. I’ve done my own benchmarks on real-life web applications, and it seems like the JIT doesn’t make that much of a difference, if any, on those kinds of PHP projects.
If you’re familiar with the null coalescing operator you’re already familiar with its shortcomings: it doesn’t work on method calls. Instead you need intermediate checks, or rely on optional helpers provided by some frameworks:
$startDate = $booking->getStartDate(); $dateAsString = $startDate ? $startDate->asDateTimeString() : null;
With the addition of the nullsafe operator, we can now have null coalescing-like behaviour on methods!
$dateAsString = $booking->getStartDate()?->asDateTimeString();
Named arguments allow you to pass in values to a function, by specifying the value name, so that you don’t have to take their order into consideration, and you can also skip optional parameters!
function foo(string $a, string $b, ?string $c = null, ?string $d = null) { /* … */ } foo( b: 'value b', a: 'value a', d: 'value d', );
Attributes, commonly known as annotations in other languages, offers a way to add meta data to classes, without having to parse docblocks.
As for a quick look, here’s an example of what attributes look like, from the RFC:
use App\Attributes\ExampleAttribute; #[ExampleAttribute] class Foo { #[ExampleAttribute] public const FOO = 'foo'; #[ExampleAttribute] public $x; #[ExampleAttribute] public function foo(#[ExampleAttribute] $bar) { } }
#[Attribute] class ExampleAttribute { public $value; public function __construct($value) { $this->value = $value; } }
Note that this base Attribute used to be called PhpAttribute in the original RFC, but was changed with another RFC afterwards. If you want to take a deep dive in how attributes work, and how you can build your own; you can read about attributes in depth on this blog.
You could call it the big brother of the switch expression: match can return values, doesn’t require break statements, can combine conditions, uses strict type comparisons and doesn’t do any type coercion.
It looks like this:
$result = match($input) { 0 => "hello", '1', '2', '3' => "world", };
This RFC adds syntactic sugar to create value objects or data transfer objects. Instead of specifying class properties and a constructor for them, PHP can now combine them into one.
Instead of doing this:
class Money { public Currency $currency; public int $amount; public function __construct( Currency $currency, int $amount, ) { $this->currency = $currency; $this->amount = $amount; } }
You can now do this:
class Money { public function __construct( public Currency $currency, public int $amount, ) {} }
While it was already possible to return self, static wasn’t a valid return type until PHP 8. Given PHP’s dynamically typed nature, it’s a feature that will be useful to many developers.
class Foo { public function test(): static { return new static(); } }
Some might call it a necessary evil: the mixed type causes many to have mixed feelings. There’s a very good argument to make for it though: a missing type can mean lots of things in PHP:
Because of the reasons above, it’s a good thing the mixed type is added. mixed itself means one of these types:
Note that mixed can also be used as a parameter or property type, not just as a return type.
Also note that since mixed already includes null, it’s not allowed to make it nullable. The following will trigger an error:
// Fatal error: Mixed types cannot be nullable, null is already part of the mixed type. function bar(): ?mixed {}
This RFC changes throw from being a statement to being an expression, which makes it possible to throw exception in many new places:
$triggerError = fn () => throw new MyError(); $foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset');
Previously, PHP used to apply the same inheritance checks on public, protected and private methods. In other words: private methods should follow the same method signature rules as protected and public methods. This doesn’t make sense, since private methods won’t be accessible by child classes.
This RFC changed that behaviour, so that these inheritance checks are not performed on private methods anymore. Furthermore, the use of final private function also didn’t make sense, so doing so will now trigger a warning:
Warning: Private methods cannot be final as they are never overridden by other classes
A small, yet useful, new feature: it’s now possible to use ::class on objects, instead of having to use get_class() on them. It works the same way as get_class().
$foo = new Foo(); var_dump($foo::class);
Whenever you wanted to catch an exception before PHP 8, you had to store it in a variable, regardless whether you used that variable or not. With non-capturing catches, you can omit the variable, so instead of this:
try { // Something goes wrong } catch (MySpecialException $exception) { Log::error("Something went wrong"); }
You can now do this:
try { // Something goes wrong } catch (MySpecialException) { Log::error("Something went wrong"); }
Note that it’s required to always specify the type, you’re not allowed to have an empty catch. If you want to catch all exceptions and errors, you can use Throwable as the catching type.
Already possible when calling a function, trailing comma support was still lacking in parameter lists. It’s now allowed in PHP 8, meaning you can do the following:
public function( string $parameterA, int $parameterB, Foo $objectfoo, ) { // … }
You can already create a DateTime object from a DateTimeImmutable object using DateTime::createFromImmutable($immutableDateTime), but the other way around was tricky. By adding DateTime::createFromInterface() and DatetimeImmutable::createFromInterface() there’s now a generalised way to convert DateTime and DateTimeImmutable objects to each other.
DateTime::createFromInterface(DateTimeInterface $other); DateTimeImmutable::createFromInterface(DateTimeInterface $other);
The Stringable interface can be used to type hint anything that implements __toString(). Whenever a class implements __toString(), it automatically implements the interface behind the scenes and there’s no need to manually implement it.
class Foo { public function __toString(): string { return 'foo'; } } function bar(string|Stringable $stringable) { /* … */ } bar(new Foo()); bar('abc');
Some might say it’s long overdue, but we finally don’t have to rely on strpos() anymore to know whether a string contains another string.
Instead of doing this:
if (strpos('string with lots of words', 'words') !== false) { /* … */ }
You can now do this
if (str_contains('string with lots of words', 'words')) { /* … */ }
Two other ones long overdue, these two functions are now added in the core.
str_starts_with('haystack', 'hay'); // true str_ends_with('haystack', 'stack'); // true
The new fdiv() function does something similar as the fmod() and intdiv() functions, which allows for division by 0. Instead of errors you’ll get INF, -INF or NAN, depending on the case.
get_debug_type() returns the type of a variable. Sounds like something gettype() would do? get_debug_type() returns more useful output for arrays, strings, anonymous classes and objects.
For example, calling gettype() on a class \Foo\Bar would return object. Using get_debug_type() will return the class name.
A full list of differences between get_debug_type() and gettype() can be found in the RFC.
Resources are special variables in PHP, referring to external resources. One example is a MySQL connection, another one a file handle.
Each one of those resources gets assigned an ID, though previously the only way to know that id was to cast the resource to int:
$resourceId = (int) $resource;
PHP 8 adds the get_resource_id() functions, making this operation more obvious and type-safe:
$resourceId = get_resource_id($resource);
Traits can specify abstract methods which must be implemented by the classes using them. There’s a caveat though: before PHP 8 the signature of these method implementations weren’t validated. The following was valid:
trait Test { abstract public function test(int $input): int; } class UsesTrait { use Test; public function test($input) { return $input; } }
PHP 8 will perform proper method signature validation when using a trait and implementing its abstract methods. This means you’ll need to write this instead:
class UsesTrait { use Test; public function test(int $input): int { return $input; } }
The token_get_all() function returns an array of values. This RFC adds a PhpToken class with a PhpToken::tokenize() method. This implementation works with objects instead of plain values. It consumes less memory and is easier to read.
From the RFC: “the Uniform Variable Syntax RFC resolved a number of inconsistencies in PHP’s variable syntax. This RFC intends to address a small handful of cases that were overlooked.”
Lots of people pitched in to add proper type annotations to all internal functions. This was a long standing issue, and finally solvable with all the changes made to PHP in previous versions. This means that internal functions and methods will have complete type information in reflection.
Previously it was possible to compile PHP without the JSON extension enabled, this is not possible anymore. Since JSON is so widely used, it’s best developers can always rely on it being there, instead of having to ensure the extension exist first.
For more information and to develop web application using PHP, WordPress OR Laravel, Hire PHP Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using PHP, Laravel or WordPress, please visit our technology page.
Content Source:
Media Library can associate files with Eloquent models. You can, for instance, associate images with a blog post model. In your Blade view, you can retrieve URLs to the associated images. It can handle multiple collections, work with multiple filesytems, create zips on the fly to download multiple files, use a customized directory structure, save bandwidth using responsive images and much more.
Before exploring Media Library Pro, let’s first explained why we built it in the first place. Here’s how a traditional upload form might look like. It uses a regular input of type file.
<form method="POST" enctype="multipart/form-data"> <x-grid> @csrf <x-field label="name"> <x-input id="name" name="name" placeholder="Your first name" /> </x-field> <x-field label="file"> <input type="file" name="file"> @error('file') {{ $message }} @enderror </x-field> <x-button dusk="submit">Submit</x-button> </x-grid> </form>
There are two big problems with this standard upload element.
First, the upload process only starts when the form is submitted. For small files in small forms, this might not be a problem. But imagine you’re uploading a multi MB file in a form. When submitting the form, you now have to wait for the upload to complete before seeing the submission results.
The second problem is something that has bothered us for a long, long time. Imagine that the input field is part of a form of which some fields are required. You’re selecting a file, submitting the form, leaving some of the required fields empty. You get redirected back to the form where error messages are now displayed. Your previous file selection is gone, and you need to select the file again.
Media Library Pro is a paid add-on package that offers Blade, Vue, and React components to upload files to your application. It ships with two components. The first one is the attachment component. It is meant to be used on a public-facing page where you want users to upload one or multiple files.
The second one is called the collection component. This one can manage the files in an existing collection. It is meant to be used in the admin part of your app.
Both of these components are available as Vue, React and Blade components. Under the hood, the Blade components are powered by Caleb’s excellent Livewire package.
These components are straightforward to install and are documented in great detail.
Let’s take a look at both the `Attachment` and `Collection` component. In the remainder of the blog post, we’ll use the Blade version of the examples, but rest assured that everything shown can also be done with the Vue and React counterparts.
To get started with the Attachment Blade component you’ll have to use x-media-library-attachment in your view.
<form method="POST"> @csrf <input id="name" name="name"> <x-media-library-attachment name="avatar"/> <button type="submit">Submit</button> </form>
Here’s how it looks like after we’ve selected a file but before submitting the form.
The x-media-library-attachment has taken care of the upload. The file is now stored as a temporary upload. In case there are validation errors when submitting the form, the x-media-library-attachment will display the temporary upload when you get redirected back to the form. There’s no need for the user to upload the file again.
Here’s the form request used to validate the uploaded.
namespace App\Http\Requests\Blade; use Illuminate\Foundation\Http\FormRequest; use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia; class StoreBladeAttachmentRequest extends FormRequest { use ValidatesMedia; public function rules() { return [ 'name' => 'required', 'media' => ['required', $this->validateSingleMedia() ->maxItemSizeInKb(3000), ], ]; } }
By applying the ValidatesMedia trait, you get access to the validateSingleMedia, which allows you to validate the upload. You can chain on many validation methods, which are documented here.
In your controller, you can associate the upload file to any model you’d like.
$formSubmission ->addFromMediaLibraryRequest($request->media) ->toMediaCollection('images');
And that is all you need to do!
The attachment component can be used to handle multiple uploads as well. In this video, you’ll see how that is done.
You can manage the entire contents of a media library collection with x-media-library-collection component. This
component is intended to use in admin sections.
Here is an example where we will administer an images collection of a $formSubmission model.
<form method="POST"> @csrf <x-field label="name"> <x-input id="name" name="name" autocomplete="off" placeholder="Your name" value="{{ old('name', $formSubmission->name) }}"/> </x-field> <x-field label="Images"> <x-media-library-collection name="images" :model="$formSubmission" collection="images" max-items="3" rules="mimes:png,jpeg" /> </x-field> <x-button dusk="submit" type="submit">Submit</x-button> </form>
Here’s how that component looks like:
This component will display the contents of the entire collection. Files can be added, removed, updated, and reordered.
To validate the response of the form, a form request like this one can be used:
namespace App\Http\Requests\Blade; use Illuminate\Foundation\Http\FormRequest; use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia; class StoreBladeCollectionRequest extends FormRequest { use ValidatesMedia; public function rules() { return [ 'name' => 'required', 'images' => [$this->validateMultipleMedia() ->maxItems(3) ->itemName('required'), ], ]; } }
Again, you need to ValidatesMedia trait. This time the validateMultipleMedia should be used. You can chain on the other validation methods, which are documented here.
In the controller, you can associate the media in the collection component with your model using the syncFromMediaLibraryRequest method.
Here’s the relevant code in the controller of the demo app.
$formSubmission ->syncFromMediaLibraryRequest($request->images) ->toMediaCollection('images');
When using the collection component, you probably want to add some extra fields to be displayed. We’ve made this a straightforward thing to do.
In the screenshot below, we added the Extra field field.
You can achieve this by passing a blade view to the fields-view prop of the x-media-library-collection.
<x-media-library-collection name="images" :model="$formSubmission" collection="images" max-items="3" rules="mimes:png,jpeg" fields-view="uploads.blade.partials.custom-properties" />
In that custom-properties view, you can put anything that should be displayed in the right half of the collection component.
Here’s the content of that custom-propertiesview.
@include('media-library::livewire.partials.collection.fields') <div class="media-library-field"> <label class="media-library-label">Extra field</label> <input dusk="media-library-extra-field" class="media-library-input" type="text" {{ $mediaItem->customPropertyAttributes('extra_field') }} /> @error($mediaItem->customPropertyErrorName('extra_field')) <span class="media-library-text-error"> {{ $message }} </span> @enderror </div>
In the form request, you can use the customProperty to validate any extra custom attributes. The second argument of the function can take any validator in Laravel.
namespace App\Http\Requests\Blade; use Illuminate\Foundation\Http\FormRequest; use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia; class StoreBladeCollectionCustomPropertyRequest extends FormRequest { use ValidatesMedia; public function rules() { return [ 'name' => 'required', 'images' => [$this->validateMultipleMedia() ->maxItems(3) ->itemName('required|max:30') ->customProperty('extra_field', 'required|max:30'), ], ]; } }
In the controller where you process the form submission, you should use the withCustomProperties method to whitelist any extra attributes that you want to sync with your media.
$formSubmission ->syncFromMediaLibraryRequest($request->images) ->withCustomProperties('extra_field') ->toMediaCollection('images');
Customizing the look and feel
By default, both the Attachment and Collection components already look good. Probably you’d like to adapt them so they match the look of your app.
Luckily, this is easy to do. The styles that ship with Media Library Pro can be used by importing or linking dist/styles.css. The styles were built with a default tailwind.config.js.
You can customize the styles by importing src/styles.css and run every @apply rule through your own tailwind.config.js
/* app.css */ @tailwind base; @tailwind components; @tailwind utilities; @import "src/styles.css"; …
To achieve that behavior where uploaded files are preserved when a form validation error occurs, we use temporary uploads.
Inside the private spatie/laravel-medialibrary-pro repo, there are a lot of tests to make sure the back end integration and the Vue, React, and Blade front end components are working as expected.
We also wanted to have browser tests that ensure that front end components work perfectly with the back end and vice versa. That’s why we added Dusk tests in our demo application. You can see them here.
Let’s take a look at one of them:
/** * @test * * @dataProvider routeNames */ public function it_can_handle_a_single_upload(string $routeName) { $this->browse(function (Browser $browser) use ($routeName) { $browser ->visit(route($routeName)) ->type('name', 'My name') ->attach('@main-uploader', $this->getStubPath('space.png')) ->waitForText('Remove') ->waitUntilMissing('.media-library-progress-wrap.media-library-progress-wrap-loading') ->press('@submit') ->assertSee('Your form has been submitted'); $this->assertCount(1, FormSubmission::get()); $this->assertEquals('space.png', FormSubmission::first()->getFirstMedia('images')->file_name); }); }
This test will upload a file and make sure that the file is associated with a model after the form is submitted.
A thing to note here is that @dataProvider attribute. This will make PHPUnit run the test for each result returned by the routeNames function defined in the same file.
public function routeNames(): array { return [ ['vue.attachment'], ['react.attachment'], ['blade.attachment'], ]; }
You can see that in combination with the routeNames function, the it_can_handle_a_single_upload will run for the vue.attachment, react.attachment and blade.attachment routes. Visiting these routes will display the form that will use the Vue, React, or Blade component, respectively. So, this one test covers a lot of logic. It makes sure that the component work using any technology. This gives us a lot of confidence that all of the components are working correctly.
For more information and to develop web application using Laravel, Hire Laravel Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
Laravel 8 is now released and includes many new features including Laravel Jetstream, a models directory, model factory classes, migration squashing, rate-limiting improvements, time testing helpers, dynamic blade components, and many more features.
Before we jump into the new features, we’d like to point out that starting with version 6, Laravel now follows semver and will release a new major version every six months. You can see how the release process works here.
Laravel Jetstream improves upon the existing Laravel UI scaffolding found in previous versions. It provides a starting point for new projects, including login, registration, email verification, two-factor authentication, session management, API support via Laravel, and team management.
Laravel 8’s application skeleton includes an app/Models directory. All generator commands assume models exist in app/Models; however if this directory doesn’t exist, the framework will assume the application keeps models within the app/ folder.
Eloquent model factories are now class-based starting in Laravel 8, with improved support for relationships between factories (i.e., a user has many posts). I think you’ll agree how awesome the new syntax is for generating records via the new and improved model factories:
use App\Models\User; User::factory()->count(50)->create(); // using a model state "suspended" defined within the factory class User::factory()->count(5)->suspended()->create();
If your application contains many migration files, you can now squash them into a single SQL file. This file will be executed first when running migrations, followed by any remaining migration files that are not part of the squashed schema file. Squashing existing migrations can decrease migration file bloat and possibly improve performance while running tests.
Laravel 8 brings improvements to existing rate limiting functionality while supporting backward compatibility with the existing throttle middleware and offering far more flexibility. Laravel 8 has the concept of Rate Limiters that you can define via a facade:
use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Support\Facades\RateLimiter; RateLimiter::for('global', function (Request $request) { return Limit::perMinute(1000); });
As you can see, the for() method takes the HTTP request instance, giving you full control over limiting requests dynamically.
Laravel users have enjoyed full control over time modification via the excellent Carbon PHP library. Laravel 8 brings this one step further by providing convenient test helpers for manipulating the time within tests:
// Travel into the future... $this->travel(5)->milliseconds(); $this->travel(5)->seconds(); $this->travel(5)->minutes(); $this->travel(5)->hours(); $this->travel(5)->days(); $this->travel(5)->weeks(); $this->travel(5)->years(); // Travel into the past... $this->travel(-5)->hours(); // Travel to an exact time... $this->travelTo(now()->subHours(6)); // Return back to the present time... $this->travelBack();
When using these methods, the time will reset between each test.
Sometimes you need to render a blade component dynamically at runtime. Laravel 8 provides the ‘<x-dynamic-component/>’ to render the component:
<x-dynamic-component :component="$componentName" class="mt-4" />
Laravel’s job batching feature allows you to easily execute a batch of jobs and then perform some action when the batch of jobs has completed executing.
The new batch method of the Bus facade may be used to dispatch a batch of jobs. Of course, batching is primarily useful when combined with completion callbacks. So, you may use the then, catch, and finally methods to define completion callbacks for the batch. Each of these callbacks will receive an Illuminate\Bus\Batch instance when they are invoked:
use App\Jobs\ProcessPodcast; use App\Podcast; use Illuminate\Bus\Batch; use Illuminate\Support\Facades\Bus; use Throwable; $batch = Bus::batch([ new ProcessPodcast(Podcast::find(1)), new ProcessPodcast(Podcast::find(2)), new ProcessPodcast(Podcast::find(3)), new ProcessPodcast(Podcast::find(4)), new ProcessPodcast(Podcast::find(5)), ])->then(function (Batch $batch) { // All jobs completed successfully... })->catch(function (Batch $batch, Throwable $e) { // First batch job failure detected... })->finally(function (Batch $batch) { // The batch has finished executing... })->dispatch(); return $batch->id;
In previous releases of Laravel, the php artisan down maintenance mode feature may be bypassed using an “allow list” of IP addresses that were allowed to access the application. This feature has been removed in favor of a simpler “secret” / token solution.
While in maintenance mode, you may use the secret option to specify a maintenance mode bypass token:
php artisan down --secret="1630542a-246b-4b66-afa1-dd72a4c43515"
After placing the application in maintenance mode, you may navigate to the application URL matching this token and Laravel will issue a maintenance mode bypass cookie to your browser:
https://example.com/1630542a-246b-4b66-afa1-dd72a4c43515
When accessing this hidden route, you will then be redirected to the / route of the application. Once the cookie has been issued to your browser, you will be able to browse the application normally as if it was not in maintenance mode.
If you utilize the php artisan down command during deployment, your users may still occasionally encounter errors if they access the application while your Composer dependencies or other infrastructure components are updating. This occurs because a significant part of the Laravel framework must boot in order to determine your application is in maintenance mode and render the maintenance mode view using the templating engine.
For this reason, Laravel now allows you to pre-render a maintenance mode view that will be returned at the very beginning of the request cycle. This view is rendered before any of your application’s dependencies have loaded. You may pre-render a template of your choice using the down command’s render option:
php artisan down --render="errors::503"
For more information and to develop web application using Laravel, Hire Laravel Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
Before we move directly to talk about 7.4 release, let’s go through each of the earlier minor releases of Laravel 7.
We will briefly look at the new features in the 7.1 release, which introduced a convenient API resource method to work with new route caching in Laravel 7.x and the ability to customize the constrained table name.
Lasse Rafn contributed an apiResource()
convenience method to work with the new Laravel 7.x caching.
Since Laravel 7.X has a new (optimized) routing implemented, route names are more important, and caching routes will break if naming collisions happen.
Normally you can use Route::name(‘posts’)->resource(…… to change the name of a group (useful for nested routes like: /posts/{post}/comments).
However, this is not possible with apiResource
.
We propose this change to allow that. It’s just a convenience to replace:
/ Before Route::name('posts') ->resource( 'posts/{post}/comments', 'PostCommentsController' ) ->only([ 'index', 'show', 'store', 'update', 'destroy' ]); // Using the apiResource() method Route::name('posts') ->apiResource( 'posts/{post}/comments', 'PostCommentsController' );
Samuel França contributed the ability to pass a table name to the constrained() method in the ForeignIdColumnDefinition class:
Here’s one example from the tests:
$blueprint ->foreignId('team_column_id') ->constrained('teams');
This version was released with HTTP client query string support and a new timeout configuration option for the SMTP mail driver. Let’s check out the new features real quick!
ShawnCZek contributed the expectsConfirmation()
method on the PendingCommand class used to test artisan commands:
$this->artisan('foo:bar') ->expectsConfirmation('Do you want to continue?', 'no') ->assertExitCode(1);
The confirmation assertion uses expectsQuestion under the hood, but asserts the actual value from the test. The same above would originally need to be:
$this->artisan('foo:bar') ->expectsConfirmation('Do you want to continue?', true) ->assertExitCode(1);
Markus Podar contributed a timeout configuration for the SMTP mail driver. The default is 30 seconds. If you want to tweak the default, add a custom timeout configuration in seconds:
'timeout' => 60, // seconds
Irfaq Syed contributed query string support to the Laravel HTTP Client, meaning you can pass a second argument to Http::get():
Here’s an example of how it works:
Http::get('https://example.com/get'); // URL: https://example.com/get Http::get('https://example.com/get?abc=123'); // URL: https://example.com/get?abc=123 Http::get('https://example.com/get', ['foo' => 'bar']); // URL: https://example.com/get?foo=bar Http::get('https://example.com/get', 'foo=bar'); // URL: https://example.com/get?foo=bar
Note that passing query params to get() overrides any present in the URI, so use one or the other.
This version was released with the ability to use ^4.0 versions of ramsey/uuid. Since the release of Laravel 7.2, a few patch releases are available that we’ll briefly cover.
Laravel 7.3 adds the possibility to use ^4.0 of ramsey/uuid, but still supports v3.7 as well. The composer dependency is now ^3.7|^4.0.
Laravel 7.2.2 fixes a few blade component issues. Notably, the make:component
command now supports sub directories:
php artisan make:component Navigation/Item # previously creates the following: # View/Components/Navigation/Item.php # views/components/item.blade.php # Now creates them as expected: # View/Components/Navigation/Item.php # views/components/navigation/item.blade.php
Laravel 7 introduced route caching speed improvements, but with that have been a few issues with apps in-the-wild. Laravel 7.2.1 fixed a route naming issue with cache; you should upgrade to the latest 7.x release to get the newest routing fixes.
It’s important to note that you should ensure the uniqueness of route names, as routes with duplicate names can “cause unexpected behavior in multiple areas of the framework.”
The latest version is released with quite a few new features, such as a custom model caster interface, a “when” higher-order collection proxy, and the ability to clear an existing “order” from the query builder.
Custom model caster interface, a “when” higher-order collection proxy, and the ability to clear an existing “order” from the query builder are the new features of Laravel 7.4.
Loris Leiva contributed the ability to use a higher-order proxy with the Collection::when()
method:
// With this PR, this: $collection->when($condition, function ($collection) use ($item) { $collection->push($item); }); // ... can be refactored as this: $collection->when($condition)->push($item);
This PR enables you to chain other higher-order proxy methods:
// This: $collection->when($condition, function ($collection) { $collection->map->parseIntoSomething(); }); // ... can be refactored as this: $collection->when($condition)->map->parseIntoSomething();
Adrian Nürnberger contributed a console test method for asking choices.
Given the following example:
$name = $this->choice('What is your name?', ['Taylor', 'Dayle'], $defaultIndex);
You could only assert the message of this question, but cannot test the given choices:
$this->artisan('question') ->expectsQuestion('What is your name?', 'Taylor') ->assertExitCode(0);
As of Laravel 7.4, you can now do the following:
$this->artisan('question') ->expectsChoice('What is your name?', 'Taylor', ['Taylor', 'Dayle']) ->assertExitCode(0);
You can also guarantee the order of choices by passing a fourth boolean argument:
$this->artisan('question') ->expectsChoice('What is your name?', 'Taylor', ['Taylor', 'Dayle'], true) ->assertExitCode(0);
@nihilsen contributed the ability to define default props via @props:
<!-- Previously you might need something like: --> @props(['type', 'message']) @php $type = $type ?? 'info' @endphp <!-- New defaults in Laravel >=7.4 --> @props(['type' => 'info', 'message'])
Brent Roose contributed a Castable interface which allows “castable” types to specify their caster classes:
// Instead of this class ModelX extends Model { protected $casts = [ 'data' => CastToDTO::class . ':' . MyDTO::class, ]; } // You could do this class ModelY extends Model { protected $casts = [ 'data' => MyDTO::class, ]; } // The underlying class use Illuminate\Contracts\Database\Eloquent\Castable; class MyDTO implements Castable { public static function castUsing() { return CastToDTO::class . ':' . static::class; } }
Jonathan Reinink contributed a reorder() method to the query builder to reset orderBy()
calls:
$query = DB::table('users')->orderBy('name'); $unorderedUsers = $query->reorder()->get();
Reorder allows you to define default order in Eloquent relationships, with the ability to back out if needed:
class Account extends Model { public function users() { return $this->hasMany(User::class)->orderBy('name'); } } // Remove the name orderBy and order by email $account->users()->reorder()->orderBy('email'); // The same can be written as: $account->users()->reorder('email');
For more information and to develop web application using Laravel, Hire Laravel Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop any custom web apps using Laravel, please visit our technology page.
Content Source:
On release of Laravel 7, in our previous post we covered some of the fantastic features such as Laravel Airlock, Custom Eloquent Casts and few more. This post covers the rest of them.
Laravel 7 allows the configuration of multiple “mailers” for a single application. Each mailer configured within the mail configuration file may have its own options and even its own unique “transport”, allowing your application to use different email services to send certain email messages. For example, your application might use Postmark to send transactional mail while using Amazon SES to send bulk mail.
Mail::mailer('postmark') ->to($request->user()) ->send(new OrderShipped($order));
By default, Laravel will use the mailer configured as the default mailer in your mail configuration file. However, you may use the mailer method to send a message using a specific mailer
configuration:
Laravel 7 includes a new method of matching compiled, cached routes that have been cached using the route:cache
Artisan command. On large applications (for example, applications with 800 or more routes), these improvements can result in a 2x speed improvement in requests per second on a simple “Hello World” benchmark. No changes to your application are required.
Laravel 7 includes first-party support for configuring Cross-Origin Resource Sharing (CORS) OPTIONS
request responses by integrating the popular Laravel CORS package written by Barry vd. Heuvel. A new cors
configuration is included in the default Laravel application skeleton.
Sometimes you may need to apply casts while executing a query, such as when selecting a raw value from a table. For example, consider the following query:
use App\Post; use App\User; $users = User::select([ 'users.*', 'last_posted_at' => Post::selectRaw('MAX(created_at)') ->whereColumn('user_id', 'users.id') ])->get();
The last_posted_at
attribute on the results of this query will be a raw string. It would be convenient if we could apply a date
cast to this attribute when executing the query. To accomplish this, we may use the withCasts
method provided by Laravel 7:
$users = User::select([ 'users.*', 'last_posted_at' => Post::selectRaw('MAX(created_at)') ->whereColumn('user_id', 'users.id') ])->withCasts([ 'last_posted_at' => 'date' ])->get();
In previous releases of Laravel, the database
queue was not considered robust enough for production usage, due to deadlocks. However, Laravel 7 provides improvements to applications using MySQL 8+ as their database backed queue. By using the FOR UPDATE SKIP LOCKED clause and other SQL enhancements, the database
driver may now safely be used in higher volume production applications.
The test
command was contributed by Nuno Maduro.
In addition to the phpunit
command, you may now use the test Artisan command to run your tests. The Artisan test runner provides beautiful console UX and more information regarding the test that is currently running. In addition, the runner will automatically stop on the first test failure:
php artisan test
Any arguments that can be passed to the phpunit
command may also be passed to the Artisan test
command:
php artisan test --group=feature
The default Markdown mail template has received a fresh, more modern design based on the Tailwind CSS color palette. Of course, this template can be published and customized according to your application’s needs:
The Artisan console’s make
commands are used to create a variety of classes, such as controllers, jobs, migrations, and tests. These classes are generated using “stub” files that are populated with values based on your input. However, you may sometimes wish to make small changes to files generated by Artisan. To accomplish this, Laravel 7 provides the stub:publish
command to publish the most common stubs for customization:
php artisan stub:publish
The published stubs will be located within a stubs
directory in the root of your application. Any changes you make to these stubs will be reflected when you generate their corresponding classes using Artisan make
commands.
Sometimes you may wish to specify that a job may be attempted many times, but should fail if the retries are triggered by a given number of exceptions. In Laravel 7, you may define a maxExceptions
property on your job class:
<?php namespace App\Jobs; class ProcessPodcast implements ShouldQueue { /** * The number of times the job may be attempted. * * @var int */ public $tries = 25; /** * The maximum number of exceptions to allow before failing. * * @var int */ public $maxExceptions = 3; /** * Execute the job. * * @return void */ public function handle() { Redis::throttle('key')->allow(10)->every(60)->then(function () { // Lock obtained, process the podcast... }, function () { // Unable to obtain lock... return $this->release(10); }); } }
In this example, the job is released for ten seconds if the application is unable to obtain a Redis lock and will continue to be retried up to 25 times. However, the job will fail if three unhandled exceptions are thrown by the job.
Laravel 7 continues the improvements made in Laravel 6.x by introducing Laravel Airlock, routing speed improvements, custom Eloquent casts, Blade component tags, fluent string operations, a developer focused HTTP client, first-party CORS support, improved scoping for route model binding, stub customization, database queue improvements, multiple mail drivers, query-time casts, a new artisan test
command, and a variety of other bug fixes and usability improvements.
Laravel Airlock provides a featherweight authentication system for SPAs (single page applications), mobile applications, and simple, token based APIs. Airlock allows each user of your application to generate multiple API tokens for their account. These tokens may be granted abilities / scopes which specify which actions the tokens are allowed to perform.
Laravel has a variety of built-in, helpful cast types; however, you may occasionally need to define your own cast types. You may now accomplish this by defining a class that implements the CastsAttributes
interface.
Classes that implement this interface must define a get
and set
methods. The get
method is responsible for transforming a raw value from the database into a cast value, while the set
method should transform a cast value into a raw value that can be stored in the database. As an example, we will re-implement the built-in json
cast type as a custom cast type:
<?php namespace App\Casts; use Illuminate\Contracts\Database\Eloquent\CastsAttributes; class Json implements CastsAttributes { /** * Cast the given value. * * @param \Illuminate\Database\Eloquent\Model $model * @param string $key * @param mixed $value * @param array $attributes * @return array */ public function get($model, $key, $value, $attributes) { return json_decode($value, true); } /** * Prepare the given value for storage. * * @param \Illuminate\Database\Eloquent\Model $model * @param string $key * @param array $value * @param array $attributes * @return string */ public function set($model, $key, $value, $attributes) { return json_encode($value); } }
Once you have defined a custom cast type, you may attach it to a model attribute using its class name:
<?php namespace App\View\Components; use Illuminate\View\Component; class Alert extends Component { /** * The alert type. * * @var string */ public $type; /** * Create the component instance. * * @param string $type * @return void */ public function __construct($type) { $this->type = $type; } /** * Get the class for the given alert type. * * @return string */ public function classForType() { return $this->type == 'danger' ? 'alert-danger' : 'alert-warning'; } /** * Get the view / contents that represent the component. * * @return \Illuminate\View\View|string */ public function render() { return view('components.alert'); } }
To learn how to write custom Eloquent casts, including custom casts that cast to value objects, please consult the Eloquent documentation.
Blade components have been overhauled to allow tag based rendering, attribute management, component classes, inline view components, and more. Since the overhaul of Blade components is so extensive, please consult the full Blade component documentation to learn about this feature.
In summary, a component may now have an associated class which specifies the data it accepts. All public properties and methods defined on the component class will automatically be made available to the component view. Any additional HTML attributes specified on the component may be managed using the automatically included $attribute
variable, which is an attribute bag instance.
In this example, we will assume that an App\View\Components\Alert
component has been defined like so:
<?php namespace App\View\Components; use Illuminate\View\Component; class Alert extends Component { /** * The alert type. * * @var string */ public $type; /** * Create the component instance. * * @param string $type * @return void */ public function __construct($type) { $this->type = $type; } /** * Get the class for the given alert type. * * @return string */ public function classForType() { return $this->type == 'danger' ? 'alert-danger' : 'alert-warning'; } /** * Get the view / contents that represent the component. * * @return \Illuminate\View\View|string */ public function render() { return view('components.alert'); } }
And, assuming the component’s Blade template has been defined like so:
<!-- /resources/views/components/alert.blade.php --> <div class="alert {{ $classForType }}" {{ $attributes }}> {{ $heading }} {{ $slot }} </div>
The component may be rendered in another Blade view using the component’s tag:
<x-alert type="error" class="mb-4"> <x-slot name="heading"> Alert content... </x-slot> Default slot content... </x-alert>
As mentioned, this is just a very small sample of the functionality of the Blade component overhaul in Laravel 7 and does not demonstrate anonymous components, inline view components, and a variety of other features. Please consult the full Blade component documentation to learn about this feature.
Laravel now provides an expressive, minimal API around the Guzzle HTTP client, allowing you to quickly make outgoing HTTP requests to communicate with other web applications. Laravel’s wrapper around Guzzle is focused on its most common use cases and a wonderful developer experience. For example, the client makes it a breeze to POST and interface with JSON data:
use Illuminate\Support\Facades\Http; $response = Http::withHeaders([ 'X-First' => 'foo', 'X-Second' => 'bar' ])->post('http://test.com/users', [ 'name' => 'Taylor', ]); return $response['id'];
In addition, the HTTP client provides fantastic, ergonomic testing functionality:
Http::fake([ // Stub a JSON response for GitHub endpoints... 'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']), // Stub a string response for Google endpoints... 'google.com/*' => Http::response('Hello World', 200, ['Headers']), // Stub a series of responses for Facebook endpoints... 'facebook.com/*' => Http::sequence() ->push('Hello World', 200) ->push(['foo' => 'bar'], 200) ->pushStatus(404), ]);
You are likely familiar with Laravel’s existing Illuminate\Support\Str
class, which provides a variety of helpful string manipulation functions. Laravel 7 now offers a more object-oriented, fluent string manipulation library built on top of these functions. You may create a fluent Illuminate\Support\Stringable
object using the Str::of
method. A variety of methods may then be chained onto the object to manipulate the string:
return (string) Str::of(' Laravel Framework 6.x ') ->trim() ->replace('6.x', '7.x') ->slug();
Sometimes you may wish to resolve Eloquent models using a column other than id
. To do so, Laravel 7 allows you to specify the column in the route parameter definition:
Route::get('api/posts/{post:slug}', function (App\Post $post) { return $post; });
Sometimes, when implicitly binding multiple Eloquent models in a single route definition, you may wish to scope the second Eloquent model such that it must be a child of the first Eloquent model. For example, consider this situation that retrieves a blog post by slug for a specific user:
use App\Post; use App\User; Route::get('api/users/{user}/posts/{post:slug}', function (User $user, Post $post) { return $post; });
When using a custom keyed implicit binding as a nested route parameter, Laravel 7 will automatically scope the query to retrieve the nested model by its parent using conventions to guess the relationship name on the parent. In this case, it will be assumed that the User
model has a relationship named posts
(the plural of the route parameter name) which can be used to retrieve the Post
model.
For more information and to develop your web apps using Laravel, Hire Laravel Developer from us as we provide you high-quality solution by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft“.
To develop the custom web app using Laravel, please visit our technology page.
Content Source:
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
© 2024 — HK Infosoft. All Rights Reserved.
© 2024 — HK Infosoft. All Rights Reserved.
T&C | Privacy Policy | Sitemap