Multi-tenancy in Laravel: Migrations, Testing, and switching tenants

Multi-tenancy in Laravel: Migrations, Testing, and switching tenants

https://www.youtube.com/watch?v=592EgykFOz4

In this video, we discuss how we can achieve multi-tenancy in Laravel using the database-per-tenant approach.

programming

via Laravel News Links https://ift.tt/2dvygAJ

May 6, 2020 at 09:03PM

How To Create/Save/Download PDF From Blade Template In PHP Laravel

How To Create/Save/Download PDF From Blade Template In PHP Laravel

https://ift.tt/3b8hkLL

Hola! you amazing people, I am back with a new article. In this article I will explain you how to create a PDF from a blade template with niklasravnsborg/laravel-pdf package. This package is a wrapper around mPDF.


Prerequisites

You have a composer installed in your computer. If not then you should definitely do it.

Have a fresh copy of Laravel project or a working project. If you want to create a new Laravel project with composer then use the following command.

composer create-project --prefer-dist laravel/laravel blog 

Step 1 – Install Laravel PDF Package With Composer

Install the LaravelPdf package with the following command

composer require niklasravnsborg/laravel-pdf 

This package is having auto discovery feature after Laravel 5.5+. If your still using the Laravel version below 5.5 then carry on with the following

Paste the following code in config/app.php

'providers' => [ // ... niklasravnsborg\LaravelPdf\PdfServiceProvider::class ] 

'aliases' => [ // ... 'PDF' => niklasravnsborg\LaravelPdf\Facades\Pdf::class ] 

After adding the above code run the following command

php artisan vendor:publish 

Step 2 – Create PDF Invoice Sample Blade Template

Following is the sample image of how it looks. Feel free to use the code and implement it in your project.

NOTE: Use the link to copy the code from GITHUB GIST.

PDF Invoice HTML Template Sample

PDF Invoice HTML Template Sample

Use the above GITHUB GIST code for quickly creating the template for PDF inside view/invoices/pdf-invoice.blade.php


Step 3 – Creating Routes

The following in the route, I have secured it within the user_auth middleware. Its not a mandatory but I have shown it so that if anyone who want to implement it securely they can do it.

/** User Related URL's */ Route::middleware(['user_auth'])->group(function () { /** Other URL's */ Route::get('/invoices/{project}/pdf-invoice', 'InvoicesController@savePdfInvoice'); }); 

The above Route URL points to InvoicesController Class and savePdfInvoice method & accepts {project} as parameter for route model binding.


Step 4 – Controller Code To Save PDF To Public Path

I am saving the PDF to my public/uploads/invoices/ folder. Following is the code to implement the PDF in your controller to Save PDF.

Overview Example (Check below for full implementation example)

Using $pdf->save('path_to_save') to save the file

use PDF; class InvoicesController { public static function savePdfInvoice(Project $project) { $pdf = PDF::loadView('invoices.pdf-invoice', [ /** Data required for view */ ]); $invoiceName = 'Name of the invoice to store'; /** Here you can use the path you want to save */ $pdf->save(public_path('uploads/invoices/'. $invoiceName)); } } 

Full Implementation Example

Using $pdf->save('path_to_save') to save the file

public static function savePdfInvoice(Project $project) { $priceDetails = ProjectsController::getProjectAmountDetails($project); $amount = $priceDetails['amount']; $gstAmount = $priceDetails['gstAmount']; $totalAmount = $priceDetails['totalAmount']; /** first param is the blade template, second param is the array of data need for the invoice */ $pdf = PDF::loadView('invoices.pdf-invoice', [ 'project' => $project, 'userDetails' => self::loggedInUserDetails(), 'amount' => $amount, 'gstAmount' => $gstAmount, 'totalAmount' => $totalAmount, ]); /** Creating the unique name for pdf */ $invoiceName = $project->unique_id.'-'.time().'_'.date('Y-m-d').'.pdf'; /** Save the PDF to /public/uploads/invoices/ folder */ $pdf->save(public_path('uploads/invoices/'. $invoiceName)); } 


Step 5 – Controller Code To Download PDF

In Step 4 you saw how to save the file to particular location. In this step you will learn how to download the PDF file

Use $pdf->download('invoice_name') to download the file

Full Implementation Of the Same. The code remains same as in that of Step 4, only $pdf->download will be used

public static function savePdfInvoice(Project $project) { $priceDetails = ProjectsController::getProjectAmountDetails($project); $amount = $priceDetails['amount']; $gstAmount = $priceDetails['gstAmount']; $totalAmount = $priceDetails['totalAmount']; $pdf = PDF::loadView('invoices.pdf-invoice', [ 'project' => $project, 'userDetails' => self::loggedInUserDetails(), 'amount' => $amount, 'gstAmount' => $gstAmount, 'totalAmount' => $totalAmount, ]); $invoiceNumber = $project->id + 1000; $pdf->download('Invoice#'. $invoiceNumber .'.pdf'); } 


Step 6 – PDF Configurations in config folder

When you do php artisan vendor:publish you will get pdf.php inside config folder where you can do global settings for your PDF.

The following is the default configuration

return [ 'mode' => 'utf-8', 'format' => 'A4', 'author' => '', 'subject' => '', 'keywords' => '', 'creator' => 'StackCoder', 'display_mode' => 'fullpage', 'tempDir' => public_path('temp') ]; 

As you can see in the above settings I have set the format of PDF to A4 sheet. And creator to StackCoder. For more details on the same visit the package in GITHUB repo.


Step 7 – Other PDF Methods

You have seen how to download & save the PDF, now lets see the method offered by PDF

output(): Outputs the PDF as a string. save($filename): Save the PDF to a file download($filename): Make the PDF downloadable by the user. stream($filename): Return a response with the PDF to show in the browser. 

For more details on the PDF option view this Laravel PDF package.


Conclusion

In this article you learnt how to download the Laravel PDF package, how to create routes, how to download & save PDF.

WHAT NEXT?

You might be interested in reading few of my other articles

How To Add Free SSL Certificate In cPanel With ZeroSSL & Certbot

How To Securely SSH Your Server & Push Files With FileZilla

How To Push Files To CPanel / Remote Server using FTP Software FileZilla

How To Install Linux, Apache, MYSQL, PHP (LAMP Stack) on Ubuntu

How To Cache Static Files With NGINX Server

Redirect www to a non-www website or vice versa

How To Create Free SSL Certificate With Lets Encrypt/Certbot In Linux (Single / Multiple Domains)

How To Install Linux, NGINX, MYSQL, PHP (LEMP Stack) on Ubuntu

PHP Built-In Web Server & Testing Your Development Project In Mobile Without Any Software

How To Do Google reCAPTCHA Integration In PHP Laravel Forms

Happy Coding 🙂

programming

via Laravel News Links https://ift.tt/2dvygAJ

May 6, 2020 at 09:03PM

How Everything Is Made

How Everything Is Made

https://ift.tt/3djJHIo

How Everything Is Made

Link

Rather than just show you how one thing is produced, this extensive playlist from Science Channel includes factory footage from 200 different items. From industrial fans to orange juice, from ketchup to luxury sports cars, there’s something here for just about every interest. So click play, and head down the rabbit hole.

fun

via The Awesomer https://theawesomer.com

May 6, 2020 at 09:31AM

Laravel Sending Emails | The Easiest and Simple Way

Laravel Sending Emails | The Easiest and Simple Way

https://ift.tt/2L4zKCx

Laravel Mail provides functionality to send large number of emails without affecting the performance of the server by using queues in laravel.

Sending emails are generic tasks done my more applications. And core PHP also provides you with a mail() function for sending the email. But developers at laravel made is an interesting and intuitive task when it comes to sending emails.

These may be sending smaller mails, blasting emails to large recipients or dispatching emails as a background task so that they don’t affect or slow down system resources can and will suit different tasks. And developers can easily expand its functionality and build over it.

Laravel Developer has done a very appreciable job and also provided with different drivers and the option of sending emails. Some of those drivers are mailgun, postmark, Amazon SES driver, SMTP etc.

Note

In this post, we’ll be covering topic regarding sending emails through laravel using SMTP services.

Table of Contents

Configuring Mails using SMTP settings

In your project root, you’ll find .env file which consists of all the environment setting for laravel application. There replace MAIL section with below code.

MAIL_DRIVER=smtp
 MAIL_HOST=smtp.googlemail.com
 MAIL_PORT=587
 MAIL_USERNAME=<email ID>
 MAIL_PASSWORD=<app-password>
 MAIL_ENCRYPTION=tls
 

The above is a simple and easiest configuration for sending the email. Our email drive in this case is MAIL_DRIVER and I’m using MAIL_HOST of google which provides free SMTP settings for sending an email.
Also, goto this google app password setting page to create an app password for your email as the normal password doesn’t work.

Generating a Mailable class

The best point about laravel mailable is that it keeps code and email template separately and this makes managing multiple email class a simple task.
The below command will generate a mailable class in your project directory laravel_email/app/Mail/WelcomeEmail.php.

php artisan make:mail WelcomeEmail
 

The newly generated mailable class looks like below.

<?php
 
 namespace App\Mail;
 
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Mail\Mailable;
 use Illuminate\Queue\SerializesModels;
 
 class WelcomeEmail extends Mailable
 {
 use Queueable, SerializesModels;
 
 /**
 * Create a new message instance.
 *
 * @return void
 */
 public function __construct()
 {
 //
 }
 
 /**
 * Build the message.
 *
 * @return $this
 */
 public function build()
 {
 
 }
 }

The __construct() method is a magic method through which parameters can be passed to WelcomeEmail mailable class.
build() method prepares or binds class data to views for sending the email. But does not send unless it is passed through send() method of Mail class.
This method is automatically triggered by the class itself.

In the build() method you have to specify view for this email, from sender information and also must be able to pass variables to views. After modification, our WelcomeEmail class looks like below.

class WelcomeEmail extends Mailable{
 use Queueable, SerializesModels;
 protected $email_data;
 
 public function __construct($data)
 {
 $this->email_data = $data;
 }
 
 public function build()
 {
 return $this->from('abc@gmail.com', "From name")
 ->subject("Welcome your registration is successfully completed.")
 ->view('emails.welcome-email-template')->with($this->email_data);
 }
 }
 

Variables passed through constructor are assigned to $this->email_data which are in turn passed to email view through the with() method.

Creating a view for mailable class

Views will be sent are email. It is just a design part where necessary data is displayed.
For creating a view file goto laravel_email/resources/views/emails/welcome-email-template.blade.php.

 
 <!DOCTYPE html>
 <html lang="en">
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Welcome Email</title>
 <style>
 .logo{
 padding: 10px;
 background-color: #f8f8f4;
 display: flex;
 }
 .logo p{
 font-family: sans-serif;
 font-size: 20px;
 }
 
 .content{
 padding: 10px;
 }
 
 .make_strong{
 font-weight: bold;
 }
 </style>
 </head>
 <body>
 <table cellpadding="0" cellspacing="0" align="center" bgcolor="#ffffff" width="100%" style="max-width:670px;border:1px solid #e8e8e8">
 <tbody>
 
 <tr>
 <td class="logo">
 <div style="float:left;width:100px;" >
 <img src="" alt="" style="width:100%;" border="0" class="">
 </div>
 <div style="padding-left: 15px;" >
 <p></p>
 </div>
 <div style="clear:both"></div>
 </td>
 </tr>
 
 <tr> 
 <td>
 <div class="content" >
 <p class="make_strong" >Hi ,</p>
 <p>Greetings from <span class="make_strong" >.</span></p>
 <p>You'r account has been successfully registered.</p>
 <a href="#" target="_blank" >Click to Login</a>
 </div>
 </td>
 </tr>
 
 <tr>
 <td bgcolor="#E0E0E0" valign="center" align="center" height="50" style="color:#000000;font:600 13px/18px Segoe UI,Arial">
 Copyright © , All rights reserved.
 </td>
 </tr>
 </tbody>
 </table>
 </body>
 </html>
 

Caution

Path and view name of email class must be the same as specified in build() method of WelcomeEmail class else InvalidArgumentException : View not found. an exception will be thrown.

Create Controller

php artisan make:controller HomeController
 

Define Route

Route::get('email/preview', 'HomeController@previewEmail');
 

Preview email before sending

previewEmail method take $data as a parameter which consists of information which will be used in views file.

<?php
 
 namespace App\Http\Controllers;
 
 use App\Mail\WelcomeEmail;
 use Illuminate\Http\Request;
 use Mail;
 class HomeController extends Controller
 {
 public function previewEmail(Request $request){
 $data = [
 "company_name" => "The Code Learners",
 "user" => [
 "name" => "Pavan Kumar"
 ],
 ];
 return new WelcomeEmail($data);
 }
 } 
 

If just want to see how end-user sees then just return new WelcomeEmail($data) object and respective view for this particular email class will be displayed into the browser.

Caution

The keyword new is used to create a new object of the class. Return object to preview email not the class.

Laravel preview email before sending

Sending email synchronously

Create a route for sending email synchronously.

Route::get('email/send', 'HomeController@sendEmailSynchronously');
 

For sending emails in synchronous manner use send() method which is provided by Mail facades. You must use mail facade before sending email.
In laravel_email/app/Http/Controllers/HomeController.php

public function sendEmailSynchronously(Request $request){
 $data = [
 "to" => "to-email@example.com",
 "company_name" => "The Code Learners",
 "user" => [
 "name" => "Pavan Kumar"
 ],
 ];
 return Mail::to($data['to'])->cc([])->bcc([])->send(new WelcomeEmail($data));
 }
 

Note

cc() and bcc() methods are optional.

Below will also work and will send an email directly specified as a parameter in to() method.

Mail::to($data['to'])->send(new WelcomeEmail($data));
 

Sending email as queued job

Create a route for sending email as a queued job.

Route::get('email/send-via-queued', 'HomeController@sendEmailQueued');
 

For sending mails through background process use the queue() method provided by facade Mail insisted of send() method.
What this does is that insisted of sending an email immediately it queues it into a particular connection which must be manually configured.

public function sendEmailQueued(Request $request){
 $data = [
 "to" => "to-email@example.com",
 "company_name" => "The Code Learners",
 "user" => [
 "name" => "Pavan Kumar"
 ],
 ];
 return Mail::to($data['to'])->queue(new WelcomeEmail($data));
 }
 

Using queue() method is faster and robust than using send() during production.

For queueing emails additional configuration must be done manually for more information on the queue you can read our Laravel Jobs and Queues – Configuring, Sending Mail, Dispacting Jobs post.
For official documentation, you can visit Laravel Mails.

Conclusion

You have come to end of Laravel Sending Emails | The easiest and simple way post. Support us by sharing this post which will help us grow and comment if you have any doubts we will reach you soon.

Reference Post

programming

via Laravel News Links https://ift.tt/2dvygAJ

May 5, 2020 at 09:03PM

How To Generate RSS Feeds in PHP Laravel

How To Generate RSS Feeds in PHP Laravel

https://ift.tt/2SDxQwT

Hi friends this is sequel of my another article How To Generate Sitemap in PHP Laravel. As I had discussed that for every website SEO plays key and vital role for Google Page ranking.

If your working on WordPress, Drupal, October CMS, Joomla or any other CMS then generating RSS is on tip of your fingers. But it will be bit confusing or difficult to generate in PHP Laravel. In this article I will show you how easily you can generate RSS feed in PHP Laravel.


Prerequisites

Hope you guys have a Blog or CMS developed in Laravel where you want to implement this RSS feed. And if your looking to host and play for free credits then you can setup your server with DigitalOcean, Linode or any other cloud platform


Step 1 – Installing Laravel spatie/laravel-feed Package

Run the following composer command to install the spaite/larvel-feed package.

composer require spatie/laravel-feed 

This will be installed in your vendor folder and added in require key of composer.json which will be as follows

"require": { "spatie/laravel-feed": "^2.6", } 

Step 2 – Add Feed Routes in web.php

Thanks to the Spatie team this comes all built in. Its as simple as the following command

/** In web.php */  Route::feeds(); 

Step 3 – Publish feed.php config file

Once you run the following command it will generate feed.php in config/feed.php where you can do few customisation, which I will explain later.

php artisan vendor:publish --provider="Spatie\Feed\FeedServiceProvider" --tag="config" 

Step 4 – Generate News Feed Code

For example for my Posts which has Post model I want to generate the NewsItem, so first let me generate new model for it via PHP Artisan command

php artisan make:model NewsItem 

This creates NewsItem model in App/NewItem path.

Now paste the following code in NewsItem model

<?php namespace App; use Post; use Carbon\Carbon; use Spatie\Feed\Feedable; use Spatie\Feed\FeedItem; class NewsItem extends Post implements Feedable { public function toFeedItem() { /** This is a standard FeedItem which must return collection and I am just passing the data that is required for it. Feel free to changes as per you convince */ return FeedItem::create([ 'id' => env('APP_URL').'/posts/'.$this->slug, 'title' => $this->title, 'summary' => $this->summary, 'updated' => $this->published_at, 'link' => env('APP_URL').'/posts/'.$this->slug, 'author' => $this->user->name, ]); } /** This function is responsible to get all your NewsItem feeds. This NewsItems gets the data from the previous created feeds. */ public static function getFeedItems() { /** I am getting only the published details */ return NewsItem::published()->orderBy('published_at', 'DESC')->get(); } } 

Step 5 – Customise Functions in config/feed.php

In config/feed.php we can configure the feed fetching function, URL of feed and views.

'items' => 'App\NewsItem@getFeedItems', /** This function we can created in Step 4 */ 'url' => '/feed', /** We can fetch the feed from APP_URL/feed */ 'title' => 'StackCoder', 'description' => 'The description of the feed.', 'language' => 'en-US', 

items – Where to get the feed items from

url – From where you need to access the feeds

title, description, language as per you convenience.


Step 6 – Adding Feed Links In Blade Pages

Add the following line in your blade in head section

<head> @include('feed::links') </head> 

Or you can even add the following html link

<link rel="alternate" type="application/atom+xml" title="News" href="/feed"> 

Step 7 – Testing If Its Working

If you have followed the above steps properly and when you go to your http://project_url/feed then you must be able to see the XML file


Conclusion

To know more on this package kindly see their repository https://github.com/spatie/laravel-feed. This is part of SEO series which I will be releasing soon. Meanwhile if your looking out for generating the sitemap for your Laravel website then following my another article How To Generate Sitemap in PHP Laravel.

Hope it help you. Happy Coding 🙂

programming

via Laravel News Links https://ift.tt/2dvygAJ

May 4, 2020 at 09:03PM

Laravel Emails | Sending emails with multiple attachments

Laravel Emails | Sending emails with multiple attachments

https://ift.tt/2KV6z4P

Laravel Mailable are well equipped for sending emails with multiple attachments. The attachments may be any file type such are pdf, excel, Docx etc. The great thing about this functionality is that setting up attachment is very easy by writing fewer lines of code.

Table of Contents

Setting up controllers

First, we’ll create a controller using the below command.

php artisan make:controller HomeController
 

Sending attachments within the email

Let us create newly mailable using below command.

php artisan make:mail PurchaseInvoiceInformation
 

In this example, class PurchaseInvoiceInformation is used for sending invoice document to customers.

Using the attach() method any type of file can be sent through email. It takes a single parameter which is the system path to the file location.

In laravel_email/app/Mail/PurchaseInvoiceInformation.php.

public function build()
 {
 return $this->from('from-email@example.com')
 ->view('emails.purchase-invoice-information')
 ->attach(public_path('uploads/sample.pdf'));
 
 }
 

To display HTML create a new view at laravel_email/resources/views/emails/purchase-invoice-information.blade.php.

<!DOCTYPE html>
 <html lang="en">
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Purchase Invoice</title>
 </head>
 <body>
 <h1>Test</h1>
 </body>
 </html>
 

Add new method sendEmailWithAttachment() into laravel_email/app/Http/Controllers/HomeController.php controller.

public function sendEmailWithAttachment(Request $request){
 return Mail::to("to-email@example.com")->send(new PurchaseInvoiceInformation());
 }
 

Update routes in laravel_email/routes/web.php with below content.

Route::get('email/send-with-attachment', 'HomeController@sendEmailWithAttachment');
 

Navigating to http://127.0.0.1/laravel_email/public/email/send-with-attachment will send email to the email id you have specified in to() method.

Below is the output you’ll receive when logged into your email account.

laravel send email with attachment

laravel send email with attachment content

 

Attaching Documents with Mime Types

You can also pass file mime type are give a custom name to file. This will help email providers to display your attachment in a proper format.

public function build()
 {
 return $this->from('from-email@example.com')
 ->view('emails.purchase-invoice-information')
 ->attach('file-public-path', [
 'as' => 'file-name-to-be-displayed.pdf',
 'mime' => 'file-mime-type',
 ]);
 }
 

Using as you can give a custom name to your attachment.
Using mime you have to specify which mime type your attachment belongs to.

Attaching Documents from storage disks

If you want to send files from storage disks then you can specify them using the attachFromStorage() method. This method takes a single parameter which is a path to the storage disk.

public function build()
 {
 return $this->from('from-email@example.com')
 ->view('emails.purchase-invoice-information')
 ->attachFromStorage('path-to-storage-disk');
 }
 

Laravel provides various storage disks such as default which is local, amazon cloud etc. To configure disks go to laravel_email/config/filesystems.php file.

Sending multiple attachments through the email

For sending multiple attachments attach() method can be called any number of times. Below is an example of multiple file uploads.

Add sendEmailWithMultipleAttachments() method in controller laravel_email/app/Http/Controllers/HomeController.php.

public function sendEmailWithMultipleAttachments(Request $request){
 $data = [
 "to" => "pavanbaddi911@gmail.com",
 "attachments" => [
 [
 "path" => public_path('uploads/inv-005.pdf'),
 "as" => "Purchase Invoice NO 005.pdf",
 "mime" => "application/pdf",
 ],
 [
 "path" => public_path('uploads/inv-007.pdf'),
 "as" => "Purchase Invoice NO 007.pdf",
 "mime" => "application/pdf",
 ],
 [
 "path" => public_path('uploads/inv-009.pdf'),
 "as" => "Purchase Invoice NO 009.pdf",
 "mime" => "application/pdf",
 ],
 ],
 ];
 return Mail::to($data['to'])->send(new PurchaseInvoiceInformation($data));
 }
 

Refactor class PurchaseInvoiceInformation for sending multiple attachments.

<?php
 
 namespace App\Mail;
 
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Mail\Mailable;
 use Illuminate\Queue\SerializesModels;
 
 class PurchaseInvoiceInformation extends Mailable
 {
 use Queueable, SerializesModels;
 
 /**
 * Create a new message instance.
 *
 * @return void
 */
 
 protected $data;
 
 public function __construct($data)
 {
 $this->data = $data;
 }
 
 /**
 * Build the message.
 *
 * @return $this
 */
 public function build()
 {
 $mail = $this->from('to-email@example.com')
 ->view('emails.purchase-invoice-information');
 
 if(!empty($this->data["attachments"])){
 foreach($this->data["attachments"] as $k => $v){
 $mail = $mail->attach($v["path"], [
 'as' => $v["as"],
 'mime' => $v["mime"],
 ]);
 }
 }
 
 }
 } 
 

$this->data["attachments"] contains an array of attachments which are attached one by one to the attach() method.

Refactor views file laravel_email/resources/views/emails/purchase-invoice-information.blade.php.

<!DOCTYPE html>
 <html lang="en">
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Purchase Invoice</title>
 </head>
 <body>
 <h1>Invoice Information</h1>
 
 <p>Dear User,</p>
 <p>Find invoices for your purchase order INV005, INV007, INV009.</p>
 
 </body>
 </html>
 

Update routes in laravel_email/routes/web.php.

Route::get('email/send-with-multiple-attachments', 'HomeController@sendEmailWithMultipleAttachments');
 

If you navigate to route email/send-with-multiple-attachments in your browser. If mail is sent you will not receive any error message.

Below is the output of email sent.

laravel sending email with multiple attachmentslaravel sending email with multiple attachments content

Take a look at our post on sending emails synchronously and also through a queue.

For more information on laravel mails, you can visit official laravel documentations.

Conclusion

You have come to end of Laravel Emails | Sending emails with multiple attachments post. Support us by sharing this post which will help us grow and comment if you have any doubts we will reach you soon.

programming

via Laravel News Links https://ift.tt/2dvygAJ

May 3, 2020 at 09:03PM

Dynamic custom domain routing in Laravel revisited

Dynamic custom domain routing in Laravel revisited

https://ift.tt/2YBVm0W

Back in November 2015, I wrote a Medium post about using Laravel’s subdomain routing feature with custom domain names, something that is important for many multi-tenant applications. There was always one thing about this solution that bugged me however, and recently I decided to take a second look at the problem to try and come up with a better approach.

The original solution

The original solution I found for using custom domains in Laravel was to add a global route pattern to RouteServiceProvider that changed the regular expression for subdomain matching to allow for full domains:

Route::pattern('domain', '[a-z0-9.\]+');

This allowed you to use the domain routing feature as follows:

Route::domain('{domain}')->group(function() { Route::get('users/{user}', function (Request $request, string $domain, User $user) { // Your code here }); });

While this works very well, it means you need to add the $domain argument to all your route actions, even if you don’t need them for the route in question. At the time I found it an acceptable consequence of the solution, but I’ve always wanted to try to find a better way.

The better way

The improved solution required completely forgetting that subdomain routing exists in Laravel the first place. Instead, we can use a simple middleware to look up the appropriate tenant based on the request host and add data to the request object so it can be used elsewhere in the application. The simplest implementation of this could be the following middleware class:

<?php namespace App\Http\Middleware; use Closure; use App\Tenant; class CustomDomain { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $domain = $request->getHost(); $tenant = Tenant::where('domain', $domain)->firstOrFail(); // Append domain and tenant to the Request object // for easy retrieval in the application. $request->merge([ 'domain' => $domain, 'tenant' => $tenant ]); return $next($request); } } 

Here, I’m assuming you have a Laravel model named Tenant which has an attribute domain which contains the full domain name you want to use for the tenant in question.

Now, in your app/Http/Kernel.php file, you can add a middleware group or route middleware that includes this new middleware. I like to create a new group for domain routes, which can be useful if there are other middleware I need to apply specifically to custom domain routes:

... protected $middlewareGroups = [ ... 'domain' => [ \App\Http\Middleware\CustomDomain::class, ], ... ];

Now, I can assing this middleware group to any routes that should be served up under a custom domain. Personally, I like to create a new routes/tenant.php routes file, and then in app/Providers/RouteServiceProvider.php add a new method for mapping tenant routes, complete with namespace and route name prefixing, such as:

public function map() { $this->mapApiRoutes(); $this->mapWebRoutes(); $this->mapTenantRoutes(); } protected function mapTenantRoutes() { Route::middleware(['web', 'auth', 'domain']) ->namespace("$this->namespace\Tenant") ->name('tenant.') ->group(base_path('routes/tenant.php')); }

The final piece of the puzzle is how to access information about the tenant from your controller actions, views and other parts of your application. After all, you’re going to need to know the tenant to correctly filter requests and what not. Unlike the previous solution, this approach does not add the $domain argument to your route action methods. Instead, you can simply read the tenant information off the request object itself. The following is an example of a controller action that does just that:

public function index(Request $request) { $tenant = $request->tenant; ... }

If you’re using Blade templates in your application, the CustomDomain middleware is also a good place to share any data that may be useful to your views that is different based on the tenant:

<?php namespace App\Http\Middleware; use Closure; use App\Tenant; use Illuminate\Support\Facades\View; class CustomDomain { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $domain = $request->getHost(); $tenant = Tenant::where('domain', $domain)->firstOrFail(); // Append domain and tenant to the Request object // for easy retrieval in the application. $request->merge([ 'domain' => $domain, 'tenant' => $tenant ]); // Share tentant data with your views for easier // customization across the board View::share('tenantColor', $tenant->color); View::share('tenantName', $tenant->name); return $next($request); } } 

Other considerations

The following are some other things you’ll likely encounter when you use this approach to enable custom domains in your application.

Authentication

You’ll most likely want to enable users of your application to only be able to login under the tenant they belong to. To do this, you may store a tenant_id attribute on your user model, and amend your authentication to take this into account when logging in. You can do this by overriding the credentials method on the stock Laravel app/Http/Controllers/Auth/LoginController.php file. The default method (which comes from the AuthenticatesUsers trait) is as follows:

protected function credentials(Request $request) { return $request->only($this->username(), 'password'); }

Making this tenant aware is as simple as changing this to the following:

protected function credentials(Request $request) { $credentials = $request->only($this->username(), 'password'); $credentials['tenant_id'] = optional($request->tenant)->id; return $credentials; }

Now users will only be able to login under the domain associated with the tenant their user model is related to.

You will also likely want to consider how your auth routes are mapped. By default, Laravel’s authentication routes are added to routes/web.php, but if you want to use the tenant middleware in your auth routes (for customisation or other reasons) you might find it better to create a new method in your RouteServiceProvider specifically for auth routes, such as:

protected function mapAuthRoutes() { Route::middleware(['web', 'domain']) ->namespace("$this->namespace\Auth") ->name('auth.') ->group(base_path('routes/auth.php')); }

Subdomains

While the goal of this is to enable support for custom domains in a Laravel application, you can still of course continue to serve subdomains and use the same approach as described here. The main difference between this solution and the built-in subdomain routing feature is that with this approach you need to store the full domain for your tenant rather than just the subdomain prefix.

Root and other non-tenant domains

In some instances, you may want to serve up something under your application’s root domain or under a specific domain that is not used by a specific tenant. This could be for an administration panel or some other functionality. One approach you could take here is to set a config for the domain you want to use and add a check for this if a tenant is not found in your CustomDomain middleware.

<?php namespace App\Http\Middleware; use Closure; use App\Tenant; use Illuminate\Support\Facades\View; class CustomDomain { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $domain = $request->getHost(); $tenant = Tenant::where('domain', $domain)->first(); if (!$tenant) { $adminDomain = config('app.admin_domain'); if ($domain != $adminDomain) { abort(404); } } // Append domain and tenant to the Request object // for easy retrieval in the application. $request->merge([ 'domain' => $domain, 'tenant' => $tenant ]); if ($tenant) { View::share('tenantColor', $tenant->color); View::share('tenantName', $tenant->name); } return $next($request); } }

For the view data, you could add fallbacks directly in the middleware here or alternatively you can add these to your app/Providers/AppServiceProvider.php in the boot method.

... public function boot() { ... View::share('tenantColor', 'gray'); View::share('tenantName', 'Admin'); ... } ...

Conclusion

And that’s about it! Overall I find this approach to be a cleaner method of implementing custom domains (and indeed subdomains) in a Laravel application. If you have any suggestions on how the above approach can be improved, feel free to reach out to me on Twitter @joelennon.

programming

via Laravel News Links https://ift.tt/2dvygAJ

May 3, 2020 at 09:03PM

Introducing the term-sheet grader

Introducing the term-sheet grader

https://ift.tt/2Wcq5iw

Jamie Goldstein
Contributor
Jamie is the founding partner of Pillar VC, a Boston-based seed-stage venture capital firm. He has spent the last 22 years investing in early-stage startups.

When we launched in 2016, we took the unusual approach of saying we’d buy common stock in startups. We believed then, and still do, that alignment with founders was more important than covering our downside in investments that didn’t work as planned. Said differently, we wanted to enhance our upside through alignment, rather than maximizing our downside through terms.

The world has changed a lot since that time. While we are actively making investments, and still buying common stock, we know that many entrepreneurs may be trying to raise money now — and it is very hard.

Fred Destin wrote a great piece about the ugly terms that can creep into term sheets during difficult times. If you have a choice between a good term sheet and a bad one, of course, you’ll take the good one. But what if you have no choice? And how can you compare term sheets in the first place?

To this end, we developed the term-sheet grader, a simple way to compare different term sheets or help characterize whether a term sheet is good or evil.

Let me first point out that none of this has anything to do with the valuation of the round (share price), the amount of capital, the likelihood of reaching a closing, the quality of the firm or the trust you have with the individual leading the investment, all absolutely critical pieces of the puzzle. Here, we are just looking at the terms and conditions, the legal structure of the investment.

We’ve listed nine key terms below — five that have to do with economics and four that relate to control and decision-making:

  • Each key term can earn +1 for being friendly and -1 for being tough.
  • There are a few really friendly terms that have a score of +2 each.
  • Likewise, there are a few really tough ones that earn a -2.
  • The best a term sheet could score is a +11, the worst is a -11.
  • The “Industry Standard” deal scores a 0.

FWIW, the Pillar common stock standard deal earns a +8 (shown below).

technology

via TechCrunch https://techcrunch.com

May 1, 2020 at 06:14PM

Knowde could make billions building the digital marketplace for the $5 trillion chemicals industry

Knowde could make billions building the digital marketplace for the $5 trillion chemicals industry

https://ift.tt/2WeqOQl

Ali Amin-Javaheri grew up in the chemicals business.

His father had worked for Iran’s state-owned chemical company and when the family fled the country in the nineteen eighties during the Iran-Iraq war, they first settled in Houston where employers welcomed the senior Amin-Jahaveri’s experience.

Houston in the 80s was dominated by the petrochemicals industry and by the time the family later relocated to Washington State, Amin-Jahaveri was already deeply steeped in a world of covalent bonds, chemical cracking, and the molecular coupling and decoupling of matter.

For the former Texas chemical kid, moving to tech-heavy, rain-soaked Washington, dominated at the time by Microsoft, was a bit of a shock, the founder recalled. But it was the 2000s and everyone was in tech so Amin-Jahaveri figured that’d be his path too.

Those two worlds collided for the young University of Washington graduate in his very first job — his only job before launching his first startup — as a programmer and developer at Chempoint.

“Completely through happenstance I was walking around a certain part of Seattle and I walked by this building and it had all these logos outside the office. I saw this logo for a company called Chempoint and I was instantly intrigued,” Amin-Jahaveri said. “I walked up to the receptionist and asked what they were doing.”

In the summer of 2001, Amazon was an online bookseller a little over seven years old, the dot-com boom hadn’t gone completely bust quite yet and business-to-business marketplaces were a hot investment.

“It was a startup with just a handful of folks,” said Amin-Jahaveri. “There wasn’t a business model in place, but the intent was to build a marketplace for chemicals… The dot-com boom was happening and everything was moving on line and the chemicals industry likely will as well.”

Fifteen years later, Chempoint is one of the last remaining companies in a market that once boasted at least fifteen competitors — and the chemicals industry still doesn’t have a true online marketplace. Until (potentially) now, with the launch of Amin-Jahaveri’s first startup — Knowde.

A volumetric flask, used during the process of determining phosphorus content in crude edible oil, sits in a laboratory of the quality assurance department at the Ruchi Soya Industries Ltd. edible oil refinery plant in Patalganga, India, on Tuesday, June 18, 2013. Photographer: Dhiraj Singh/Bloomberg via Getty Images

For the vast majority of Americans, the chemicals industry remains a ubiquitous abstraction. Consumers have a direct relationship with the energy business through the movements of prices at the pump, but the ways in which barrels of oil get converted into the plastics, coatings, films, flavors, fillings, soaps, toothpastes, enamels and unguents that touch everyone’s daily life are a little bit less obvious.

It’s a massive industry. The U.S. accounted for 17% of the global chemicals market in 2017 and that percentage amounted to a staggering $765 billion in sales. Worldwide there are thousands of chemicals companies selling hundreds of different specialty chemicals each and all contributing to a total market worth trillions of dollars.

“The market is $5 trillion,” said Amin-Jahaveri. “Just to be super clear about that.. It’s $5 trillion worth of transactions happening every year.”

It’s no secret that venture capitalists love marketplaces. Replacing physical middlemen with electronic ones offers efficiencies and economies of scale that have a cold logic and avoid the messiness of human contact. For the past twenty years, different entrepreneurs have cropped to tackle creating systems that could connect buyers on one side with sellers on another — and the chemicals industry has been investors’ holy grail since Chempoint made its pitch to the market in 2001.

“The chemicals industry is the most interesting of all of them. It’s the biggest. It’s also the most fragmented,” said Sequoia partner Shaun Maguire. “There were three companies in the world that all did about $90 billion in sales and none of those three companies did more than 1.6% of sales of the entire industry.” 

Those kinds of numbers would make any investor’s jaw drop. And several firms tried to make a pitch for the hotly contested financing round for Knowde. Maguire first heard that there looking for funds to pursue the creation of the first true marketplace business for the chemicals industry through a finance associate at Sequoia, Spencer Hemphill.

Hemphill knew an early Knowde investor named Ian Rountree at Cantos Ventures and had heard Rountree talk about the new company. He flagged the potential deal to Maguire and another Sequoia partner. It only took one hour for Maguire to be blown away by Amin-Jahaveri’s pedigree in the industry and his vision for Knowde.

From that initial meeting in September to the close of the company’s $14 million Series A round on March 11 (the day the markets suffered their worst COVID-19-related losses), Maguire was tracking the company’s progress. Other firms in the running for the Knowde deal included big names like General Catalyst, according to people with knowledge of the process.

Sequoia wound up leading the Series A deal for Knowde, which also included previous investors Refactor Capital, 8VC, and Cantos Ventures.

The tipping point for Maguire was the rapid adoption and buy-in from the industry when Knowde flipped the switch on sales in early January.

An employee of International Flavors and Fragrances (IFF) picks up perfume components on December 8, 2016 at the company’s laboratory in Neuilly-sur-Seine, near Paris. / AFP / PATRICK KOVARIK (Photo credit should read PATRICK KOVARIK/AFP via Getty Images)

For at least the past fifty years, the modern chemicals industry has been defined — and in some ways constrained — by its sales pitches. There are specialty manufacturers who have hundreds of chemicals that they’ve made, but the knowledge of what those chemicals can do is often locked inside research labs. The companies rely on distributors, middlemen, and internal sales teams to get the word out, according to Maguire and Amin-Jahaveri.

“The way that things are done is still through field sales teams and product catalogs and brochures and face to face meetings and all that stuff,” said Amin-Jahaveri. “This industry has not evolved as quickly as the rest of the world… And we always knew that something has got to give.”

One selling point for Knowde is that it breaks that logjam, according to investors like Maguire.

“One of the references said that they had a bunch of legacy flavors from the seventies,” Maguire said. “It was a  Madagascar Vanilla that none of their sales people had tried to sell for 25 years… By putting them on Knowde the sales numbers had gone up over 1,000%… That company does over $5 billion a year in sales through flavors.”

The change happened as the old guard of executives began aging out of the business, according to Amin-Jahaveri. “Between 2002 and 2012 nothing happened.. There was no VC money thrown at any type chemical company and then it started changing a little bit,” he said. “The first domino was the changing age demographic… these consumer product companies kept getting younger.”

Amin-Jahaveri’s previous company grew to $400 million in revenue selling technology and services to the chemicals industry. It was back-end software and customer relationship tools that the industry had never had and needed if it were to begin the process of joining the digital world. Knowde, according to Amin-Jahaveri, is the next phase of that transition.

“Our plan is to connect the chemical producers directly with the buyers,” Amin-Jahaveri said. “And provide all the plumbing and storefronts necessary to manage these things themselves.”

All that Knowde needed to do was collate the disparate data about what chemicals small manufacturers were making and had in stock and begin listing that information online. That transparency of information used to be more difficult to capture, since companies viewed their product catalog as an extension of their intellectual property — almost a trade secret, according to Amin-Jahaveri.

Once companies began listing products online, Amin-Jahaveri and his team could go to work creating a single, searchable taxonomy that would allow outsiders to find the materials they needed without having to worry about differences in descriptions.

Knowde has broken down the chemicals industry into ten different verticals including: food, pharmaceuticals, personal care, houseware goods, industrial chemicals. The company currently operates in three different verticals and plans to extend into all ten within the year.

Amin-Jahaveri knows that he’s not going to get a meaningful chunk of business from the huge chemical manufacturers like BASF or Dow Chemical that pump out thousands of tons of commodity chemicals, those deals only represent $2 trillion of the total addressable market.

That means another $3 trillion in sales are up for grabs for the company Amin-Jahaveri founded with his partner Woyzeck Krupa.

While the opportunity is huge, the company — like every other new business launching in 2020 — is still trying to do business in the middle of the worst economic collapse in American history. However, Amin-Jahaveri thinks the new economic reality could actually work in Knowde’s favor.

“It’s going to be one more trigger event for these chemical companies that they have to go online,” he said. The personal relationships that drove much of the sales for the chemicals business before have dried up. No more conferences and events means no more opportunities to glad-hand, backslap, and chat over drinks at the hotel bar. So these companies need to find a new way to sell.

Maguire sees another benefit to the movement of chemical catalogs into an online marketplace, and that’s internal transparency within chemical companies.

“Even the biggest companies in the world do not have an internal search feature even for their own chemicals,” said Maguire. “I talked to two of the biggest companies in the world. In the case of one chemist who is a friend of mine. If you are trying to formulate some new concoction how do you find what chemicals you have in the company? If it’s in my division it’s pretty easy.. If I need chemicals from another division… there’s no way to search it right now.”

technology

via TechCrunch https://techcrunch.com

May 1, 2020 at 12:05PM

A Clever DIY Hands-Free Sanitizer Dispenser

A Clever DIY Hands-Free Sanitizer Dispenser

https://ift.tt/2zOWqEz

To the man with a hammer, everything looks like a nail. To the guy who owns a PVC pipe distribution company, well…

By the way, I love how he touches the thing with his hands first.

fun

via Core77 https://ift.tt/1KCdCI5

May 1, 2020 at 08:40AM