Paper Dashboard Laravel – Free Frontend Preset for Laravel

version license GitHub issues open GitHub issues closed

Frontend version: Paper Dashboard v2.1.1. More info at https://www.creative-tim.com/product/paper-dashboard-2/?ref=pdl-readme

Product Image

Speed up your web development with the Bootstrap 4 Admin Dashboard built for Laravel Framework 5.5 and up.

Note

We recommend installing this preset on a project that you are starting from scratch, otherwise your project’s design might break.

Prerequisites

If you don’t already have an Apache local environment with PHP and MySQL, use one of the following links:

Also, you will need to install Composer: https://getcomposer.org/doc/00-intro.md
And Laravel: https://laravel.com/docs/6.x/installation

Installation

After initializing a fresh instance of Laravel (and making all the necessary configurations), install the preset using one of the provided methods:

Via composer

  1. Cd to your Laravel app
  2. Install this preset via composer require laravel-frontend-presets/paper-dashboard. No need to register the service provider. Laravel 5.5 & up can auto detect the package.
  3. Run php artisan preset paper command to install the Argon preset. This will install all the necessary assets and also the custom auth views, it will also add the auth route in routes/web.php (NOTE: If you run this command several times, be sure to clean up the duplicate Auth entries in routes/web.php)
  4. In your terminal run composer dump-autoload
  5. Run php artisan migrate --seed to create basic users table

By using the archive

  1. In your application’s root create a presets folder
  2. Download an archive of the repo and unzip it
  3. Copy and paste paper-dashboard-master folder in presets (created in step 2) and rename it to paper
  4. Open composer.json file
  5. Add "LaravelFrontendPresets\\PaperPreset\\": "presets/paper/src" to autoload/psr-4 and to autoload-dev/psr-4
  6. Add LaravelFrontendPresets\PaperPreset\PaperPresetServiceProvider::class, to config/app.php file
  7. In your terminal run composer dump-autoload
  8. Run php artisan preset paper command to install the Paper Dashboard preset. This will install all the necessary assets and also the custom auth views, it will also add the auth route in routes/web.php (NOTE: If you run this command several times, be sure to clean up the duplicate Auth entries in routes/web.php)
  9. Run php artisan migrate --seed to create basic users table

Usage

Register a user or login using admin@paper.com and secret and start testing the preset (make sure to run the migrations and seeders for these credentials to be available).

Besides the dashboard and the auth pages this preset also has a user management example and an edit profile page. All the necessary files (controllers, requests, views) are installed out of the box and all the needed routes are added to routes/web.php. Keep in mind that all of the features can be viewed once you login using the credentials provided above or by registering your own user.

Dashboard

You can access the dashboard either by using the "Dashboard" link in the left sidebar or by adding /home in the url.

Profile edit

You have the option to edit the current logged in user’s profile (change name, email and password). To access this page just click the "User profile" link in the left sidebar or by adding /profile in the url.

The App\Htttp\Controlers\ProfileController handles the update of the user information.

public function update(ProfileRequest $request) { auth()->user()->update($request->all()); return back()->withStatus(__('Profile successfully updated.')); } 

Also you shouldn’t worry about entering wrong data in the inputs when editing the profile, validation rules were added to prevent this (see App\Http\Requests\ProfileRequest). If you try to change the password you will see that other validation rules were added in App\Http\Requests\PasswordRequest. Notice that in this file you have a custom validation rule that can be found in App\Rules\CurrentPasswordCheckRule.

public function rules() { return [ 'old_password' => ['required', 'min:6', new CurrentPasswordCheckRule], 'password' => ['required', 'min:6', 'confirmed', 'different:old_password'], 'password_confirmation' => ['required', 'min:6'], ]; } 

User management

The preset comes with a user management option out of the box. To access this click the "User Management" link in the left sidebar or add /user to the url. The first thing you will see is the listing of the existing users. You can add new ones by clicking the "Add user" button (above the table on the right). On the Add user page you will see the form that allows you to do this. All pages are generate using blade templates:

<div class="row"> <label class="col-sm-2 col-form-label"></label> <div class="col-sm-7"> <div class="form-group"> <input class="form-control" name="name" id="input-name" type="text" placeholder="" value="" required="true" aria-required="true"/> @if ($errors->has('name')) <span id="name-error" class="error text-danger" for="input-name"></span> @endif </div> </div> </div> 

Also validation rules were added so you will know exactely what to enter in the form fields (see App\Http\Requests\UserRequest). Note that these validation rules also apply for the user edit option.

public function rules() { return [ 'name' => [ 'required', 'min:3' ], 'email' => [ 'required', 'email', Rule::unique((new User)->getTable())->ignore($this->route()->user->id ?? null) ], 'password' => [ $this->route()->user ? 'nullable' : 'required', 'confirmed', 'min:6' ] ]; } 

Once you add more users, the list will get bigger and for every user you will have edit and delete options (access these options by clicking the three dotted menu that appears at the end of every line).

All the sample code for the user management can be found in App\Http\Controllers\UserController. See store method example bellow:

public function store(UserRequest $request, User $model) { $model->create($request->merge(['password' => Hash::make($request->get('password'))])->all()); return redirect()->route('user.index')->withStatus(__('User successfully created.')); } 

Table of Contents

Versions

HTML LARAVEL
Paper Dashboard HTML Paper Dashboard Laravel

Demo

Profile Page Users Page Notifications Page
Profile Page Users Page Notifications Page
View More

Documentation

The documentation for the Paper Dashboard Laravel is hosted at our website.

File Structure

├── app │   ├── Http │   │   ├── Controllers │   │   │   ├── Auth │   │   │   │   └── RegisterController.php │   │   │   ├── HomeController.php │   │   │   ├── PageController.php │   │   │   ├── ProfileController.php │   │   │   └── UserController.php │   │   └── Requests │   │   ├── PasswordRequest.php │   │   ├── ProfileRequest.php │   │   └── UserRequest.php │   └── Rules │   └── CurrentPasswordCheckRule.php ├── database │   └── seeds │   ├── DatabaseSeeder.php │   └── UsersTableSeeder.php └── resources ├── assets │   ├── css │   │   ├── bootstrap.min.css │   │   ├── bootstrap.min.css.map │   │   ├── paper-dashboard.css │   │   ├── paper-dashboard.css.map │   │   └── paper-dashboard.min.css │   ├── demo │   │   ├── demo.css │   │   └── demo.js │   ├── fonts │   │   ├── nucleo-icons.eot │   │   ├── nucleo-icons.ttf │   │   ├── nucleo-icons.woff │   │   └── nucleo-icons.woff2 │   ├── img │   │   ├── apple-icon.png │   │   ├── bg │   │   │   ├── fabio-mangione.jpg │   │   │   └── jan-sendereks.jpg │   │   ├── bg5.jpg │   │   ├── damir-bosnjak.jpg │   │   ├── default-avatar.png │   │   ├── faces │   │   │   ├── ayo-ogunseinde-1.jpg │   │   │   ├── ayo-ogunseinde-2.jpg │   │   │   ├── clem-onojeghuo-1.jpg │   │   │   ├── clem-onojeghuo-2.jpg │   │   │   ├── clem-onojeghuo-3.jpg │   │   │   ├── clem-onojeghuo-4.jpg │   │   │   ├── erik-lucatero-1.jpg │   │   │   ├── erik-lucatero-2.jpg │   │   │   ├── joe-gardner-1.jpg │   │   │   ├── joe-gardner-2.jpg │   │   │   ├── kaci-baum-1.jpg │   │   │   └── kaci-baum-2.jpg │   │   ├── favicon.png │   │   ├── header.jpg │   │   ├── jan-sendereks.jpg │   │   ├── logo-small.png │   │   └── mike.jpg │   ├── js │   │   ├── core │   │   │   ├── bootstrap.min.js │   │   │   ├── jquery.min.js │   │   │   └── popper.min.js │   │   ├── paper-dashboard.js │   │   ├── paper-dashboard.js.map │   │   ├── paper-dashboard.min.js │   │   └── plugins │   │   ├── bootstrap-notify.js │   │   ├── chartjs.min.js │   │   └── perfect-scrollbar.jquery.min.js │   └── scss │   ├── paper-dashboard │   │   ├── _alerts.scss │   │   ├── _animated-buttons.scss │   │   ├── _buttons.scss │   │   ├── cards │   │   │   ├── _card-chart.scss │   │   │   ├── _card-map.scss │   │   │   ├── _card-plain.scss │   │   │   ├── _card-stats.scss │   │   │   └── _card-user.scss │   │   ├── _cards.scss │   │   ├── _checkboxes-radio.scss │   │   ├── _dropdown.scss │   │   ├── _fixed-plugin.scss │   │   ├── _footers.scss │   │   ├── _images.scss │   │   ├── _inputs.scss │   │   ├── _misc.scss │   │   ├── mixins │   │   │   ├── _buttons.scss │   │   │   ├── _cards.scss │   │   │   ├── _dropdown.scss │   │   │   ├── _inputs.scss │   │   │   ├── _page-header.scss │   │   │   ├── _transparency.scss │   │   │   └── _vendor-prefixes.scss │   │   ├── _mixins.scss │   │   ├── _navbar.scss │   │   ├── _nucleo-outline.scss │   │   ├── _page-header.scss │   │   ├── plugins │   │   │   ├── _plugin-animate-bootstrap-notify.scss │   │   │   └── _plugin-perfect-scrollbar.scss │   │   ├── _responsive.scss │   │   ├── _sections.scss │   │   ├── _sidebar-and-main-panel.scss │   │   ├── _tables.scss │   │   ├── _typography.scss │   │   └── _variables.scss │   └── paper-dashboard.scss └── views ├── auth │   ├── login.blade.php │   ├── passwords │   │   ├── email.blade.php │   │   └── reset.blade.php │   └── register.blade.php ├── layouts │   ├── app.blade.php │   ├── footer.blade.php │   ├── navbars │   │   ├── auth.blade.php │   │   └── navs │   │   ├── auth.blade.php │   │   └── guest.blade.php │   └── page_templates │   ├── auth.blade.php │   └── guest.blade.php ├── pages │   ├── dashboard.blade.php │   ├── icons.blade.php │   ├── map.blade.php │   ├── notifications.blade.php │   ├── tables.blade.php │   ├── typography.blade.php │   └── upgrade.blade.php ├── profile │   └── edit.blade.php ├── users │   ├── create.blade.php │   ├── edit.blade.php │   └── index.blade.php └── welcome.blade.php 

Browser Support

At present, we officially aim to support the last two versions of the following browsers:

Resources

HTML LARAVEL
Paper Dashboard HTML Paper Dashboard Laravel

Change log

Please see the changelog for more information on what has changed recently.

Credits

Reporting Issues

We use GitHub Issues as the official bug tracker for the Paper Dashboard Laravel. Here are some advices for our users that want to report an issue:

  1. Make sure that you are using the latest version of the Paper Dashboard Laravel. Check the CHANGELOG from your dashboard on our website.
  2. Providing us reproducible steps for the issue will shorten the time it takes for it to be fixed.
  3. Some issues may be browser specific, so specifying in what browser you encountered the issue might help.

Licensing

Useful Links

Social Media

Creative Tim:

Twitter: https://twitter.com/CreativeTim?ref=pdl-readme

Facebook: https://www.facebook.com/CreativeTim?ref=pdl-readme

Dribbble: https://dribbble.com/creativetim?ref=pdl-readme

Instagram: https://www.instagram.com/CreativeTimOfficial?ref=pdl-readme

Updivision:

Twitter: https://twitter.com/updivision?ref=pdl-readme

Facebook: https://www.facebook.com/updivision?ref=pdl-readme

Linkedin: https://www.linkedin.com/company/updivision?ref=pdl-readme

Updivision Blog: https://updivision.com/blog/?ref=pdl-readme

Credits

via Laravel News Links
Paper Dashboard Laravel – Free Frontend Preset for Laravel

How to setup automatic db backup in Laravel

Hi All, this is Adi again with a Laravel related article. This time in a shorter format. As Laravel developers we need a way to back up our app’s databases somewhere for both save keeping the data and for analysis. I want to share with you a simple solution that I have devised for some of my smaller projects. I have tested this method only on MySql DB and on a VPS, but I think it’s pretty much the same for any database.

TLDR;

The outline of my solution is as follows. There’s an artisan command which handles the backup, that runs periodically using a cron. This command makes use of the mysqldump tool that comes with all MySql installations. mysqldump dumps the given DB into a .sql and we can control where it is dumped. And that’s how my solution works. Now let’s see some code.

The Code

First off create an Artisan command like so php artisan make:command BackupDatabase. This should create a class with the name you mentioned in the command and should also have some default scaffolding for the command.

DB Backup command

Let me explain what the above code does. Within the constructor we prepare the name of the file (line 20), then we check if there’s a folder named backups within the storage folder, if not we create it (line 21). Then we instantiate a process, with the command that we want to be executed, we also pass it other details (line 23-29).

Then in the handle method runs the process and logs the output to the application logs. This handle method is executed after the constructor by Laravel itself, so you don’t have to invoke it from anywhere.

And finally you need to setup cron, you have 2 options here, either you can call Laravel’s schedule:run command or call your backup command directly.

Conclusion

This is a pretty simple and neat solution for backing up your most valuable asset, that’s the data. You can extend this feature to do more, like attach the .sql file to an email or upload it to dropbox or where ever and so on.

That’s all from me, it’s been Adi – more about me at Simplest Web.

Related resources

via Laravel News Links
How to setup automatic db backup in Laravel

Create a simple report in Laravel

Published: Sep 27, 2019 by C.S. Rhymes

Recently I was tasked with creating a report in a Laravel project and I thought I would share some of the things I learned along the way. I’m going to use a shop as an example with an orders table that contains the orders, but these principles should apply to pretty much any report. Firstly I want to get the number of orders for the previous week and then I want to get a count of orders by week and year so I can put this data into a report.

Orders last week

The first request is to show how many orders there have been in the past week. Sounds simple right, but even this has a few challenges you need to be aware of.

We could start by creating a query that filters the orders that are greater than the start of the week and less than the end of the week.

$ordersLastWeek = Order::where('created_at', '>', '2019-09-16') ->where('created_at', '<', '2019-09-22') ->count(); 

This returns us a number thanks to using count() instead of get(), but we have hard coded the dates in our query which is less than ideal as we would have to change the query each week.

Luckily we can make use of Carbon to automatically calculate the start and end dates for our query. We can start by finding the current date and time using now(), then subtract a week and then find the start of the week and the end of the week. We can also tell the database we only want the created_at column in this query by adding a select() rather than getting all of the fields in the order.

$ordersLastWeek = Order::select('created_at') ->where('created_at', '>', now()->subWeek()->startOfWeek()) ->where('created_at', '<', now()->subWeek()->endOfWeek()) ->count(); 

If we wanted to display the orders from the week before last we can change subWeek() to subWeeks(2).

Orders By Week

Now we need to get a little more complicated. We need a count of orders for each week and year.

I initially thought I could make use of the count() method like the previous query but it turns out this doesn’t work as I had expected. I could return the count of all orders, but I couldn’t use it with groupBy().

If I only had a few orders I could get all of the orders and then loop through them with some collection methods in PHP to calculate the week and year for each item and then group them how I wanted.

// Please don't do this $ordersByWeek = Order::all()->map(function($item) { $item->week = $item->created_at->weekOfYear; $item->year = $item->created_at->year; return $item; }) ->groupBy(['year', 'week']) ->map ->map(function($week) { return $week->count(); }); 

Just to explain, I’m getting all the orders, then looping through each of the orders and set the week and year using carbon methods based on the created_at, before grouping by year and week and then looping through the weeks and returning a count of the orders for that week.

This works, but its not very efficient and could start using a lot of memory very quickly as the number of orders starts to grow. Instead, we need to make use of the power of the database. The rest of the article assumes you are using mysql as your database connection as different databases may need slightly different syntax or methods, but the principles should still apply.

We need a way of querying the database to get a count of orders. We can make use of DB::raw() in our select statement to count the order ids. To do this we need to use a mysql aggregate function called count(). We then give this the name of quantity using as.

DB::raw('count(id) as quantity)

We can use DB::raw() once more to get the week number and year from the created_at date using mysql’s year() and week() methods.

DB::raw('week(created_at) as week')

We can then group by the calculated year and week values to get the quantity of orders for each year and week.

use Illuminate\Support\Facades\DB; $ordersByWeek = Order::select([ DB::raw('count(id) as quantity'), DB::raw('week(created_at) as week'), DB::raw('year(created_at) as year') ]) ->groupBy(['year', 'week']) ->get() ->toArray(); return $ordersByWeek; 

The toArray() method on the end converts the result to an array to simplify the response. Something like the below would be returned in a json response format.

[ { "quantity": 3, "week": 36, "year": 2019 }, { "quantity": 2, "week": 37, "year": 2019 } ] 

You could further customise the above query to only show a particular year by using the when() method. This checks if year is in the request() sent to your controller. Laravel has some handy tools for comparing dates built in, such as whereDate(), whereMonth(), whereDay() and whereYear().

$ordersByWeek = Order::select([ DB::raw('count(id) as quantity'), DB::raw('week(created_at) as week'), DB::raw('year(created_at) as year') ]) ->when(request('year'), function ($query) { $query->whereYear('created_at', request('year')); }) ->groupBy(['year', 'week']) ->get() ->toArray(); 

The when() method also allows you to set a third parameter which will run if the test returns false, so you could filter by the current year by default if year is not in the request().

$ordersByWeek = Order::select([ DB::raw('count(id) as quantity'), DB::raw('week(created_at) as week'), DB::raw('year(created_at) as year') ]) ->when(request('year'), function ($query) { $query->whereYear('created_at', request('year')); }, function ($query) { $query->whereYear('created_at', now()->format('Y')); }) ->groupBy(['year', 'week']) ->get() ->toArray(); 

Hopefully this post has provided you with a starting point to start accessing some key metrics from your Laravel project and show you how you can refactor your queries to make them a bit more reusable, especially by using the when() method, instead of having to write separate queries for similar requests.

via Laravel News Links
Create a simple report in Laravel

Build event-driven microservices with GCP and Laravel

Laravel Cloud Pub/Sub.

Why?

Build a scalable Laravel apps using event-driven microservices architecture (Pub/Sub), this tool adds the ability for your Laravel applications to communicate with each other using Google Cloud Pub/Sub.

Define your architecture.

First of all, you need to create subscriptions and topics in Google Cloud Platform, or you can use the cli.

Installation.

  • composer require gdg-tangier/cloud-pubsub

Configuration.

You can define multiple subscribers (queue connections) config in config/queue.php, the app can subscribe to multiple subscriptions.

Example.

'pubsub' => [  'driver' => 'pubsub',  'queue' => env('SUBSCRIPTION'),  'credentials' => [  'keyFilePath' => storage_path(env('PUBSUB_CLIENT_KEY')), // credentials file path '.json'  'projectId' => env('GCP_PROJECT_ID'),  ],  ],

Here where you can define your subscriptions jobs, events and topics mappings.

Example.

<?php  return [  /*  * GCP Credentials.  */  'credentials' => [  'keyFilePath' => storage_path(env('PUBSUB_CLIENT_KEY', 'client')),  'projectId' => env('GCP_PROJECT_ID'),  ],   /*  * Here where you map events name with Google Pub/Sub topics.  *  * Means, map each event name to specific Google Pub/Sub topic.  */  'events' => [  'event_name' => '__YOUR_TOPIC_NAME__',  ],   /*  * Here where you can tie the subscription classes (jobs) to topics.  *  * Means, map each subscription job to a specific Google pubsub topic.  * The subscription job is responsible for handling the incoming data  * from a Google Pub/Sub topic.  */  'subscriptions' => [  \App\PubSub\DummyJob::class => '__YOUR_TOPIC_NAME__',  ], ];

Create subscription class.

  • php artisan pubsub:make-subscriber <Name>

A subscription class will be created at app/Subscribers

Example.

<?php  namespace App\Subscribers;  use GDGTangier\PubSub\Subscriber\SubscriberJob; use GDGTangier\PubSub\Subscriber\Traits\JobHandler;  class UserUpdated {  use JobHandler;   /**  * @var mixed  */  public $payload;   /**  * @var \GDGTangier\PubSub\Subscriber\SubscriberJob  */  public $job;   /**  * UserUpdated constructor.  *  * @param \GDGTangier\PubSub\Subscriber\SubscriberJob $job  * @param $payload  */  public function __construct(SubscriberJob $job, $payload)  {  $this->job = $job;  $this->payload = $payload;  }   /**  * Execute the job.  *  * @return void  */  public function handle()  {  //   } }

Publishing data to the cloud.

use GDGTangier\PubSub\Publisher\Facades\PublisherFacade;  PublisherFacede::publish('MyData', 'event_name');
$publisher = app('gcloud.publisher.connection');  $publisher->publish('MyDaya', 'event_name');

php artisan pubsub:publish <message> <event>

Subscriptions worker.

  • php artisan pubsub:subscribe <connection>

Note: To keep the queue:subscribe process running permanently in the background, you should use a process monitor such as Supervisor to ensure that the queue worker does not stop running.

Testing.

You need to install GCP command line tool.

  1. Run the pubsub emulator./emulator.sh
  2. Export the pubsub emulator host export PUBSUB_EMULATOR_HOST=localhost:8085
  3. Run phpunit

via Laravel News Links
Build event-driven microservices with GCP and Laravel

Inertia.js and Livewire: a high level comparison

Setting the stage

Inertia and Livewire were both born out of frustration with the current JavaScript landscape. Frameworks like Vue.js or React enable us to build incredible user interfaces, but the cost in complexity of building a SPA is incredibly high.

I see Inertia and Livewire as opposite solutions to similar problems. In a nutshell, Livewire enables you to build user interfaces by creating special components in Blade. You don’t need to write any JavaScript unless strictly necessary. Inertia replaces Blade views altogether by returning JavaScript components from controller actions. Those components can be built with your frontend framework of choice.

Livewire is a Laravel library, while Inertia has adapters for several server and client frameworks. That said, this comparison assumes you want to use Laravel on the backend.

More or less JavaScript

Let’s start with Livewire. Livewire is invisible at first. You build your application with Blade like you’re already used to. Need to add something interactive? Sprinkle in some basic JavaScript, or build a Livewire component.

Livewire components can be embedded in your existing views:

They exist out of a plain PHP file to control the data and a Blade file to control the template.

<?php use Livewire\Component; class Counter extends Component { public $count = 0; public function render() { return view('livewire.counter'); } } 
<div> <span></span> </div>

You can bind data and events to DOM nodes using wire: directives like wire:click. Events trigger an HTTP request and invoke their associated handler method on the component class written in PHP.

<?php use Livewire\Component; class Counter extends Component { public $count = 0; public function increment() { $this->count++; } public function decrement() { $this->count--; } public function render() { return view('livewire.counter'); } } 
<div> <button wire:click="increment">+</button> <button wire:click="decrement">-</button> <span></span> </div>

This allows you to write interactive components without writing any JavaScript. State and event handling gets lifted to the component class on the server.

When it comes to writing JavaScript, Inertia is Livewire’s polar opposite. After installing Inertia you stop writing Blade views altogether.

In contrast to Livewire, you return components from your controller actions.

<?php class UsersController { public function index() { return inertia('Users/Index', [ 'users' => User::all(), ]); } } 

Inertia will render a component written in Vue (or your framework of choice) matching the component path you specified in the response.

<template> <table> <tbody> <tr v-for="user in users" :key="user.id"> <!-- … --> </tr> </tbody> </table> </template> <script> export default { props: ['users'], } </script>

You handle user interactions on the client like you’re already used to with Vue. If you need to transition to a new page, use the InertiaLink component. This will request a JSON response with AJAX instead of triggering a full page visit, giving your application a smooth SPA-like experience.

<template> <table> <tbody> <tr v-for="user in users" :key="user.id"> <td> <InertiaLink :href="`/users/${user.id}`">  </InertiaLink> </td> </tr> </tbody> </table> </template> <script> export default { props: ['users'], } </script>

Inertia can also be used to fetch fresh data for the current page.

<template> <div> <input type="search" v-model="search"> <table> <tbody> <tr v-for="user in users" :key="user.id"> <td> <InertiaLink :href="`/users/${user.id}`">  </InertiaLink> </td> </tr> </tbody> </table> </div> </template> <script> export default { props: ['users'], data() { return { search: '', }; }, watch: { search(search) { Inertia.visit( `window.location.href?search=${search}`, { preserveState: true } ); } } } </script>

Developer experience

If you decide to use Livewire, you can progressively add Livewire components throughout your application. Data fetching is also managed in the Livewire component PHP class, so it’s separate from your application’s controllers. That means you can embed multiple components on a single page, and they’ll each have their state and lifecycle.

With Inertia you pretty much need to go all-in (at least per section of your application). Data fetching happens in controllers like you’re already used to, but that means you need to think more in “pages” and less in “components” in the context of the client-server communication.

Both of these approaches have a similar outcome: you end up writing a lot less AJAX-only endpoints.

Take a classic data table component as an example. In a traditional application, you’d have a controller action to return the base view and another action to fetch data asynchronously.

With Livewire you’d write a data table Livewire component that takes care of both the template and the data fetching.

With Inertia you’d write a single controller action that returns the view with the relevant data. This works because every subsequent request is already an AJAX request.

Render performance

JavaScript is a hard requirement for Inertia to render anything at all. If you need your server to return a fully rendered document, Inertia is a no go for now. The lack of server rendering changes the initial load experience, and can potentially impact SEO. A server-rendered document will always display faster than one that only renders on the client after all assets are downloaded and executed.

This is a much-discussed tradeoff when talking about SPAs. In the context of an interactive web application, the added load time is often worth it for the optimizations you can do on subsequent renders. Note that the performance penalty for Inertia is a lot smaller than for SPAs. SPAs need to make an additional AJAX request on every page to fetch data, while data is immediately included in an Inertia response.

Livewire is a whole different beast. Since Livewire renders everything on the server, you’ll always have a short time to first meaningful paint. After the content’s downloaded, Livewire will execute its scripts and the page will be interactive. Assuming you’re not loading huge amounts of JavaScript, the time to interactive of Inertia and Livewire are quite similar.

Should I use Inertia or Livewire?

The usual answer to all programming questions in the universe: it depends.

From a personal preference perspective

Aside from the context of your project: if you prefer developing in Vue, React, or another frontend framework, you’ll prefer Inertia. If you love Blade and want to write less JavaScript, Livewire would probably be your weapon of choice. This is, however, a highly subjective measure.

From a technical perspective

If you’re building a marketing-heavy landing page, a blog, or anything else with a higher bounce rate by nature, the longer time to first meaningful paint can hurt. Livewire is a better fit for these. The same applies to pages that must display content without relying on JavaScript.

If you’re building an app it’s a more nuanced decision.

A big selling point for Livewire is that each component has its lifecycle. This is pretty big you have a lot of blocks that need to communicate to the server individually.

Inertia keeps you limited to pages, but that makes the whole thing more familiar and gives you that smooth SPA-like experience throughout your application.

From an onboarding perspective

If you’re already building apps with Laravel and Vue, Inertia feels like a step up from mounting components in Blade views without drastically changing the way you need to structure your application. Livewire’s model is a bigger shift away from the MVC monolith we’re used to building.

Closing thoughts

Keep in mind that this is a very high-level overview of the two. Both have a ton of small features that spark joy in day-to-day development.

One thing Inertia and Livewire have in common: they’re both young and very exciting pieces of technology.

If Livewire sounds interesting to you, take a look at laravel-livewire.com. Livewire is created and maintained by Caleb Porzio. If you want to learn more about Inertia.js, I highly recommend reading “Server-side apps with client-side rendering” and “Introducing Inertia.js” from its author Jonathan Reinink.

via Laravel News Links
Inertia.js and Livewire: a high level comparison

A new tool for self-taught developers (sponsor)

A new tool for self-taught developers (sponsor)

Being a self-taught developer often means learning as you go, but also needing to write solid code on a timeline.

AnyMod is a new service with hundreds of ready-to-use modules (“mods”) that act as a fast starting point for your work: CMS, themes, forms, marketing sections, and more. You can add mods to any site (any tech stack) and they work automatically.

Mods make your work easier by being:

  • Fast: A page full of mods can load in about 20ms
  • Automatic: CMS & forms work without any extra setup, etc.
  • Pre-styled: already responsive and nice-looking, with dozens of free themes
  • Easy to modify: you can edit code and content directly, with live reload across all your screens
  • Easy to add: add mods to your site by copy/pasting one line of HTML

All of this means you can build really quickly, whether you’re adding features (like CMS) to static client sites, or integrating with React, Vue and whatever else you’re using.

AnyMod is also a great resource for continuing to learn.  Because all mods are open source, you can pop open the code editor and start messing around with a mod to see how it works. Mods are generally very well-written, so you might learn a thing or two.

The live reload is also just really cool: when you change a mod, it instantly updates everywhere you’re viewing it. No additional configuration is needed, and it makes for an extremely fast workflow.

If you’re a self-taught developer looking to continue learning and complete projects quickly with a lot of polish, consider checking out AnyMod.  It’s free to use and has a great community of self-taught devs building and sharing mods:

Check it out at anymod.com

***

Many thanks to AnyMod via Syndicate Ads for sponsoring the site this week.


Filed in: News


Enjoy this? Get Laravel News delivered straight to your inbox every Sunday.

No Spam, ever. We’ll never share your email address and you can opt out at any time.

via Laravel News
A new tool for self-taught developers (sponsor)

Making a Hardware Store Muzzleloader

Here’s a short two-part video showing a pretty decent build of a homemade muzzleloading pistol that was created from parts the guy found in a hardware store.

Warning: Turn off the sound… the only audio is some really bad “music.”

About two minutes in, I found myself cringing at the waste, as he cuts the lock plate from the MIDDLE of a large hunk of steel plate. He should’ve cut it from the edge to conserve his material. Please tell me I’m not the only person who thinks that way?

Impressive lock, but questionable mainspring.

I won’t bore you with a blow-by-blow… the video is in two parts but they’re only about 7 and 4 minutes long. Even if you don’t like his methods, it ought to give you some ideas anyhow.

Drilling out the hammer.

Drilling out the hammer.

Here are the videos… enjoy.

The post Making a Hardware Store Muzzleloader appeared first on AllOutdoor.com.

via All Outdoor
Making a Hardware Store Muzzleloader

We Are in the Middle of a Wave of Interesting New Productivity Software Startups

VC fund A16z’s Benedict Evans writes: We are in the middle of a wave of interesting new productivity software startups — there are dozens of companies that remix some combination of lists, tables, charts, tasks, notes, light-weight databases, forms, and some kind of collaboration, chat or information-sharing. All of these things are unbundling and rebundling spreadsheets, email and file shares. Instead of a flat grid of cells, a dumb list of files, and a dumb list of little text files (which is what email really is), we get some kind of richer canvas that mixes all of these together in ways that are native to the web and collaboration. Then, we have another new wave of productivity company that addresses a particular profession and bundles all of the tasks that were spread across spreadsheets, email and file shares into some new structured flow. […] A few years ago a consultant told me that for half of their jobs they told people using Excel to use a database, and for the other half they told people using a database to use Excel. There’s clearly a point in the life of any company where you should move from the list you made in a spreadsheet to the richer tools you can make in coolproductivityapp.io. But when that tool is managing a thousand people, you might want to move it into a dedicated service. After all, even Craigslist started as an actual email list and ended up moving to a database. But then, at a certain point, if that task is specific to your company and central to what you do, you might well end up unbundling Salesforce or SAP or whatever that vertical is and go back to the beginning. Of course, this is the cycle of life of enterprise software. IBM mainframes bundled the adding machines you see Jack Lemmon using below, and also bundled up filing cabinets and telephones. SAP unbundled IBM. But I’d suggest there are two specific sets of things that are happening now. First, every application category is getting rebuilt as a web application, allowing continuous development, deployment, version tracking and collaboration. As Frame.io (video!) and OnShape (3D CAD!) show, there’s almost no native PC application that can’t be rebuilt as a web app. In parallel, everything now has to be native to collaboration, and so the model of a binary file saved to a file share will generally go away over time (this could be done with a native PC app, but in practice generally won’t be). So, we have some generational changes, and that also tends to create new companies. But second, and much more important — everyone is online now. The reason we’re looking at nursing or truck drivers or oil workers is that an entire generation now grew up after the web, and grew up with smartphones, and assumes without question that every part of their life can be done with a smartphone. In 1999 hiring ‘roughnecks’ in a mobile app would have sounded absurd — now it sounds absurd if you’re not. And that means that a lot of tasks will get shifted into software that were never really in software at all before.



Share on Google+

Read more of this story at Slashdot.

via Slashdot
We Are in the Middle of a Wave of Interesting New Productivity Software Startups

David Hasselhoff in Moped Rider

David Hasselhoff in Moped Rider

Link

We all know that Germans love David Hasselhoff, so it makes perfect sense that the Knight Rider and Baywatch star would appear in a commercial for a German automotive website. The words may be in German, but the humor is universal. Presumably, K.I.T.T. was replaced with a moped due to fuel efficiency concerns.

via The Awesomer
David Hasselhoff in Moped Rider

Comic for September 29, 2019

Transcript

CEO: I don’t understand why you are recommending blockchain for this application.
Boss: My staff are the experts, but I can explain the basic idea. You see, using blockchain is like losing a necklace on the beach. Then a seagull finds the necklace and takes it back to it’s nest. And we all like data security, don’t we?
CEO: It’s almost as if you are proposing a plan you don’t understand at any level.
Boss: Well, yes, but keep in mind that you wouldn’t understand it even if I could explain it.
CEO: But you’re sure someone on your staff understands it, right?
Boss: Define "sure".

via Dilbert Daily Strip
Comic for September 29, 2019