Customize laravel fortify email verification to use a mailjet template - laravel

I've been trying to get fortify's native email verification feature to use mailjet so templates can easily be adjusted. I've hit a bit of a roadblock as all tutorials and sources I've found are all about blade templates. Does someone have some pointers in the right direction or perhaps personal experience setting this up?
Thanks in advance!

You need to bind your own implementation of Laravel\Fortify\Contracts\VerifyEmailViewResponse in the FortifyServiceProvider class.
# app/Providers/FortifyServiceProvider.php
namespace App\Providers;
use App\Actions\Fortify\YourClassHere;
use Laravel\Fortify\Contracts\VerifyEmailViewResponse;
class FortifyServiceProvider extends ServiceProvider
{
public function boot()
{
app()->singleton(VerifyEmailViewResponse::class, YourClassHere::class);
}
}
# app/Actions/Fortify/YourClassHere.php
namespace App\Actions\Fortify;
use Laravel\Fortify\Contracts\VerifyEmailViewResponse;
class YourClassHere extends VerifyEmailResponse
{
public function toResponse($request)
{
// your logic here.
// since mailjet uses an api, perhaps return the response of a curl call,
// or a response form Http::get(...)
// or use a third-party package like laravel-mailjet (https://mailjet.github.io/laravel-mailjet/)
}
}
The logic that sends the verification email is part of the Illuminate\Auth\MustVerifyEmail trait. If you want to change it, you need to override it in your User model.
class User extends Authenticatable
{
/**
* Send the email verification notification.
*
* #return void
*/
public function sendEmailVerificationNotification()
{
// your logic here.
}
}

Related

Facades vs. Classes with static methods in Laravel

I was looking around the Laravel framework and some of their products and I noticed that Cashier is using the Casheir class with static methods compared to Socialite, which is used as a facade.
What are the benefits/downsides of building it one or the other way, or is there none at all?
I would like to build something myself, but I don't want to start building it as a class with static methods if building it as a facade is a better solution.
When you may need multiple implementations, a single interface can be defined through facade to simplify the code
Building it as a class with static methods:
When you have multiple classes you have to do something like this:
CashierOne::method, CashierTwo::method ....
Used as a facade:
According to what you bind to the container to switch the implementation
You only need to call through an interface:
// Define a Cashier Facade
class Cashier extends Facade
{
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor()
{
return 'cashier';
}
}
// In CashServiceProvider
$this->app->singleton('cashier', function ($app) {
return new CashierManager ($app);
});
// In CashierManager
public function gateway($name = null)
{
// get cashier implementation by name
}
public function __call($method, $parameters)
{
return $this->gateway()->$method(...$parameters);
}
// In Controller
Cashier::method
In addition, the facade is easier to test, check:
https://laravel.com/docs/5.8/facades#how-facades-work

Set Mailable header via a trait?

I'm creating a Laravel package that would benefit from the use of emails. When a user would use my package they would want to email a file created by the package, but also set some custom headers for the email.
In an ideal solution, I would like to have a trait that the developer could simply use on their mailable class and it would automatically set the header for that email without any additional code. Is this something that is even possible via the use of a trait?
Some solutions have suggested adding headers to mailables by putting this in the build method:
$this->withSwiftMessage(function ($message) {
$headers = $message->getHeaders();
$headers->addTextHeader('mime', 'text/calendar');
});
But is there some way to have my own custom trait piggy-back on the build method of the Mailable that is using it WITHOUT having to write it in the Mailable class itself?
SOLUTION USING TRAITS
The only way to be able to do that with a trait would be defining the build method in your trait and make your user define another function instead of build such that you have the direct manipulation of the function actually used by Mailable class.
So your trait would be:
trait IsMailable {
public function build()
{
$this->withSwiftMessage(function ($message) {
$headers = $message->getHeaders();
$headers->addTextHeader('mime', 'text/calendar');
});
if(!method_exists($this, 'buildMail')) throw \Exception('buildMail is not defined!');
return $this->buildMail();
}
}
So your user will have to define the method buildMail instead of build.
OPTIMAL SOLUTION
The optimal solution, IMHO, would be extending the class Illuminate\Mail\Mailable redefining the method send and making the end user implement this newly defined class instead of Illuminate\Mail\Mailable.
So your class would be:
class Mailable extends \Illuminate\Mail\Mailable {
/**
* Send the message using the given mailer.
*
* #param \Illuminate\Contracts\Mail\Mailer $mailer
* #return void
*/
public function send(MailerContract $mailer)
{
$this->withSwiftMessage(function ($message) {
$headers = $message->getHeaders();
$headers->addTextHeader('mime', 'text/calendar');
});
parent::send($mailer);
}
}
Doing that your user can use the build method as it would do using the standard Illuminate\Mail\Mailable class but the end result would be that your class is piggybacking the additional information that you actually need.

How i can extend laravel translator (any other component)?

I want to implement some extra features to Illuminate\Translate\Translator.
So, i create my folder in ~/vendor directory, place there My/Traslator class, that will implement Symfony\Component\Translation\TranslatorInterface. Right?
Is it OK to extend laravel translator class (a lot of functionality will be duplicated otherwise) in my package?
If it is ok - it will be necessary to tie to current laravel version to keep code stable. But what will happen in case enduser laravel version will differ from one required in my package?
What should i do then to make laravel use my translator class in application (facades,etc)?
Make a Translator class and make it extend Illuminate\Translation\Translator
<?php
namespace App\Helpers;
use Illuminate\Translation\Translator as LaravelTranslator;
class Translator extends LaravelTranslator
{
// here you can overwrite any functions you want/need
}
Create your own TranslationServiceProvider inside app/providers (just copy the laravel translation service provider and change the line where it uses Translator with your own Translator class where you have overwritten what you needed)
<?php
namespace App\Providers;
use App\Helpers\Translator; // <= Your own class
use Illuminate\Translation\FileLoader;
use Illuminate\Support\ServiceProvider;
class TranslationServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->registerLoader();
$this->app->singleton('translator', function ($app) {
$loader = $app['translation.loader'];
// When registering the translator component, we'll need to set the default
// locale as well as the fallback locale. So, we'll grab the application
// configuration so we can easily get both of these values from there.
$locale = $app['config']['app.locale'];
$trans = new Translator($loader, $locale);
$trans->setFallback($app['config']['app.fallback_locale']);
return $trans;
});
}
/**
* Register the translation line loader.
*
* #return void
*/
protected function registerLoader()
{
$this->app->singleton('translation.loader', function ($app) {
return new FileLoader($app['files'], $app['path.lang']);
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return ['translator', 'translation.loader'];
}
}
Comment out or delete the Laravels translator service line inside config/app.php:
//Illuminate\Translation\TranslationServiceProvider::class,
Add your own Provider in that same array
App\Providers\TranslationServiceProvider::class,
This page has more information: http://laravel.com/docs/5.0/extending#container-based-extension
So what you need to do is:
Extend the built-in class from the vendor directory
Create a new service provider that add your translation class to the service container
Replace Laravel’s translation service provider in your config/app.php file with the namespace of your translation service provider
Now when you ask for the translation service provider out of the service container—either directly (app('translator')) or with the Lang façade, it will return your translation class rather than Laravel’s.

Injection in Repository

I found many questions about my problem and tried (I think) all the solutions, but I can not make it work. I'm overlooking something very easy, probably.
I'm using Laravel 5. I try to implement a repository-pattern.
I have an Eloquent model '\Notos\Kind'.
Then I have this interface:
namespace Notos\Contracts;
interface Kind
{
public function findByName($name);
}
My Repository looks like this:
namespace Notos\Repository;
use Illuminate\Database\Eloquent\Model;
use Notos\Contracts\Kind as KindContract;
class Kind implements KindContract
{
protected $kind;
public function __construct(Model $kind)
{
$this->kind = $kind;
}
public function findByName($name)
{
return $this->kind->firstOrCreate(array('name' => $name));
}
}
My ServiceProvider:
namespace Notos\Providers;
use Illuminate\Support\ServiceProvider;
use Notos\Kind;
use Notos\Repository\Kind as KindRepository;
class RepoServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->bind('Notos\Contracts\Kind', function ($app) {
return new KindRepository(new Kind);
});
}
}
And my controller that uses the repository:
namespace Notos\Http\Controllers;
use Notos\Repository\Kind as KindRepository;
class KindController extends Controller
{
protected $kind;
public function __construct(KindRepository $kind)
{
$this->kind = $kind;
}
public function find($name)
{
return $this->kind->findByName($name);
}
}
This provider is registered in config/app.php
When I try to execute the KindController#find I get this error:
BindingResolutionException in Container.php line 785:
Target [Illuminate\Database\Eloquent\Model] is not instantiable.
I can't find what I'm doing wrong.
It works perfect if I change __construct(Model $kind) to __construct(Kind $kind).
Any ideas?
Thanks
The first thing, I would advice you to add to your class names the function so for example instead of Kind for repository use KindRepository, the same for contract. Otherwise you will have 3 kinds classes (of course in different namespaces) but it will be hard to analyse the code.
The problem here is that in your KindController you try to inject KindRepository directly but in constructor you use Model. It won't work because Model is only abstract class. What you should do to make it work?
In the code:
$this->app->bind('Notos\Contracts\Kind', function ($app) {
return new KindRepository(new Kind);
});
you told Laravel that when you will use Notos\Contracts\Kind it should create KindRepository for you with Kind in constructor - look you told here about Contract, not about repository itself.
So to make it work, you should use in your controller not your repository, but your contract.
Instead of line:
use Notos\Repository\Kind as KindRepository;
you should write:
use Notos\Contracts\Kind as KindRepository;
and it should work now.

How does laravel 5 know which contract implementation I want to use?

I'm kind of confused of how to use contracts. I think that's because I haven't used unit-testing so that it's not obvious for me how contracts work.
Let's have look at this code:
use Illuminate\Contracts\Auth\Guard;
...
public function __construct(Guard $auth)
{
$this->auth = $auth;
$this->middleware('guest', ['except' => 'getLogout']);
}
public function postRegister(RegisterRequest $request)
{
// Registration form is valid, create user...
$this->auth->login($user);
return redirect('/');
}
So how do I know which class implements login method of contract in this line: $this->auth->login($user) ? And how can I change the class if I want to use my own?
In laravel 4 I wrote Auth::user() as an example and I used it everywhere in any controller and it worked. Now I should inject a contract inside a controller method and use it like $auth->user?
Also, If I get it right, contracts are used for making an abstraction. Okay, so, if I want to build a new interface for my own class and then have multiple classes that implement my interface, where should I write the code? I can't think of an example but lets imagine I need to implement an interface for enabling/disabling a lamp, and I have two methods like on() and off() and I have multiple ways to do that. Do I need to create new contract for that?
I hope I can make this a bit clearer for you...
Ad.1. You can check default binding at /vendor/laravel/framework/src/Illuminate/Foundation/Application.php (method registerCoreContainerAliases around line 792). If you want to create your own class or extend existing I recommend looking at How to extend Laravel's Auth Guard class? or http://laravel.com/docs/master/extending (this one is more about Laravel 4.x but might give you an idea).
Ad.2. Actually you can still use Auth::user() but I inject a contract in constructor or a method and call it like $this->auth->user or $auth->user.
Ad.3. I have a /app/Repositories folder where I put my interfaces and implementations, so to follow your example I would create subfolder Lamp and I would create LampInterface with on() and off() methods, then I would create something like Lamp.php that implements LampInterface. Next I would create a service provider in /app/Providers, like LampServiceProvider.php with binding:
namespace Apps\Providers;
use Illuminate\Support\ServiceProvider;
class LampServiceProvider extends ServiceProvider {
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->singleton(
'App\Repositories\Lamp\LampInterface',
'App\Repositories\Lamp\Lamp'
);
}
}
After that I would register new service provider in /app/config/app.php and finally I can inject my interface like:
public function switchLampOn(App\Repository\Lamp\LampInterface $lamp)
{
$lamp->on();
}

Resources