(or at least seems to be magical?)
How is all
this working?
(When I know it's working well and will work)
use App\User;
Route::get('users/{user}', function (User $user) {
return $user->email;
});
// Otherwise, we would have to do
$user = User::find($userId);
return $user->email;
// Open - https://example.com/users/1
// Response - gauravmakhecha@gmail.com$request->validate([
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
// Otherwise would have to put tons of
// `if` conditions before our main logic.
// This won't let the user specify same title
// or skip the author details.$schedule->command('mumbai:meetup')
->weekends()
->hourly()
->timezone('India/Kolkata')
->between('11:00', '14:00')
;
// Run `mumbai:meetup` command
// hourly
// on weekends
// between 11 AM and 2 PM
// in the indian timezone.
// And don't forget `Vada Pav`App\Flight::withCount('passengers')
->with('routes')
->whereHas('routes', function ($query) {
$query->where('over_the_ocean', false);
})
->where('is_domestic', 1)
->orWhere('cost', '<=', 1000)
->orderBy('name')
->limit(10)
->get()
;
// Similar to plain English, isn't it?// Inside a service provider
public function boot()
{
Response::macro('caps', function ($val) {
return Response::make(strtoupper($val));
});
}
// Somewhere in the app
return response()->caps('foo');$attendees = Attendee::where('blind_bird', 1)
->get()
;
// instead of
$attendees->each(function ($attendee) {
$attendee->sayThankYou();
});
$attendees->each->sayThankYou();
// average, avg, contains, each, every,
// filter, first, flatMap, groupBy, keyBy,
// map, max, min, partition, reject, some,
// sortBy, sortByDesc, sum, and unique.- Ignition
- Laravel Debugbar
- Laravel Passport
- Laravel Horizon
- Laravel Telescope
- All packages by Spatie
Mail::to($user)->send(new OrderShipped($order));
// Sends an email based on the configuration.
// I can't even think how would I consider
// config based emails manually
Auth::login($user);
// instead of
new(\Illuminate\Auth\AuthManager)->login($user);
// Best thing: These can be mocked for testing.Service providers are the central place of all Laravel application bootstrapping. Your own application, as well as all of Laravel's core services are bootstrapped via service providers.
and go through a request lifecycle to understand them.
$kernel = $app->make(
Illuminate\Contracts\Http\Kernel::class
);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();public/index.php
public function handle($request)
{
try {
$request->enableHttpMethodParameterOverride();
$response = $this->sendRequestThroughRouter(
$request
);
}
...
return $response;
}
Illuminate/Foundation/Http/Kernel.php
index.php -> Kernel.php@handle()
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
$this->bootstrap();
...
}Illuminate/Foundation/Http/Kernel.php
index.php -> Kernel.php@handle() -> @sendRequestThroughRouter()
public function bootstrap()
{
if (! $this->app->hasBeenBootstrapped()) {
$this->app->bootstrapWith(
$this->bootstrappers()
);
}
}Illuminate/Foundation/Http/Kernel.php
index.php -> Kernel.php@handle() -> @sendRequestThroughRouter() -> @bootstrap()
protected $bootstrappers = [
\Ill.\Found.\Bootstrap\LoadEnvironmentVariables::cl.,
\Ill.\Found.\Bootstrap\LoadConfiguration::class,
\Ill.\Found.\Bootstrap\HandleExceptions::class,
\Ill.\Found.\Bootstrap\RegisterFacades::class,
\Ill.\Found.\Bootstrap\RegisterProviders::class,
\Ill.\Found.\Bootstrap\BootProviders::class,
];Illuminate/Foundation/Http/Kernel.php
'providers' => [
Ill.\Auth\AuthServiceProvider::class,
Ill.\Broadcasting\BroadcastServiceProvider::class,
// Lots of service providers by the framework
// ...
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
],config/app.php
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
//
}
public function boot()
{
//
}
}
app/Providers/AppServiceProvider.php
Additionally, it can bind things to the Service container
}
Package Development
// What can we do in service providers?
- Load/merge configuration files
- Load routes
- Load migrations
- Load translations
- Load views
- Add commands
- Load assetsaka Breaking news
Some of our open-source packages (https://github.com/freshbitsweb/)
The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection.
require __DIR__.'/../vendor/autoload.php';
// Turn On The Lights
$app = require_once __DIR__.'/../bootstrap/app.php';public/index.php
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
return $app;bootstrap/app.php
1st use case
$this->app->bind(
'Illuminate\Contracts\Cache\Repository',
'Illuminate\Cache\FileStore'
);in a service provider...
$this->app->when(PhotoController::class)
->needs(Filesystem::class)
->give(Storage::disk('local'));
$this->app->when([VideoController::class])
->needs(Filesystem::class)
->give(Storage::disk('s3'));use Ill.\Contracts\Cache\Repository as CacheContract;
...
public function __construct(CacheContract $cache)
{
$this->cache = $cache;
}
...
public function write($sessionId, $data)
{
return $this->cache->put(...);
}Illuminate/Session/CacheBasedSessionHandler.php
Resolve the class in your app using the service container instead of creating a new instance manually.
And create a dummy implementation of a class when testing your application.
2nd use case
use App\Services\Salesforce;
// instead of
$salesforce = new Salesforce();
$salesforce = resolve(Salesforce::class);
$salesforce->addLead($user);
// or
public function __construct(Salesforce $salesforce)
{
$this->salesforce = $salesforce;
}somewhere in your app...
use App\Services\Salesforce;
use Tests\Mocks\Salesforce as SalesforceMock;
...
public function setUp()
{
parent::setUp();
// Mock Salesforce calls
$this->app->bind(Salesforce::class, function () {
return new SalesforceMock;
});
}Tests/TestCase.php
The service container is, after all, a container, right?
We can put anything in there as per our requirement as far as we use it wisely.
3rd use case
// Set the binding to login Rider automatically
app()->singleton('impersonate_rider', function () {
return true;
});app/Http/Controllers/API/ResetPasswordController.php
public function validateForPassportPasswordGrant($password)
{
if (app()->offsetExists('impersonate_rider')) {
return true;
}
...
}app/Rider.php
Laravel facades serve as "static proxies" to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.
Cache::get('my_lottery_number');class Cache extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'cache';
}
}Illuminate/Support/Facades/Cache.php
public function registerCoreContainerAliases()
{
foreach ([
'auth' => [\Illuminate\Auth\AuthManager::class],
'cache' => [\Ill.\Cache\CacheManager::class],
'files' => [\Ill.\Filesystem\Filesystem::class],
'session' => [\Ill.\Session\SessionManager::c.],
...
] as $key => $aliases) {
foreach ($aliases as $alias) {
$this->alias($key, $alias);
}
}
}Illuminate/Foundation/Application.php
public static function __callStatic($method, $args)
{
// Gets instance from container using the 'key'
$instance = static::getFacadeRoot();
...
return $instance->$method(...$args);
}Illuminate/Support/Facades/Facade.php
// This means that
Cache::get('my_lottery_number');
// is same as
(new \Ill.\Cache\CacheManager())->get('my_lottery_number');public function testOrderShipping()
{
Mail::fake();
// Perform order shipping...
Mail::assertSent(
OrderShipped::class,
function ($mail) use ($order) {
return $mail->order->id === $order->id;
}
);
Mail::assertNotSent(AnotherMailable::class);
}Tests/Feature/ExampleTest.php
public function testGetIndex()
{
Cache::shouldReceive('get')
->once()
->with('my_lottery_number')
->andReturn('420');
$response = $this->get('/users');
// ...
}Tests/Feature/UserControllerTest.php
There is much more in the framework to bring magic into your development. Keep hunting...
They help make apps Readable, Maintainable, Well-tested, and Well-documented.