by 尤川豪
/views
/controllers
/models
/Article.php
/User.php
/Order.php
/Product.php
/Category.php
/Coupon.php
model
entity
class Article extends Eloquent
{
public function getDate(){/*...*/}
// 呈現給台灣地區的時間格式
public function getTaiwaneseDateTime(){/*...*/}
// 呈現給歐美地區的時間格式
public function getWesternDateTime(){/*...*/}
public function getTaiwaneseDate(){/*...*/}
public function getWesternDate(){/*...*/}
}
class ArticlePresenter
{
protected $article;
public function __construct(Article $article)
{
$this->article = $article;
}
// 呈現給台灣地區的時間格式
public function getTaiwaneseDateTime(){
return date('Y-m-d', $this->article->created_at);
}
// 呈現給歐美地區的時間格式
public function getWesternDateTime(){/*...*/}
public function getTaiwaneseDate(){/*...*/}
public function getWesternDate(){/*...*/}
}
@foreach($articles as $article)
<?php $presenter = new ArticlePresenter($article); ?>
發文日期:{{ $presenter->getTaiwaneseDate() }}
@endforeach
class Article extends Eloquent
{
public function present()
{
return new ArticlePresenter($this);
}
}
@foreach($articles as $article)
發文日期:{{ $article->present()->getTaiwaneseDate() }}
@endforeach
class Article extends Eloquent
{
protected $presenterInstance;
public function present()
{
if ( ! $this->presenterInstance)
{
$this->presenterInstance = new ArticlePresenter($this);
}
return $this->presenterInstance;
}
}
trait PresentableTrait {
protected $presenterInstance;
public function present()
{
// ...
if ( ! $this->presenterInstance)
{
$this->presenterInstance = new $this->presenter($this);
}
return $this->presenterInstance;
}
}
use Laracasts\Presenter\PresentableTrait;
class Article extends \Eloquent {
use PresentableTrait;
protected $presenter = 'ArticlePresenter';
}
use Laracasts\Presenter\Presenter;
class ArticlePresenter extends Presenter {
// 呈現給台灣地區的時間格式
public function getTaiwaneseDateTime(){/*...*/}
// 呈現給歐美地區的時間格式
public function getWesternDateTime(){/*...*/}
public function getTaiwaneseDate(){/*...*/}
public function getWesternDate(){/*...*/}
}
@foreach($articles as $article)
發文日期:{{ $article->present()->getTaiwaneseDate() }}
@endforeach
$users = User::where('votes', '>', 100)
->whereGender('W')
->orderBy('created_at')
->get();
還容易duplicate
$users = User::popular()->women()->orderBy('created_at')->get();
$users = User::where('votes', '>', 100)->whereGender('W')->orderBy('created_at')->get();
用了Query Scope
沒用Query Scope
class User extends Eloquent {
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
public function scopeWomen($query)
{
return $query->whereGender('W');
}
}
Laravel官方提供的Query Scopes...
class UserRepository
{
public function getPopularWomen()
{
return User::where('votes', '>', 100)->whereGender('W')->orderBy('created_at')->get();
}
}
$repository = new UserRepository();
$users = $repository->getPopularWomen();
class UserController extends BaseController
{
protected $users;
public function __construct(UserRepository $repository)
{
parent::__construct();
$this->users = $repository;
}
public function getIndex()
{
$women = $this->users->getPopularWomen();
}
}
$users = User::where('votes', '>', 100)->whereGender('W')->orderBy('created_at')->get();
$users = User::popular()->women()->orderBy('created_at')->get();
$users = $this->users->getPopularWomen();
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Collection;
abstract class EloquentRepository
{
protected $model;
public function __construct($model = null)
{
$this->model = $model;
}
public function getById($id)
{
return $this->model->find($id);
}
public function getAll()
{
return $this->model->all();
}
public function save($data)
{
if ($data instanceOf Model) {
return $this->storeEloquentModel($data);
}
}
public function saveMany($collection)
{
foreach($collection as $model)
{
$this->storeEloquentModel($model);
}
}
public function delete($model)
{
return $model->delete();
}
protected function storeEloquentModel($model)
{
if ($model->getDirty()) {
return $model->save();
} else {
return $model->touch();
}
}
}
都用Active Record了,
testing避開資料庫可不容易...
$validation = Validator::make(
array(
'name' => Input::get( 'name' ),
'email' => Input::get( 'email' ),
),
array(
'name' => array( 'required', 'alpha_dash' ),
'email' => array( 'required', 'email' ),
)
);
if ( $validation->fails() ) {
$errors = $validation->messages();
}
// ...
還容易duplicate
class Ball extends Eloquent
{
private $rules = array(
'color' => 'required|alpha|min:3',
'size' => 'required',
// .. more rules here ..
);
public function validate($data)
{
// make a new validator object
$v = Validator::make($data, $this->rules);
// return the result
return $v->passes();
}
}
$b = new Ball();
if ($b->validate(Input::all())){
// success code
}else{
// failure code
}
class ArticleForm
{
protected $validationRules = [
'title' => 'required',
'content' => 'required',
];
protected $inputData;
protected $validator;
public function __construct($input)
{
$this->inputData = $input;
}
public function isValid()
{
$this->validator = Validator::make($this->input, $this->validationRules);
return $this->validator->passes();
}
public function getErrors()
{
return $this->validator->errors();
}
}
$form = new ArticleForm( Input::all() );
if ( ! $form->isValid() ){
return Redirect::back()->with( [ 'errors' => $form->getErrors() ] );
}
$article = new Article( Input::only('title', 'content', 'status') );
$article->save();
class ArticleForm
{
protected $validationRules = [
'title' => 'required',
'content' => 'required',
];
protected $inputData;
protected $validator;
public function __construct($input)
{
$this->inputData = $input;
}
public function isValid()
{
$this->validator = Validator::make($this->input, $this->validationRules);
return $this->validator->passes();
}
public function getErrors()
{
return $this->validator->errors();
}
}
class FormModel
{
protected $validationRules;
protected $inputData;
protected $validator;
public function __construct($input)
{
$this->inputData = $input;
}
public function isValid()
{
$this->validator = Validator::make($this->input, $this->validationRules);
return $this->validator->passes();
}
public function getErrors()
{
return $this->validator->errors();
}
}
class ArticleForm extends FormModel
{
protected $validationRules = [
'title' => 'required',
'content' => 'required',
];
}
protected $happyArticleValidationRules;
protected $angryArticleValidationRules;
protected $funnyArticleValidationRules;
public function isValidHappy()
{
$this->validator = Validator::make($this->input, $this->happyArticleValidationRules);
return $this->validator->passes();
}
public function isValidAngry()
{
$this->validator = Validator::make($this->input, $this->angryArticleValidationRules);
return $this->validator->passes();
}
public function isValidFunny()
{
$this->validator = Validator::make($this->input, $this->funnyArticleValidationRules);
return $this->validator->passes();
}
月租費就收400元好了
class CheckoutController extends Controller
{
public function postSubmitOrder()
{
// 1. 利用Stripe從信用卡扣款
\Stripe\Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => array(
// 這是一個簡化的範例。請別把信用卡資料存在資料庫。
"number" => $user->creditCard->number,
"exp_month" => $user->creditCard->expMonth,
"exp_year" => $user->creditCard->expYear,
"cvc" => $user->creditCard->cvc
),
));
// 2. 建立訂單
$order = new Order();
$order->price = 400;
$order->user_id = Auth::user()->id;
$order->save();
// 3. 發送確認Email
Mail::send('emails.confirmation', [], function($message) use ($user)
{
$message->to( $user->email )
->subject( '謝謝您的訂購。' );
});
}
}
// 1. 利用Stripe從信用卡扣款
\Stripe\Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => array(
// 這是一個簡化的範例。請別把信用卡資料存在資料庫。
"number" => $user->creditCard->number,
"exp_month" => $user->creditCard->expMonth,
"exp_year" => $user->creditCard->expYear,
"cvc" => $user->creditCard->cvc
),
));
// 2. 建立訂單
$order = new Order();
$order->price = 400;
$order->user_id = Auth::user()->id;
$order->save();
// 3. 發送確認Email
Mail::send('emails.confirmation', [], function($message) use ($user)
{
$message->to( $user->email )
->subject( '謝謝您的訂購。' );
});
// 1. 利用Stripe從信用卡扣款
\Stripe\Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => array(
// 這是一個簡化的範例。請別把信用卡資料存在資料庫。
"number" => $user->creditCard->number,
"exp_month" => $user->creditCard->expMonth,
"exp_year" => $user->creditCard->expYear,
"cvc" => $user->creditCard->cvc
),
));
// 2. 建立訂單
$order = new Order();
$order->price = 400;
$order->user_id = Auth::user()->id;
$order->save();
// 3. 發送確認Email
Mail::send('emails.confirmation', [], function($message) use ($user)
{
$message->to( $user->email )
->subject( '謝謝您的訂購。' );
});
// 1. 利用Stripe從信用卡扣款
\Stripe\Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => array(
// 這是一個簡化的範例。請別把信用卡資料存在資料庫。
"number" => $user->creditCard->number,
"exp_month" => $user->creditCard->expMonth,
"exp_year" => $user->creditCard->expYear,
"cvc" => $user->creditCard->cvc
),
));
// 2. 建立訂單
$order = new Order();
$order->price = 400;
$order->user_id = Auth::user()->id;
$order->save();
// 3. 發送確認Email
Mail::send('emails.confirmation', [], function($message) use ($user)
{
$message->to( $user->email )
->subject( '謝謝您的訂購。' );
});
// 1. 利用Stripe從信用卡扣款
\Stripe\Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => array(
// 這是一個簡化的範例。請別把信用卡資料存在資料庫。
"number" => $user->creditCard->number,
"exp_month" => $user->creditCard->expMonth,
"exp_year" => $user->creditCard->expYear,
"cvc" => $user->creditCard->cvc
),
));
// 2. 建立訂單
$order = new Order();
$order->price = 400;
$order->user_id = Auth::user()->id;
$order->save();
// 3. 發送確認Email
Mail::send('emails.confirmation', [], function($message) use ($user)
{
$message->to( $user->email )
->subject( '謝謝您的訂購。' );
});
class User extends Eloquent
{
public function checkout()
{
// 1. 利用Stripe從信用卡扣款
\Stripe\Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => array(
// 這是一個簡化的範例。請別把信用卡資料存在資料庫。
"number" => $this->creditCard->number,
"exp_month" => $this->creditCard->expMonth,
"exp_year" => $this->creditCard->expYear,
"cvc" => $this->creditCard->cvc
),
));
// 2. 建立訂單
$order = new Order();
$order->price = 400;
$order->user_id = $this->id;
$order->save();
// 3. 發送確認Email
Mail::send('emails.confirmation', [], function($message) use ($user)
{
$message->to( $user->email )
->subject( '謝謝您的訂購。' );
});
}
}
// 原本的Checkout controller
$user->checkout();
// 瀏覽專輯頁面一鍵AJAX付款的對應controller
$user->checkout();
// 用iframe做plugin讓藝人能放進官網的controller
$user->checkout();
// 處理手機App結帳的controller
$user->checkout();
工程師A:是否變得優雅許多!
class Order extends Eloquent
{
public function checkout()
{
// 1. 利用Stripe從信用卡扣款
\Stripe\Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
$user = User::find($this->user_id);
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => array(
// 這是一個簡化的範例。請別把信用卡資料存在資料庫。
"number" => $user->creditCard->number,
"exp_month" => $user->creditCard->expMonth,
"exp_year" => $user->creditCard->expYear,
"cvc" => $user->creditCard->cvc
),
));
// 2. 發送確認Email
Mail::send('emails.confirmation', [], function($message) use ($user)
{
$message->to( $user->email )
->subject( '謝謝您的訂購。' );
});
}
}
// 原本的Checkout controller
$order = new Order(
Auth::user()->id,
400
);
$order->checkout();
// 瀏覽專輯頁面一鍵AJAX付款的對應controller
$order = new Order(
Auth::user()->id,
400
);
$order->checkout();
// 用iframe做plugin讓藝人能放進官網的controller
$order = new Order(
Auth::user()->id,
400
);
$order->checkout();
// 處理手機App結帳的controller
$order = new Order(
Auth::user()->id,
400
);
$order->checkout();
工程師B:這才叫做優雅!
class BillService
{
public function checkout(User $user)
{
// 1. 利用Stripe從信用卡扣款
\Stripe\Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => array(
// 這是一個簡化的範例。請別把信用卡資料存在資料庫。
"number" => $user->creditCard->number,
"exp_month" => $user->creditCard->expMonth,
"exp_year" => $user->creditCard->expYear,
"cvc" => $user->creditCard->cvc
),
));
// 2. 建立訂單
$order = new Order();
$order->price = 400;
$order->user_id = $user->id;
$order->save();
// 3. 發送確認Email
Mail::send('emails.confirmation', [], function($message) use ($user)
{
$message->to( $user->email )
->subject( '謝謝您的訂購。' );
});
}
}
// 原本的Checkout controller
$service = new BillService();
$service->checkout(
Auth::user()
);
// 瀏覽專輯頁面一鍵AJAX付款的對應controller
$service = new BillService();
$service->checkout(
Auth::user()
);
// 用iframe做plugin讓藝人能放進官網的controller
$service = new BillService();
$service->checkout(
Auth::user()
);
// 處理手機App結帳的controller
$service = new BillService();
$service->checkout(
Auth::user()
);
工程師C:兩位別吵了!都沒擁有它!
多個entity爭執不下、
行為本身又很複雜的時候,
獨立成service。
class Document extends Eloquent
{
public function addPermission($value, $type, $role, $withLink = false)
{
$googleClient = new Google_Client();
$googleClient->setClientId(Config::get('google_drive.clientId'));
$googleClient->setClientSecret(Config::get('google_drive.clientSecret'));
$googleClient->setRedirectUri(Config::get('google_drive.redirectUri'));
$googleClient->setAccessType('offline');
$googleClient->setScopes(array('https://www.googleapis.com/auth/drive'));
$googleClient->setApprovalPrompt('force');
$googleService = new Google_Service_Drive($this->googleClient);
$googleClient->setAccessToken(/*...*/);
$newPermission = new Google_Service_Drive_Permission();
$newPermission->setValue($value);
$newPermission->setType($type);
$newPermission->setRole($role);
$newPermission->setWithLink($withLink);
$googleService->permissions->insert($this->fileId, $newPermission);
}
}
<?php
class GoogleDriveService{
protected $googleClient;
protected $googleService;
public function __construct(){
$this->googleClient = new Google_Client();
$this->googleClient->setClientId(Config::get('google_drive.clientId'));
$this->googleClient->setClientSecret(Config::get('google_drive.clientSecret'));
$this->googleClient->setRedirectUri(Config::get('google_drive.redirectUri'));
$this->googleClient->setAccessType('offline');
$this->googleClient->setScopes(array('https://www.googleapis.com/auth/drive'));
$this->googleClient->setApprovalPrompt('force');
$this->googleService = new Google_Service_Drive($this->googleClient);
$this->googleClient->setAccessToken(TokenServiceProider::getAccessToken());
}
public function insertPermission( $fileId, $value, $type, $role, $withLink = false) {
$newPermission = new Google_Service_Drive_Permission();
$newPermission->setValue($value);
$newPermission->setType($type);
$newPermission->setRole($role);
$newPermission->setWithLink($withLink);
$this->googleService->permissions->insert($fileId, $newPermission);
}
}
class Document extends Eloquent
{
public function addPermission($value, $type, $role, $withLink = false)
{
$service = new GoogleDriveService();
$service->insertPermission($this->fileId, $value, $type, $role, $withLink = false) ;
}
}
<?php
class GoogleDriveService{
protected $googleClient;
protected $googleService;
public function __construct(){
$this->googleClient = new Google_Client();
$this->googleClient->setClientId(Config::get('google_drive.clientId'));
$this->googleClient->setClientSecret(Config::get('google_drive.clientSecret'));
$this->googleClient->setRedirectUri(Config::get('google_drive.redirectUri'));
$this->googleClient->setAccessType('offline');
$this->googleClient->setScopes(array('https://www.googleapis.com/auth/drive'));
$this->googleClient->setApprovalPrompt('force');
$this->googleService = new Google_Service_Drive($this->googleClient);
$this->googleClient->setAccessToken(TokenServiceProider::getAccessToken());
}
public function insertPermission( $fileId, $value, $type, $role, $withLink = false) {
$newPermission = new Google_Service_Drive_Permission();
$newPermission->setValue($value);
$newPermission->setType($type);
$newPermission->setRole($role);
$newPermission->setWithLink($withLink);
$this->googleService->permissions->insert($fileId, $newPermission);
}
}
<?php namespace Howtomakeaturn\GoogleDriveKing;
use Google_Clinet;
use Google_Service_Drive;
class GoogleDriveKing{
protected $googleClient;
protected $googleService;
public function __construct(){
$this->googleClient = new Google_Client();
$this->googleClient->setClientId(Config::get('google_drive.clientId'));
$this->googleClient->setClientSecret(Config::get('google_drive.clientSecret'));
$this->googleClient->setRedirectUri(Config::get('google_drive.redirectUri'));
$this->googleClient->setAccessType('offline');
$this->googleClient->setScopes(array('https://www.googleapis.com/auth/drive'));
$this->googleClient->setApprovalPrompt('force');
$this->googleService = new Google_Service_Drive($this->googleClient);
$this->googleClient->setAccessToken(TokenServiceProider::getAccessToken());
}
// ...
}
<?php
class BackupController extends Controller
{
public function postDownload()
{
$results = DB::select('select * from users');
// ...
}
}
<?php
namespace Howtomakeaturn\CSVDumper;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
class CSVDumper{
protected $tableName;
protected $doctrineSchemaManager;
protected $queryBuilder;
public function __construct($tableName)
{
$this->tableName = $tableName;
$this->doctrineSchemaManager = Schema::getConnection()->getDoctrineSchemaManager();
$this->queryBuilder = DB::table($tableName);
}
// ...
}
<?php
class BackupController extends Controller
{
public function postDownload()
{
// ...
foreach ($tableNames as $name) {
$dumper = new Howtomakeaturn\CSVDumper\CSVDumper($name);
$result = $dumper->dumpAndStoreTable(storage_path() . '/database-backup');
}
// ...
}
}
/views
/controllers
/models
/Article.php
/User.php
/Order.php
/Product.php
/Category.php
/Coupon.php
/views
/controllers
/MyApp
/Article
/Article.php
/Presenter.php
/Repository.php
/Form.php
/User
/User.php
/Presenter.php
/Repository.php
/Form.php
/Order
// ...
/Service
/FirstService.php
/SecondService.php
/GithubName
/CoolPackageOne
/CoolPackageTwo
/CoolPackageThree
/views
/controllers
/MyApp
/Entities
/Article.php
/User.php
/Presenters
/Article.php
/User.php
/Repositories
/Article.php
/User.php
/Forms
/Article.php
/User.php
// ...
/Service
/FirstService.php
/SecondService.php
/GithubName
/CoolPackageOne
/CoolPackageTwo
/CoolPackageThree
Factory, Search, Utility, Observer, Listener...etc