Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP 2大 web フレームワークの徹底比較!

Shohei Okada
September 13, 2017

PHP 2大 web フレームワークの徹底比較!

2017/09/13 に開催したサポーターズ CoLab 勉強会の資料です。
https://supporterzcolab.com/event/137/

Shohei Okada

September 13, 2017
Tweet

More Decks by Shohei Okada

Other Decks in Programming

Transcript

  1. 1. 背景 2. Model 層の比較 3. View 層の比較 4. Controller

    層の比較 5. その他特徴 6. 全体考察・まとめ 6 目次
  2. 1. 背景 2. Model 層の比較 3. View 層の比較 4. Controller

    層の比較 5. その他特徴 6. 全体考察・まとめ 7 目次
  3. • もともと CakePHP のみを利用していた • オフショア開発をやっていた時代にベトナムの開発チームから Laravel を使いたいという要望が出て採用 • 以降、ソリューションチームでは

    Laravel が主流に • 1つ1つのシステムが小粒なので毎回違う技術を選べる • Slim や FuelPHP を採用したシステムも • 「チーム移動時のコスト」 < 「多様性により得られる恩恵」 • 同じPHP なので、そこまで大きなギャップではない • 新たな知見を得られやすい 8 背景 - なぜフレームワークが混在しているか
  4. • サグーワークスのリニューアル(2017年1月) • CakePHP 1.3 → CakePHP 3.2 にバージョンアップ •

    https://www.wantedly.com/companies/willgate2/post_a rticles/70451 • 新しいコンサルティングツール開発(現在開発中) • Laravel 5.4 を採用 • 社内に双方の最新メジャーバージョンの知見 • → 「比較・考察は価値のある情報になるのでは?」 9 背景 – 今回の勉強会開催の理由
  5. 10

  6. 注意:スライドの内容 • 公式サイト等からの引用については枠線で囲い 斜字体で表記します 例) • 実際に利用したうえでの私見や考察には 「【私見】」や「【考察】」と明記します 13 The

    Model layer represents the part of your application that implements the business logic. モデル層はビジネスロジックを実装するアプリケーションの部品を表しま す。
  7. 1. 背景 2. Model 層の比較 3. View 層の比較 4. Controller

    層の比較 5. その他特徴 6. 全体考察・まとめ 14 目次
  8. • ディレクトリ 15 Model 層の比較 The Model layer represents the

    part of your application that implements the business logic. モデル層はビジネスロジックを実装するアプリケーションの部品を表しま す。 . ├── src/ : : │ ├── Model/ │ │ ├── Behavior/ │ │ ├── Entity/ │ │ └── Table/ : :
  9. • CakePHP ORM • 3つの概念に分かれる • Table • Entity •

    Behavior 16 Model 層の比較 The CakePHP ORM borrows ideas and concepts from both ActiveRecord and Datamapper patterns. It aims to create a hybrid implementation that combines aspects of both patterns to create a fast, simple to use ORM. CakePHP の ORM はアクティブレコードやデータマッパーパターンのアイ デアやコンセプトを拝借しています。 その目的は、早く作成し、シンプ ルに ORM を利用するという2つの利点を混成させるためです。
  10. • Table • Entity 17 Model 層の比較 They allow you

    to save new records, modify/delete existing ones, define relations, and perform bulk operations. これらを利用することで、新しいレコードを保存したり、 既存データの 編集/削除、リレーションの定義、そして一括処理ができます。 Entities represent individual records and allow you to define row/record level behavior & functionality. エンティティーは、個々のレコードを意味し、 行/レコードレベルの振る 舞いや機能の定義を可能にします。
  11. • Behavior • 【考察】 • 処理の種類ごとに記述する場所が規約で決められている • どこに書くべきか、悩まずに記述できる • 組み合わせやすい分類になっている

    • 共通処理は Behavior • テーブル単位の操作の Table • レコード単位の操作は Entity 18 Model 層の比較 Behaviors provide a convenient way to package up behavior that is common across many models. ビヘイビアーは、多くのモデルで共通の振る舞いをまとめる便利な方法を 提供します。
  12. • “Models” のようなディレクトリは存在しない • 【私見】意訳すると、 「“models” という言葉が指す意味は人によって変わるので、 開発したいモノに合わせて各々が判断した場所に置けばよい」 19 Model

    層の比較 When getting started with Laravel, many developers are confused by the lack of a models directory. However, the lack of such a directory is intentional. We find the word "models" ambiguous since it means many different things to many different people. For this reason, we choose to place Eloquent models in the app directory by default, and allow the developer to place them somewhere else if they choose.
  13. • 明示的に Model と言っているのは Eloquent ORM のみ • php artisan

    make:model の説明 「Create a new Eloquent model class」 • 【考察】 • ORM 即ち Model という意味ではない • Eloquent model class にビジネスロジックを 記述してもよい • Eloquent model class を単なる ORM とみなし 他の階層構造にビジネスロジックを記述してもよい 20 Model 層の比較
  14. • Eloquent ORM • 【私見】「Laravel 強み」としてよく挙げられる • 【考察】比較的シンプルな記述ができるのが理由か • 読み方がよく議論になる

    • 【私見】では「エロクワント」と読む 21 Model 層の比較 The Eloquent ORM included with Laravel provides a beautiful, simple ActiveRecord implementation for working with your database.
  15. 実現したいこと • 異なるテーブルのレコード 「クライアントお問い合わせ」 「ユーザお問い合わせ」 • どちらも問い合わせ内容を body というカラムに格納 •

    保存する前に body 内に含まれる特殊文字を HTML エンティティに変換したい 22 Model 層の比較 - コード比較 case 1 ※これくらいの処理は本来、ミューテータを使えば良い
  16. 23 Model 層の比較 - コード比較 case 1 class SafeStringBehavior extends

    Behavior { public function beforeSave($event, $entity, $options) { // h() -> htmlspecialchars() $entity->body = h($entity->body); return true; } } class ClientContactsTable extends Table { public function initialize(array $config) { parent::initialize($config); // SafeStringBehavior の読み込み $this->addBehavior('SafeString'); } } // UserContractsTable も同様に記述
  17. 24 Model 層の比較 - コード比較 case 1 class SafeStringBehavior extends

    Behavior { public function beforeSave($event, $entity, $options) { // h() -> htmlspecialchars() $entity->body = h($entity->body); return true; } } class ClientContactsTable extends Table { public function initialize(array $config) { parent::initialize($config); // SafeStringBehavior の読み込み $this->addBehavior('SafeString'); } } // UserContractsTable も同様に記述する • 共通の挙動は Behavior に記述する • 保存前実行される処理は beforeSave 関数に記述する
  18. 25 Model 層の比較 - コード比較 case 1 class SafeStringBehavior extends

    Behavior { public function beforeSave($event, $entity, $options) { // h() -> htmlspecialchars() $entity->body = h($entity->body); return true; } } class ClientContactsTable extends Table { public function initialize(array $config) { parent::initialize($config); // SafeStringBehavior の読み込み $this->addBehavior('SafeString'); } } // UserContractsTable も同様に記述する • Table に addBehavior() を記述する
  19. パターン1 26 Model 層の比較 - コード比較 case 1 class ContactObserver

    { public function saving(Model $model) { // e() -> htmlspecialchars() $model->body = e($model->body); } } // UserContact も同様に記述 class ClientContact extends Model { } class AppServiceProvider extends ServiceProvider { public function boot() { ClientContact::observe(ContactObserver::class); UserContact::observe(ContactObserver::class); } }
  20. パターン1 27 Model 層の比較 - コード比較 case 1 class ContactObserver

    { public function saving(Model $model) { // e() -> htmlspecialchars() $model->body = e($model->body); } } // UserContact も同様に記述 class ClientContact extends Model { } class AppServiceProvider extends ServiceProvider { public function boot() { ClientContact::observe(ContactObserver::class); UserContact::observe(ContactObserver::class); } } • 保存処理の前に発火する “saving” イベントを観測する Observer を作成
  21. パターン1 28 Model 層の比較 - コード比較 case 1 class ContactObserver

    { public function saving(Model $model) { // e() -> htmlspecialchars() $model->body = e($model->body); } } // UserContact も同様に記述 class ClientContact extends Model { } class AppServiceProvider extends ServiceProvider { public function boot() { ClientContact::observe(ContactObserver::class); UserContact::observe(ContactObserver::class); } } • ServiceProvider 内で対象 Model に Observer を登録
  22. パターン1 29 Model 層の比較 - コード比較 case 1 class ContactObserver

    { public function saving(Model $model) { // e() -> htmlspecialchars() $model->body = e($model->body); } } // UserContact も同様に記述 class ClientContact extends Model { } class AppServiceProvider extends ServiceProvider { public function boot() { ClientContact::observe(ContactObserver::class); UserContact::observe(ContactObserver::class); } } • 欠点:Modelの定義から 処理を辿れない
  23. パターン2 30 Model 層の比較 - コード比較 case 1 // UserContact

    も同様に記述 class ClientContact extends Model { protected $events = [ 'saving' => ClientContactSaving::class, ]; } class Event { } // UserContractSaving も同様に記述 class ClientContactSaving extends Event { public $target; public function __construct(ClientContact $clientContact) { $this->target = $clientContact; } } class ConvertToSafeString { public function handle(Event $event) { $event->target->body = e($event->target->body); } } class EventServiceProvider extends ServiceProvider { protected $listen = [ 'ClientContactSaving' => [ ConvertToSafeString::class, ], 'UserContactSaving' => [ ConvertToSafeString::class, ], ]; }
  24. パターン2 31 Model 層の比較 - コード比較 case 1 // UserContact

    も同様に記述 class ClientContact extends Model { protected $events = [ 'saving' => ClientContactSaving::class, ]; } class Event { } // UserContractSaving も同様に記述 class ClientContactSaving extends Event { public $target; public function __construct(ClientContact $clientContact) { $this->target = $clientContact; } } class ConvertToSafeString { public function handle(Event $event) { $event->target->body = e($event->target->body); } } class EventServiceProvider extends ServiceProvider { protected $listen = [ 'ClientContactSaving' => [ ConvertToSafeString::class, ], 'UserContactSaving' => [ ConvertToSafeString::class, ], ]; } • Model に “saving” イベントを登録
  25. パターン2 32 Model 層の比較 - コード比較 case 1 // UserContact

    も同様に記述 class ClientContact extends Model { protected $events = [ 'saving' => ClientContactSaving::class, ]; } class Event { } // UserContractSaving も同様に記述 class ClientContactSaving extends Event { public $target; public function __construct(ClientContact $clientContact) { $this->target = $clientContact; } } class ConvertToSafeString { public function handle(Event $event) { $event->target->body = e($event->target->body); } } class EventServiceProvider extends ServiceProvider { protected $listen = [ 'ClientContactSaving' => [ ConvertToSafeString::class, ], 'UserContactSaving' => [ ConvertToSafeString::class, ], ]; } • Model に対応する Event を定義
  26. パターン2 33 Model 層の比較 - コード比較 case 1 // UserContact

    も同様に記述 class ClientContact extends Model { protected $events = [ 'saving' => ClientContactSaving::class, ]; } class Event { } // UserContractSaving も同様に記述 class ClientContactSaving extends Event { public $target; public function __construct(ClientContact $clientContact) { $this->target = $clientContact; } } class ConvertToSafeString { public function handle(Event $event) { $event->target->body = e($event->target->body); } } class EventServiceProvider extends ServiceProvider { protected $listen = [ 'ClientContactSaving' => [ ConvertToSafeString::class, ], 'UserContactSaving' => [ ConvertToSafeString::class, ], ]; } • Event を捕捉した際に処理を行う Listener を定義
  27. パターン2 34 Model 層の比較 - コード比較 case 1 // UserContact

    も同様に記述 class ClientContact extends Model { protected $events = [ 'saving' => ClientContactSaving::class, ]; } class Event { } // UserContractSaving も同様に記述 class ClientContactSaving extends Event { public $target; public function __construct(ClientContact $clientContact) { $this->target = $clientContact; } } class ConvertToSafeString { public function handle(Event $event) { $event->target->body = e($event->target->body); } } class EventServiceProvider extends ServiceProvider { protected $listen = [ 'ClientContactSaving' => [ ConvertToSafeString::class, ], 'UserContactSaving' => [ ConvertToSafeString::class, ], ]; } • ServiceProvider 内で Event と Listener の対応を登録
  28. パターン2 35 Model 層の比較 - コード比較 case 1 // UserContact

    も同様に記述 class ClientContact extends Model { protected $events = [ 'saving' => ClientContactSaving::class, ]; } class Event { } // UserContractSaving も同様に記述 class ClientContactSaving extends Event { public $target; public function __construct(ClientContact $clientContact) { $this->target = $clientContact; } } class ConvertToSafeString { public function handle(Event $event) { $event->target->body = e($event->target->body); } } class EventServiceProvider extends ServiceProvider { protected $listen = [ 'ClientContactSaving' => [ ConvertToSafeString::class, ], 'UserContactSaving' => [ ConvertToSafeString::class, ], ]; } 長所 • Model から処理を追跡できる 短所 • 記述量が多い • 実現するために考えることが多い • 突如として現れる 基底クラス Event など
  29. 実現したいこと • クライアントと担当コンサルタントの多対多関係 • 担当コンサルタントの一括更新 36 Model 層の比較 - コード比較

    case 2 clients - id - name consultants - id - name client_consultant - client_id - consultant_id client_id consultant_id 1 1 1 2 1 3 client_id consultant_id 1 1 1 4 1 5
  30. 37 Model 層の比較 - コード比較 case 2 $Clients = TableRegistry::get('Clients');

    $Clients->belongsToMany( 'Consultants', ['saveStrategy' => 'replace'] ); $clientEntity = $Clients->get( 1, ['contain' => 'Consultants'] ); $clientEntity->consultants = $Clients->Consultants ->find('all') ->where(['id IN' => [1, 4, 5]]) ->all() ->toArray(); $clientEntity->dirty('consultants', true); $Clients->save($clientEntity); class Client extends Model { public function consultants() { return $this->belongsToMany('App¥Consultant'); } } class Consultant extends Model { } $client = Client::find(1); $client->consultants()->sync([1, 4, 5]);
  31. 38 Model 層の比較 - コード比較 case 2 $Clients = TableRegistry::get('Clients');

    $Clients->belongsToMany( 'Consultants', ['saveStrategy' => 'replace'] ); $clientEntity = $Clients->get( 1, ['contain' => 'Consultants'] ); $clientEntity->consultants = $Clients->Consultants ->find('all') ->where(['id IN' => [1, 4, 5]]) ->all() ->toArray(); $clientEntity->dirty('consultants', true); $Clients->save($clientEntity); class Client extends Model { public function consultants() { return $this->belongsToMany('App¥Consultant'); } } class Consultant extends Model { } $client = Client::find(1); $client->consultants()->sync([1, 4, 5]); データ取得・更新の処理
  32. CakePHP Laravel ビジネスロジック Model 層に記述する 記述箇所は規定されていない (開発者の判断に委ねられてい る) Model 層の構造

    Table/Entity/Behavior の 3つの概念に分かれている ActiveRecord 実装の ORM のみを 提供 考察 • 各々にどのような処理を 書くのかが定まっている →悩まず書ける • 簡単な処理であれば クラス定義は必要ない →コードを書く量が少ない • ロジックを Model に書いても 良いし、それ意外の場所に別の 名前で書いても良い →場面にあわせた設計思想の取 り入れができる • ORM に関する記述はシンプル になりやすい 39 【考察】Model 層比較
  33. 1. 背景 2. Model 層の比較 3. View 層の比較 4. Controller

    層の比較 5. その他特徴 6. 全体考察・まとめ 40 目次
  34. • ディレクトリ 41 View 層の比較 Views are responsible for generating

    the specific output required for the request. ビューはリクエストに対する出力を生成する役割を担います。 . ├── src/ : : │ ├── Template/ │ │ ├── Element/ : : : │ │ ├── Layout/ │ │ └── Pages/ │ └── View/ │ ├── Helper/ : :
  35. • CakePHP Template • 「PHP 別の構文」(原文:alternative PHP syntax) 42 View

    層の比較 CakePHP のテンプレートファイルは既定の拡張子を .ctp (CakePHP Template) としており、 制御構造や出力のために PHP 別の構文 を利用す ることができます。 条件分岐 繰り返し <?php if ($isSucceeded): ?> <?= $message ?> <?php endif; ?> <?php foreach ($items as $item): ?> <?= $item['name'] ?> <?php endforeach; ?>
  36. • CakePHP Template • 「PHP 別の構文」(原文:alternative PHP syntax) • つまりPHP

    43 View 層の比較 CakePHP のテンプレートファイルは既定の拡張子を .ctp (CakePHP Template) としており、 制御構造や出力のために PHP 別の構文 を利用す ることができます。 条件分岐 繰り返し <?php if ($isSucceeded): ?> <?= $message ?> <?php endif; ?> <?php foreach ($items as $item): ?> <?= $item['name'] ?> <?php endforeach; ?>
  37. • 表示のためのロジックを切り離すもの • ディレクトリ • views 以下には blade template ファイルのみが置かれる

    58 View 層の比較 Views contain the HTML served by your application and separate your controller / application logic from your presentation logic. . : ├── resources : : │ └── views :
  38. • Blade • シンプルかつ強力 • <?php ?> タグを使わずに記述 • ヘルパー等は別途実装するかパッケージインストールが必要

    59 View 層の比較 Blade is the simple, yet powerful templating engine provided with Laravel. Unlike other popular PHP templating engines, Blade does not restrict you from using plain PHP code in your views. 条件分岐 繰り返し @if ($isSucceeded) {{ $message }} @endif @foreach ($items as $item) {{ $item['name'] }} @endforeach
  39. • 継承等の機能も Blade 自体が提供 60 View 層の比較 - コード比較 case

    1 <html> <head> <title>@yield('title')</title> </head> <body> <div> @yield('content') </div> </body> </html> @extends('layouts.master') @section('title') ここにタイトル @endsection @section('content') ここにコンテンツ @endsection views/layouts/master.blade.php views/index.blade.php
  40. • Layout の場合は記述を省略できる 61 View 層の比較 - コード比較 case 1

    <html> <head> <title><?= $this->fetch('title'); ?></title> </head> <body> <div> <?= $this->fetch('content'); ?> </div> </body> </html> <?php // layoutの継承は自動で行われる // $this->extend('layout/master'); $this->assign('title', 'ここにタイトル'); // viewの出力はすべて content に出力されるので不要 //$this->start('content'); ?> ここにコンテンツ <?php // $this->end(); ?> Layout/top.ctp View/top/index.ctp
  41. 62 View 層の比較 - コード比較 case 2 {{-- パッケージ "laravelcollective/html"

    の インストール・設定が必要 --}} {!! Form::open( [ 'url' => '/user', 'method' => 'post', ] ); !!} {!! Form::text('email', '[email protected]'); !!} // デフォルトで利用可能 echo $this->Form->create( $userEntity, [ 'url' => '/user', 'type' => 'POST', ] ); echo $this->Form->input( 'email', [ 'type' => 'text', 'value' => '[email protected]', ] );
  42. 63 【考察】View 層比較 CakePHP Laravel View 層の構造 • Layout /

    View / Element / Helper の4層に分かれる • 表示の制御に携わる部分は 全て Blade が担う • CakePHP の Helper に 該当するものは実装または インストールが必要 考察 • Model 層と同様、 各々にどのような処理を 書くのかが定まっている →迷わず書ける • 共通処理の実装をどこに書くかは 規定されていない →ヘルパーの実装・Facade・ blade 拡張など実現方法は多岐にわ たる • Blade template の記法がシンプル
  43. 1. 背景 2. Model 層の比較 3. View 層の比較 4. Controller

    層の比較 5. その他特徴 6. 全体考察・まとめ 64 目次
  44. • ディレクトリ 65 Controller 層の比較 . : ├── src/ :

    : │ ├── Controller/ │ │ └── Component/ : : Your controller should handle interpreting the request data, making sure the correct models are called, and the right response or view is rendered. Controllers can be thought of as middle layer between the Model and View. コントローラーはリクエストを解釈して、適切なモデルが 呼ばれるのを 確認して、正しいレスポンスまたはビューを書き出します。コントロー ラーはモデルとビューの 中間層とみなすことができます。
  45. • Component • ルーティング • フォールバックメソッド • デフォルトで /Controller名/action名 のルーティングが

    読み込まれる 66 Controller 層の比較 コンポーネントはコントローラー間で共有されるロジックのパッケージで す。
  46. • ドキュメント内に「Controller とは何か」という説明は 明示されていない • 【考察】単にリクエストをハンドリングするロジックを 記述するクラスという位置づけ • ディレクトリ 67

    Controller 層の比較 Instead of defining all of your request handling logic as Closures in route files, you may wish to organize this behavior using Controller classes. . ├── app : : │ ├── Http/ │ │ ├── Controllers/ │ │ : : :
  47. • メソッドインジェクション • メソッドの引数に型情報を与えることで クラスの依存性解決を自動的に行う • ¥Illuminate¥Http¥Request を引数に指定することで リクエストパラメータを扱うことができる 68

    Controller 層の比較 In addition to constructor injection, you may also type-hint dependencies on your controller's methods. class UserController extends Controller { /** * Store a new user. * * @param Request $request * @return Response */ public function store(Request $request) { $name = $request->name; // } }
  48. 69 【考察】Controller 層比較 CakePHP Laravel 特徴 • Component • 共通処理を記述

    • デフォルトで /Controller名/action名 の ルーティングが読み込まれる • メソッドインジェクション • 引数に型情報を 与えることで依存性解決 考察 機能に関しての違いがあるが 基本的な役割は2つのフレームワーク間で変わらない
  49. 1. 背景 2. Model 層の比較 3. View 層の比較 4. Controller

    層の比較 5. その他特徴 6. 全体考察・まとめ 70 目次
  50. 71 同様な概念の比較 CakePHP Laravel CLI /bin/cake /artisan 設定変数の 読み書き Configure::read(‘debug’);

    Configure::write(‘debug’, true); config(‘app.debug’); config([‘app.debug’ => true]); バリデーション 「保存しようとするデータ」が 対象 「リクエスト内のデータ」が 対象 日時操作 Cake¥I18n¥Time (Chronos ベース) Carbon ※ Chronos へ移行する Proposal あり ログ Cake¥Log (独自) Monolog 単体テスト フレームワーク PHP Unit PHP Unit
  51. • Utility • 例) • Hash 配列操作をサポート • Text 文字列操作をサポート

    • Number 数値操作をサポート • Debug Kit 72 その他特徴 DebugKit は、CakePHP アプリケーションを簡単にデバッグするための ツールバーを提供する コアチームがサポートしているプラグインです。
  52. • Service Container • クラス依存性解決のための仕組み • 複数の解決方法が提供されており、 場面に合わせた方法を選ぶことができる • DI(依存性注入)がやりやすい

    →テストの書きやすいコードに 76 その他特徴 The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection. class UserController extends Controller { protected $users; public function __construct(UserRepository $users) { $this->users = $users; }
  53. • Facade • Service Container に格納されているインスタンスの メソッドを static メソッドのように利用可能 •

    デフォルトで Log, DB, Session などといった Facade を提供 • 自分で Facade 実装することもできる 77 その他特徴 Facades provide a "static" interface to classes that are available in the application's service container. Laravel ships with many facades which provide access to almost all of Laravel's features. ¥DB::transaction(function () { // トランザクション開始 }); ¥Log::debug('debug log'); ¥Log::info('info log'); ¥Log::error('error log');
  54. • Laravel を取り巻くサービス・プロダクトが豊富 • Homestead • Vagrant を利用した開発環境 • Laracasts

    • Laravel および PHP に関する チュートリアル動画を配信しているサイト • Laravel Mix • webpack の設定の wrapper (npm パッケージ) • デフォルトで Vue.js や SASS を利用可能 • など 79 その他特徴
  55. 1. 背景 2. Model 層の比較 3. View 層の比較 4. Controller

    層の比較 5. その他特徴 6. 全体考察・まとめ 80 目次
  56. 81 【考察】全体考察・まとめ CakePHP Laravel 特徴 「設定より規約」にもとづいて 少ないコードで機能を実現する 拡張のための機能を提供し コードを美しく保つ 長所

    • 規約に則れば絶対的なコード記述量が 少なくて済む • 「正しい書き方」を公式が 提示してくれている • 「特有の書き方」「暗黙の了解」 を強制される場面が少ない • ORM や View テンプレートの記述が 比較的シンプル • 拡張するための仕組みが 提供されている 短所 • 「正しい書き方」を把握していないと いびつな造りになるおそれがある • 自力で拡張するためには CakePHP の 実装レベルの理解が必要になる • クラスの階層構造などの設計を 自力でできないと道に迷ってしまう • 設定を明示的に書くことが多いため 絶対的な記述量は多くなりがち
  57. 82 【考察】全体考察・まとめ CakePHP Laravel 特徴 「設定より規約」にもとづいて 少ないコードで機能を実現する 拡張のための機能を提供し コードを美しく保つ 長所

    • 規約に則れば絶対的なコード記述量が 少なくて済む • 「正しい書き方」を公式が 提示してくれている • 「特有の書き方」「暗黙の了解」 を強制される場面が少ない • ORM や View テンプレートの記述が 比較的シンプル • 拡張するための仕組みが 提供されている 短所 • 「正しい書き方」を把握していないと いびつな造りになるおそれがある • 自力で拡張するためには CakePHP の 実装レベルの理解が必要になる • クラスの階層構造などの設計を 自力でできないと道に迷ってしまう • 設定を明示的に書くことが多いため 絶対的な記述量は多くなりがち 規約に則り、記述を減らすことで早く書きたい → CakePHP 自力で進み方を決め、柔軟に拡張していきたい → Laravel