The most flexible container you've ever seen, and Illuminate Contracts ▸ Macros, façades, re-binding, and more ▸ Environment variables and conditional config ▸ It's Just PHP™ customlaravel.com by @stauffermatt
it's bad. Sometimes the best tool isn't the most discoverable. Sometimes it's us that needs to change, not the tool. customlaravel.com by @stauffermatt
the request object ▸ Route::controller ▸ Custom façades that aren't façades ▸ Anything makes you go "that's so clever" instead of "that's so simple" customlaravel.com by @stauffermatt
▸ resolving things out of it ▸ things Laravel resolves using it ▸ autowiring vs. explicit ▸ service providers ▸ aliases and Facades customlaravel.com by @stauffermatt
this thing at this address ▸ "Address": a string, usually a fully-qualified class name or a shortcut string like "logger" ▸ "Thing": usually either a class name, a Closure, or an object app()->bind('address', Thing::class); app()->bind('logger', Logger::class); customlaravel.com by @stauffermatt
"thing" at the given "address" ▸ "give me the thing for address 'logger'" ▸ app()->make('logger') returns an instance of Logger ▸ Also can resolve by type hinting a container-resolved class like a Controller customlaravel.com by @stauffermatt
itself it creates using the container ▸ Controllers, middleware, etc. ▸ Why we can type hint dependencies in a controller ▸ Also some methods; controller methods, firing jobs, etc. class MyController { public function __construct(APIClient $client) { customlaravel.com by @stauffermatt
default; ask for "App\Thing" and it tries new App\Thing ▸ If App\Thing has dependencies it'll do the same for each ▸ If all dependencies are easy to resolve then you're good! If not.. ▸ app()->bind(Thing::class, function () { return new App\Thing('my-api-code'); }); customlaravel.com by @stauffermatt
another: app()->alias('logger', SomeOtherLogger::class) ▸ "When I ask for SomeOtherLogger, give me 'logger'" ▸ Façades say "make a new class; let me call statics on it and proxy them through to an instance of another class" customlaravel.com by @stauffermatt
custom config files (config/chat.php) ▸ Make up your own .env variables and import into your config ▸ Important: Don't directly reference env() inline! customlaravel.com by @stauffermatt
LoginController@username() ▸ Some are placed in your default controller (RegisterController@create) but all are adjustable customlaravel.com by @stauffermatt
ServiceProvider { public function boot() { // parent::boot(); } public function map() { $this->mapApiRoutes(); $this->mapWebRoutes(); // } protected function mapWebRoutes() { Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); } customlaravel.com by @stauffermatt
a sign you should consider customizing there. class AuthServiceProvider extends ServiceProvider { public function boot() { $this->registerPolicies(); // } customlaravel.com by @stauffermatt
in your controller methods ▸ php artisan make:middleware KeepOutBadPeople ▸ Apply globally, add to a custom middleware group, make route optional customlaravel.com by @stauffermatt
cousins ▸ Step 1. Bind your own class app()->bind(MyClass::class, Closure) ▸ Step 2. Bind your class to interfaces app()->bind(MyInterface::class, ClosureOrClassName) customlaravel.com by @stauffermatt
to a global shortcut app()->bind('myalias', ClosureOrClassName) ▸ Step 4. Re-bind other classes/interfaces to that global shortcut app()->alias('myalias', SomeContractClassName) customlaravel.com by @stauffermatt
Illuminate\Contracts\Logging; interface Log { public function alert($message, array $context = []); public function critical($message, array $context = []); // ... customlaravel.com by @stauffermatt
Step 2. Implement getFacadeAccessor() method; return a string that would resolve out of the container Step 3. Register it in config/app.php@aliases customlaravel.com by @stauffermatt
Cache::shouldReceive('get')->once()->with('key')- >andReturn('value') ▸ Shout out to MailThief ❤ ▸ Swap `em yourself! customlaravel.com by @stauffermatt
($attribute, $value, $parameters, $validator) { return app(Client::class)->validRepository($url); }); // or Validator::extend('repo', 'RepoValidator@validate'); // .. in your language file: [ "repo" => "The given repository is invalid.", ] customlaravel.com by @stauffermatt
__construct($source, $branch) { $this->source = $source; $this->branch = $branch; } public function passes($attribute, $value) { if (! $this->source instanceof Source) return false; return $this->source->client()->validRepository( $value, $this->branch ); } public function message() { return 'The given repository is invalid.'; } customlaravel.com by @stauffermatt
function () { return "<?php if (app('context')->isPublic()): ?>"; }); Blade::directive('endpublic', function () { return "<?php endif; ?>"; }); // Use: @public Only show on the public web site @endpublic customlaravel.com by @stauffermatt
function ($value) { return App\User::public() ->where('name', $value) ->first(); }); // In your binding Route::get('profile/{user}', function (App\User $user) { // }); customlaravel.com by @stauffermatt
{} // Form Request Validation public function store(StoreCommentRequest $request) {} // Form Request class StoreCommentRequest extends FormRequest { public function authorize() { return (bool)rand(0,1); } public function rules () { return ['validation rules here']; } } customlaravel.com by @stauffermatt
function ($value) { return app('github')->findRepository($value); }); // In your routes file Route::get('repositories/{repository}', function ($repo) { // }); customlaravel.com by @stauffermatt
methods, properties, etc. } // Type-hint in a route public function index(MyMagicalRequest $request) {} // Or even re-bind globally in public/index.php $response = $kernel->handle( // $request = Illuminate\Http\Request::capture() $request = App\MyMagicalRequest::capture() ); // (but, remember, macros!) customlaravel.com by @stauffermatt
methods, properties, etc. } // Return from a route public function index() { return MyMagicalResponse::forUser(User::find(1337)); } // Or macro it Response::macro('magical', function ($user) { return MyMagicalResponse::forUser($user); }); return response()->magical($user); customlaravel.com by @stauffermatt
don't enshrine, discoverability 3. 101: Modify the intended-to-be-modified; make your own, too 4. 201: Use the container! 5. 301: Override/custom all the classes! 6. Custom Homestead, Lambo customlaravel.com by @stauffermatt