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 9 without breaking backwards compatibility.
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 10 continues the improvements made in Laravel 9.x by introducing argument and return types to all application skeleton methods, as well as all stub files used to generate classes throughout the framework. In addition, a new, developer-friendly abstraction layer has been introduced for starting and interacting with external processes.
PHP 8.1 is the minimum-required PHP version in Laravel 10. Some PHP 8.1 features, such as readonly properties and array_is_list, are used in Laravel 10.
Not only is the framework professionally maintained and updated on a regular basis, but so are all of the official packages and the ecosystem.
The following is a list of the most recent official Laravel packages that have been updated to support Laravel 10:
Predis is a robust Redis client for PHP that may help you get the most out of caching to provide a fantastic user experience. Laravel formerly supported both versions 1 and 2, but as of Laravel 10, the framework no longer supports Predis 1.
Although Laravel documentation mentions Predis as the package for interacting with Redis, you may also use the official PHP extension. This extension provides an API for communicating with Redis servers.
If you were to make an invokable validation rule in Laravel 9, you would need to add an –invokable flag after the Artisan command. This is no longer necessary because all Laravel 10 rules are invokable by default. So, you may run the following command to create a new invokable rule in Laravel 10:
php artisan make:rule CustomRule
On its initial release, Laravel utilized all of the type-hinting features available in PHP at the time. However, many new features have been added to PHP in the subsequent years, including additional primitive type-hints, return types, and union types.
Laravel 10.x thoroughly updates the application skeleton and all stubs utilized by the framework to introduce argument and return types to all method signatures. In addition, extraneous “doc block” type-hint information has been deleted.
This change is entirely backwards compatible with existing applications. Therefore, existing applications that do not have these type-hints will continue to function normally.
The Artisan test command has received a new –profile option that allows you to easily identify the slowest tests in your application:
php artisan test --profile
To improve the framework’s developer experience, all of Laravel’s built-in make commands no longer require any input. If the commands are invoked without input, you will be prompted for the required arguments:
php artisan make:controller
Laravel 10 can create a random and secure password with a given length:
$password = Str::password(12);
A new first-party package, Laravel Pennant, has been released. Laravel Pennant offers a light-weight, streamlined approach to managing your application’s feature flags. Out of the box, Pennant includes an in-memory array driver and a database driver for persistent feature storage.
Features can be easily defined via the Feature::define method:
use Laravel\Pennant\Feature; use Illuminate\Support\Lottery; Feature::define('new-onboarding-flow', function () { return Lottery::odds(1, 10); });
Once a feature has been defined, you may easily determine if the current user has access to the given feature:
if (Feature::active('new-onboarding-flow')) { // ... }
Of course, for convenience, Blade directives are also available:
@feature('new-onboarding-flow') <div> <!-- ... --> </div> @endfeature
Laravel 10.x introduces a beautiful abstraction layer for starting and interacting with external processes via a new Process facade:
use Illuminate\Support\Facades\Process; $result = Process::run('ls -la'); return $result->output();
Processes may even be started in pools, allowing for the convenient execution and management of concurrent processes:
use Illuminate\Process\Pool; use Illuminate\Support\Facades\Process; [$first, $second, $third] = Process::concurrently(function (Pool $pool) { $pool->command('cat first.txt'); $pool->command('cat second.txt'); $pool->command('cat third.txt'); }); return $first->output();
Horizon and Telescope have been updated with a fresh, modern look including improved typography, spacing, and design
Pest test scaffolding is now enabled by default when creating new Laravel projects. To enable this feature, use the –pest flag when building a new app with the Laravel installer:
laravel new example-application --pest
Laravel 10 is a significant release for the Laravel framework, and it comes with several new features and improvements that will help developers create more robust and efficient web applications. The introduction of BladeX, model event hooks, and improved routing features make it easier for developers to build modular and scalable applications. The dropping of PHP 8.0 support is also a significant decision that ensures that developers are using the latest version of PHP, which is more secure and efficient. As always, Laravel continues to evolve and innovate, making it an excellent choice for web development projects.
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:
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:
What should we learn next? If you are a developer, this question should always be in your mind. Every day, new technologies are introduced and improvements are made to existing ones. Since we can’t learn all these technologies, it is really important to decide what should we learn next.
In this article, we’re going to discuss three back end development frameworks based on three different programming languages to give you an insight into what you should learn in 2021.
NodeJS is a JavaScript runtime environment framework that can be used for cross-platform development purposes. Since JavaScript is one of the most popular languages in the current context, that popularity has lifted up NodeJS to be one of the most used back end frameworks as well. Apart from that, NodeJS brings many important features that attract developers.
NodeJS is used by some famous companies all around the world including eBay, General Electric, GoDaddy, Microsoft, PayPal, Uber, Wikipins. Node JS is a perfect match if you’re building I/O bound applications, data streaming applications, Data Intensive Real-time Applications (DIRT), JSON APIs based applications, or single-page applications.
Advantages
Disadvantages
Django is an open-source, high-level web application framework written in Python. Django was introduced in 2005, and its idea of using Python for web development was a huge revolution. Django follows the model-template-view architecture and the main focus of this framework is to provide an easy method for the development of complex websites. Instagram, Mozilla, Bitbucket are some leading companies that use Django as their framework.
Advantages
Disadvantages
PHP is another famous language among web developers and Laravel is based on PHP. Laravel follows model-view-control architecture and is robust and easy to understand. Laravel is known as a good starting point for young developers. It provides a large set of features, like flexible routing for easy scaling, configuration management to handle different environments, query builders and ORM to query databases, Schema Builder to maintain database definitions and schemas, lightweight templates, etc. 9GAG, MasterCard, Kmong are some famous companies that use Laravel in their products.
Advantages
Disadvantages
As you can see, all these three frameworks are very popular among developers and they tend to select the framework based on their preferred language most of the time. For example, If you’re good with JavaScript, you will surely go with NodeJS. But there are other aspects we should take into account when selecting a framework.
If you’re a novice developer, who doesn’t have knowledge about JavaScript, Python, or PHP, Django or Python will be a good option for you to start with. Since Python is very straightforward and simple in its syntax, you can easily understand it. So, we will rank Django at the top when it comes to the learning curve while Laravel and NodeJS come next.
Security is another measurement we need to address in any project and all these frameworks provide built-in features to make a developer’s life easy. Out of these three, Django claims first place here as well.
If we talk about scalability and performance Django can be recognized as the best framework in scalability aspects while NodeJS provides the best performance.
All these frameworks have large communities and good documentation to get started with and they’re well established. So don’t hesitate to select them for your projects.
For more information and to develop web application using NodeJS, Hire Back End 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 NodeJS, 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:
Sanctum is Laravel’s lightweight API authentication package. This tutorial will go over using Laravel Sanctum to authenticate a mobile app. The app will be built in Flutter, Google’s cross-platform app development toolkit. We may skip some implementation details of the mobile app since that is not the focus of this tutorial.
We’ve set up Homestead to provision a domain name, api.sanctum-mobile.test, where my backend will be served, as well as a MySQL database.
First, create the Laravel app:
laravel new sanctum_mobile
At the time of writing, it gives me a new Laravel project (v8.6.0). As with the SPA tutorial, the API will provide a list of books, so We’ll create the same resources:
php artisan make:model Book -mr
The mr flags create the migration and controller too. Before we mess with the migrations, let’s first install the Sanctum package, since we’ll need its migrations again.
composer require laravel/sanctum php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Now, create the books migration:
Schema::create('books', function (Blueprint $table) { $table->id(); $table->string('title'); $table->string('author'); $table->timestamps(); });
Next, run your app’s migrations:
php artisan migrate
If you now take a look in the database, you’ll see the Sanctum migration has created a personal_access_tokens table, which we’ll use later when authenticating the mobile app.
Let’s update DatabaseSeeder.php to give us some books (and a user for later):
Book::truncate(); $faker = \Faker\Factory::create(); for ($i = 0; $i < 50; $i++) { Book::create([ 'title' => $faker->sentence, 'author' => $faker->name, ]); } User::truncate(); User::create([ 'name' => 'Alex', 'email' => 'alex@alex.com', 'password' => Hash::make('pwdpwd'), ]);
Now seed the database: php artisan db:seed. Finally, create the route and the controller action. Add this to the routes/api.php file:
Route::get('book', [BookController::class, 'index']);
and then in the index method of BookController, return all the books:
return response()->json(Book::all());
After checking that the endpoint works — curl https://api.sanctum-mobile.test/api/book — it’s time to start the mobile app.
For the mobile app, we’ll be using Android Studio and Flutter. Flutter allows you to create cross-platform apps that re-use the same code for Android and iPhone devices. First, follow the instructions to install Flutter and to set up Android Studio, then launch Android Studio and click “Create a new Flutter project.”
Follow the recipe in Flutter’s cookbook to fetch data from the internet to create a page that fetches a list of books from the API. A quick and easy way to expose our API to the Android Studio device is to use Homestead’s share command:
share api.sanctum-mobile.test
The console will output an ngrok page, which will give you a URL (something like https://0c9775bd.ngrok.io) exposing your local server to the public. (An alternative to ngrok is Beyond Code’s Expose.) So let’s create a utils/constants.dart file to put that in:
const API_URL = 'http://191b43391926.ngrok.io';
Now, back to the Flutter cookbook. Create a file books.dart which will contain the classes required for our book list. First, a Book class to hold the data from the API request:
class Book { final int id; final String title; final String author; Book({this.id, this.title, this.author}); factory Book.fromJson(Map<String, dynamic> json) { return Book( id: json['id'], title: json['title'], author: json['author'], ); } }
Second, a BookList class to fetch the books and call the builder to display them:
class BookList extends StatefulWidget { @override _BookListState createState() => _BookListState(); } class _BookListState extends State<BookList> { Future<List<Book>> futureBooks; @override void initState() { super.initState(); futureBooks = fetchBooks(); } Future<List<Book>> fetchBooks() async { List<Book> books = new List<Book>(); final response = await http.get('$API_URL/api/book'); if (response.statusCode == 200) { List<dynamic> data = json.decode(response.body); for (int i = 0; i < data.length; i++) { books.add(Book.fromJson(data[i])); } return books; } else { throw Exception('Problem loading books'); } } @override Widget build(BuildContext context) { return Column( children: <Widget>[ BookListBuilder(futureBooks: futureBooks), ], ); } }
And last, a BookListBuilder to display the books:
class BookListBuilder extends StatelessWidget { const BookListBuilder({ Key key, @required this.futureBooks, }) : super(key: key); final Future<List<Book>> futureBooks; @override Widget build(BuildContext context) { return FutureBuilder<List<Book>>( future: futureBooks, builder: (context, snapshot) { if (snapshot.hasData) { return Expanded(child: ListView.builder( itemCount: snapshot.data.length, itemBuilder: (context, index) { Book book = snapshot.data[index]; return ListTile( title: Text('${book.title}'), subtitle: Text('${book.author}'), ); }, )); } else if (snapshot.hasError) { return Text("${snapshot.error}"); } return CircularProgressIndicator(); } ); } }
Now we just need to modify the MyApp class in main.dart to load the BookList:
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Sanctum Books', home: new Scaffold( body: BookList(), ) ); } }
Now launch this in your test device or the emulator, and you should see a list of books.
Great, so we know the API is working and that we can fetch books from it. The next step is to set up authentication.
We’re going to use the provider package, and follow the guidelines in the official documentation for setting up simple state management. We want to create an authentication provider that keeps track of the logged-in status and eventually communicates with the server. Create a new file, auth.dart. Here’s where the authentication functionality will go. For the moment, we’ll return true so we can test the process works:
class AuthProvider extends ChangeNotifier { bool _isAuthenticated = false; bool get isAuthenticated => _isAuthenticated; Future<bool> login(String email, String password) async { print('logging in with email $email and password $password'); _isAuthenticated = true; notifyListeners(); return true; } }
With this provider, we can now check whether we’re authenticated and display the correct page accordingly. Modify you main function to include the provider:
void main() { runApp( ChangeNotifierProvider( create: (BuildContext context) => AuthProvider(), child: MyApp(), ) ); }
… and modify the MyApp class to show the BookList widget if we’re logged-in, or a LoginForm widget otherwise:
body: Center( child: Consumer<AuthProvider>( builder: (context, auth, child) { switch (auth.isAuthenticated) { case true: return BookList(); default: return LoginForm(); } }, ) ),
The LoginForm classes contain a lot of “widgety” cruft, so We’ll refer you to the GitHub repo if you’re interested in looking at it. Anyway, if you load the app in your test device, you should see a login form. Fill in a random email and password, submit the form, and you’ll see a list of books.
Ok, let’s set up the backend to handle the authentication. The docs tell us to create a route that will accept the username and password, as well as a device name, and return a token. So let’s create a route in the api.php file:
Route::post('token', [AuthController::class, 'requestToken']);
and a controller: php artisan make:controller AuthController. This will contain the code from the docs:
public function requestToken(Request $request): string { $request->validate([ 'email' => 'required|email', 'password' => 'required', 'device_name' => 'required', ]); $user = User::where('email', $request->email)->first(); if (! $user || ! Hash::check($request->password, $user->password)) { throw ValidationException::withMessages([ 'email' => ['The provided credentials are incorrect.'], ]); } return $user->createToken($request->device_name)->plainTextToken; }
Providing the username and password are valid, this will create a token, save it in the database, and return it to the client. To get this to work, we need to add the HasApiTokens trait to our User model. This gives us a tokens relationship, allowing us to create and fetch tokens for the user, and a createToken method. The token itself is a sha256 hash of a 40-character random string: this string (unhashed) is returned to the client, which should save it to use with any future requests to the API. More precisely, the string returned to the client is composed of the token’s id, followed by a pipe character (|), followed by the plain text (unhashed) token.
So now we have this endpoint in place, let’s update the app to use it. The login method will now have to post the email, password, and device_name to this endpoint, and if it gets a 200 response, save the token in the device’s storage. For device_name, We’re using the device_info package to get the device’s unique ID, but in fact, this string is arbitrary.
final response = await http.post('$API_URL/token', body: { 'email': email, 'password': password, 'device_name': await getDeviceId(), }, headers: { 'Accept': 'application/json', }); if (response.statusCode == 200) { String token = response.body; await saveToken(token); _isAuthenticated = true; notifyListeners(); }
We use the shared_preferences package, which allows for the storage of simple key-value pairs, to save the token:
saveToken(String token) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('token', token); }
So now we’ve got the app displaying the books page after a successful login. But of course, as things stand, the books are accessible with or without successful login. Try it out: curl https://api.sanctum-mobile.test/api/book. So now let’s protect the route:
Route:::middleware('auth:sanctum')->get('book', [BookController::class, 'index']);
Login again via the app, and this time you’ll get an error: “Problem loading books”. You are successfully authenticating, but because we don’t as yet send the API token with our request to fetch the books, the API is quite rightly not sending them. As in the previous tutorial, let’s look at the Sanctum guard to see what it’s doing here:
if ($token = $request->bearerToken()) { $model = Sanctum::$personalAccessTokenModel; $accessToken = $model::findToken($token); if (! $accessToken || ($this->expiration && $accessToken->created_at->lte(now()->subMinutes($this->expiration))) || ! $this->hasValidProvider($accessToken->tokenable)) { return; } return $this->supportsTokens($accessToken->tokenable) ? $accessToken->tokenable->withAccessToken( tap($accessToken->forceFill(['last_used_at' => now()]))->save() ) : null; }
The first condition is skipped since we aren’t using the web guard. Which leaves us with the above code. First, it only runs if the request has a “Bearer” token, i.e. if it contains an Authorization header which starts with the string “Bearer”. If it does, it will call the findToken method on the PersonalAccessToken model:
if (strpos($token, '|') === false) { return static::where('token', hash('sha256', $token))->first(); } [$id, $token] = explode('|', $token, 2); if ($instance = static::find($id)) { return hash_equals($instance->token, hash('sha256', $token)) ? $instance : null; }
The first conditional checks to see whether the pipe character is in the token and, if not, to return the first model that matches the token. We assume this is to preserve backward compatibility with versions of Sanctum before 2.3, which did not include the pipe character in the plain text token when returning it to the user. (Here is the pull request: the reason was to make the token lookup query more performant.) Anyway, assuming the pipe character is there, Sanctum grabs the model’s ID and the token itself, and checks to see if the hash matches with what is stored in the database. If it does, the model is returned.
Back in Guard: if no token is returned, or if we’re considering expiring tokens (which we’re not in this case), return null (in which case authentication fails). Finally:
return $this->supportsTokens($accessToken->tokenable) ? $accessToken->tokenable->withAccessToken( tap($accessToken->forceFill(['last_used_at' => now()]))->save() ) : null;
Check that the tokenable model (i.e., the User model) supports tokens (in other words, that it uses the HasApiTokens trait). If not, return null – authentication fails. If so, then return this:
$accessToken->tokenable->withAccessToken( tap($accessToken->forceFill(['last_used_at' => now()]))->save() )
The above example uses the single-argument version of the tap helper. This can be used to force an Eloquent method (in this case, save) to return the model itself. Here the access token model’s last_used_at timestamp is updated. The saved model is then passed as an argument to the User model’s withAccessToken method (which it gets from the HasApiTokens trait). This is a compact way of updating the token’s last_used_at timestamp and returning its associated User model. Which means authentication has been successful.
So, back to the app. With this authentication in place, we need to update the app’s call to the book endpoint to pass the token in the request’s Authorization header. To do this, update the fetchBooks method to grab the token from the Auth provider, then add it to the header:
String token = await Provider.of<AuthProvider>(context, listen: false).getToken(); final response = await http.get('$API_URL/book', headers: { 'Authorization': 'Bearer $token', });
Don’t forget to add a getToken method to the AuthProvider class:
Future<String> getToken() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString('token'); }
Now try logging in again, and this time the books should be displayed.
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:
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