Skip to content

Instantly share code, notes, and snippets.

@monbang
Last active March 31, 2020 14:57
Show Gist options
  • Save monbang/a27dc0112e4ccf2ff7015992fb516b77 to your computer and use it in GitHub Desktop.
Save monbang/a27dc0112e4ccf2ff7015992fb516b77 to your computer and use it in GitHub Desktop.
SOLID-laracast
<?php
namespace Acme\Reporting;
use Auth, DB, Exception;
class SalesReporter
{
public functon between($startDate, $endDate) {
// Q: do we need a user for this class to work ??
// auth is application login move to controller
if (!Auth::check()) throw new Exception('login required');
$sales = $this->queryDBForSalesBetween($startDate, $endDate);
return $this->format($sales);
}
// Q: if we change our db layer than ? Too many consumers of this class
protected function queryDBForSalesBetween($startDate, $endDate) {
return DB::table('sales')->whereBetween('created_at', [$startDate, $endDate])->sum('change') / 100;
}
// Q: now we need json response ??
// Q: is it consumers responsibility to format ?
// Q: if we need some class based formating than ???
protected function format($sales) {
return "<h1>Saled: $sales</h1>";
}
}
// router php
Route::get('sales-report', function() {
$report = new Acme\Reporting\SalesReporter();
$begin = Carbon::now()->subDays(10);
$end = Carbon::now();
return $report->between($begin, $end);
});
/**
Q: how many resons this class has to change ?
Q: what are it's responsibilities ?
Goal: A class should have single responsibility
*/
// extract db responsibilities to separete class
class SalesRepository
{
// Q: if we change our db layer than ? Too many consumers of this class
// A: now we have extracted to a separate class no problem
public function between($startDate, $endDate) {
return DB::table('sales')->whereBetween('created_at', [$startDate, $endDate])->sum('change') / 100;
}
}
// for extracting the format method
interface SalesOutputInterface {
public function output($sales);
}
// extracted the format method
class HtmlOutput implements SalesOutputInterface {
public function output($sales) {
return "<h1>Saled: $sales</h1>";
}
}
class SalesReporter
{
// move query/saving operations to repository interface/class
private $repo;
public function __constructor(SalesRepository $repo) {
$this->repo = $repo;
}
public functon between($startDate, $endDate, SalesOutputInterface $formatter) {
// db operation extracted
$sales = $this->repo->between($startDate, $endDate);
return $formatter->output($sales);
}
}
Route::get('sales-report', function() {
$report = new Acme\Reporting\SalesReporter(new SalesRepository);
$begin = Carbon::now()->subDays(10);
$end = Carbon::now();
return $report->between($begin, $end, new HtmlOutput);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment