Y-KANOH
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
PHPerのための「PHPフレームワーク」を語り合うPHP TechCafe ================================================== https://rakus.connpass.com/event/264108/ # PHPer's NEWS ::: info **[PHPクイズの解答と解説 (PHP Conference Japan 2022)](https://tech.pepabo.com/2022/10/05/php-conference-japan-2022-quiz/)** ::: ::: info **[【PHP8.3】JSONが正しいかどうか判定できるようになる](https://wiki.php.net/rfc/json_validate)** ::: ::: info **[PHP 8.1.12 Released! PHP 8.0.25 Released!](https://www.php.net/)** ::: ::: info **[Generics via Attributes in PHP — Can We Have Them?](https://pronskiy.com/blog/generics-via-attributes-in-php/)** ::: ::: info **[「OpenSSL」にセキュリティアップデート - 脆弱性の評価は下方修正](https://www.security-next.com/141071)** ::: ::: info **[GitHub、より細かな権限設定が可能な新しい個人用アクセストークンをパブリックベータ版として提供](https://codezine.jp/article/detail/16709)** ::: ::: info **[Laravel Workflow - 個々のマイクロサービスを利用して複雑なビジネス要求を達成するためのツール](https://dev.to/rmcdaniel/laravel-workflow-orchestration-vs-choregraphy-5aj8)** ::: ::: info **[「XKCP SHA-3」に脆弱性 - 「Python」「PHP」などにも影響](https://www.security-next.com/141201)** ::: ::: info **[PHPerKaigi 各種募集開始!!](https://fortee.jp/phperkaigi-2023/proposal/callfor)** ::: ::: info **[PHP8.2のリリースがちょっと延期](https://news-web.php.net/php.internals/118991/php.internals/)** バグが見つかったんなら仕方がないね ::: ::: info **[「gmail」ドメインを「gmai」と誤記、10カ月気付かず2000件超の情報漏えいか 埼玉大が「ドッペルゲンガー・ドメイン」の毒牙に](https://www.itmedia.co.jp/news/articles/2211/21/news144.html)** 送信側によるドメインチェックは必須 ::: ::: info **[PHP7.4サポート終了!!](https://www.php.net/supported-versions.php)** ::: ::: info **[PHPStan 1.9.0リリース](https://phpstan.org/blog/phpstan-1-9-0-with-phpdoc-asserts-list-type)** ::: ::: info **[AWSが「Docker Desktop」代替となり得る「Finch」をオープンソースで公開](https://www.itmedia.co.jp/news/articles/2211/24/news107.html)** ::: ::: info **[GitHub、テキストエディタ「Atom」の最終版を公開、12月にはリポジトリをアーカイブへ](https://codezine.jp/article/detail/16912)** ::: ::: info **[PHPフレームワーク「Symfony 6.2」リリース](https://thinkit.co.jp/news/bn/20376)** ::: ::: info **[The PHP Foundation: Impact and Transparency Report 2022](https://thephp.foundation/blog/2022/11/22/transparency-and-impact-report-2022/)** PHPの保守・開発は順調に進んでいるようでなによりです。 ::: # 特集:「PHPフレームワーク」を語り合う * Webアプリケーションフレームワーク とは([wiki](https://ja.wikipedia.org/wiki/Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF)) * 動的な ウェブサイト、Webアプリケーション、Webサービスの開発をサポートするために設計されたアプリケーションフレームワーク * Web開発で用いられる共通した作業に伴う労力を軽減する * データベースへのアクセス * テンプレートエンジン * セッション管理 * コードの再利用を促進させる * そもそもFWってなんで必要? * 開発速度向上 * Webアプリケーション開発でよく利用する処理(セッション管理やDBアクセス、Cookieなど)が既に用意されているため、それらを再利用するだけで開発が進められる * セキュリティ対応 * 脆弱性が見つかった場合に修正版がリリースされる * メンテされているOSSの場合 * 開発ルールの順守 * フレームワークのルールに従って作成することが強いられる反面、開発チーム全体で共通のルールで開発できるため、ルールに逸脱するようなコードが生まれにくい ## 比較するフレームワーク * Laravel * Symfony * CakePHP * Slim ## 設計思想 ### Laravel https://laravel.com/docs/9.x/installation - プログレッシブフレームワーク - we mean that Laravel grows with you. - Laravel はあなたと共に成長するということです。 - Laravel は依存性注入、単体テスト、キュー、リアルタイム イベント などのための堅牢なツールを提供します。 - スケーラブルなフレームワーク - Laravel は信じられないほどスケーラブルです。 - 実際、Laravel アプリケーションは、1 か月あたり数億のリクエストを処理するように簡単にスケーリングされています。 - コミュニティ フレームワーク ### Symfony > What could be more useful than an application developed by users for their own needs > https://symfony.com/at-a-glance#a-philosophy ユーザーが自分たちのニーズに合わせて開発したアプリケーションほど便利なものはない 作成されたコンポーネントを組み合わせて、フルスタックフレームワークを作成することもマイクロサービスを作成することも可能。 開発者の目的に応じて規模を変えることができることが特徴。 コンポーネントが標準化されており、アプリケーションが成熟しても使用したいコンポーネントを自由に導入することができる。 Java の [Spring Framework](https://spring.io/) や Ruby の [Ruby on Rails](https://rubyonrails.org/) の影響を受けているとのこと。 Symfony コンポーネントは [Drupal](https://www.drupal.org/), [Prestashop](https://www.prestashop.com/en), [Laravel](https://laravel.com/) で利用されている ### CakePHP - MVC ![公式の図](https://book.cakephp.org/4/ja/_images/typical-cake-request.png) ### Slim > Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs. > https://www.slimframework.com/ Slimはシンプルかつ強力な Web アプリケーションと API をすばやく作成するのに役立つ PHP マイクロ フレームワークです。 > At its core, Slim is a dispatcher that receives an HTTP request, invokes an appropriate callback routine, and returns an HTTP response. That’s it. > You don’t always need a kitchen-sink solution like Symfony or Laravel. These are great tools, for sure. But they are often overkill. Instead, Slim provides only a minimal set of tools that do what you need and nothing else. > https://www.slimframework.com/docs/v4/ 本質的に、Slim は HTTP リクエストを受け取り、適切なコールバック ルーチンを呼び出し、HTTP レスポンスを返すディスパッチャーです。それだけ。 SymfonyやLaravelのようなキッチン シンク ソリューションが常に必要なわけではありません。これらは確かに優れたツールです。しかし、それらはしばしばやり過ぎです。代わりに、Slim は、必要なことだけを行う最小限のツール セットのみを提供します。 ## ルーティング ### Laravel https://laravel.com/docs/9.x/routing #### デフォルトルートファイル デフォルトでは下記2つファイルにルーティングを定義する - routes/web.php - routes/api.php #### 定義方法 UserControllerにindxメソッドを定義している場合 下記のように定義すると`/user`のパスに対して、UserControllerのindexメソッドが対応される ```php= <?php use App\Http\Controllers\UserController; Route::get('/user', [UserController::class, 'index']); ``` #### 利用可能なルーターメソッド ```php= <?php Route::get($uri, $callback); Route::post($uri, $callback); Route::put($uri, $callback); Route::patch($uri, $callback); Route::delete($uri, $callback); Route::options($uri, $callback); ``` #### パラメータ ```php= <?php Route::get('/posts/{post}/comments/{comment}', [CommentController::class, 'show']); ``` ### Symfony #### routes.yaml に記載するパターン `routes.yaml` を以下の通り編集する ```yaml= app_lucky_number: path: /lucky/number controller: App\Controller\LuckyController::number ``` `/lucky/number` にアクセスすることで `LuckyController` の `number` メソッドにルーティングされる #### アノテーションまたはアトリビュートを利用するパターン(こっちが推奨) コントローラを以下の通り変更 ```php= <?php // src/Controller/LuckyController.php namespace App\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class LuckyController { #[Route('/lucky/number')] public function number(): Response { $number = random_int(0, 100); return new Response( '<html><body>Lucky number: '.$number.'</body></html>' ); } } ``` 上記の通り記述することで `routes.yaml` を作成しなくともルーティングされる ### CakePHP https://book.cakephp.org/3/ja/development/routing.html `routes.php`に記載 例:`/`にアクセスすると`ArticlesController`の`index()`メソッドを実行する ```php= use Cake\Routing\Router; // スコープ付きルートビルダーを使用。 Router::scope('/', function ($routes) { $routes->connect('/', ['controller' => 'Articles', 'action' => 'index']); }); // static メソッドを使用。 Router::connect('/', ['controller' => 'Articles', 'action' => 'index']); ``` `/articles/15`にアクセスすると`ArticlesController`の`view(15)`メソッドを実行する ```php= $routes->connect( '/articles/:id', ['controller' => 'Articles', 'action' => 'view'] ) ->setPatterns(['id' => '\d+']) ->setPass(['id']); ``` HTTPメソッドによって分けたいときは以下の記述 ```php= // GET リクエストへのみ応答するルートの作成 $routes->get( '/cooks/:id', ['controller' => 'Users', 'action' => 'view'], 'users:view' ); // PUT リクエストへのみ応答するルートの作成 $routes->put( '/cooks/:id', ['controller' => 'Users', 'action' => 'update'], 'users:update' ); ``` ### Slim https://www.slimframework.com/docs/v4/objects/routing.html ```php= $app->get('/books/{id}', function ($request, $response, array $args) { // Show book identified by $args['id'] }); ``` ## セッション管理 ### Laravel https://laravel.com/docs/9.x/session #### 設定ファイル config/session.php #### セッションの操作方法 グローバルセッションヘルパーとRequestインスタンス経由の2つの方法 ##### グローバルセッションヘルパー ```php= <?php $value = session('key'); ``` ##### Requestインスタンス経由 ```php= <?php public function show(Request $request, $id) { $value = $request->session()->get('key'); // } ``` ### Symfony 以下の2通り * RequestStack から取得 * SessionInterface から取得 #### [RequestStack](https://symfony.com/doc/current/session.html) から取得するパターン * `HttpFoundation component` を追加することで利用可能 ```bash= composer require symfony/http-foundation ``` * セッションの設定は `config/packages/framework.yaml` に記載 * 公式にはXMLとPHPの説明もあるが、デフォルトは `yaml` ? * `handler_id` * null * 稼働しているPHPの設定に依存 * session.handler.native_file * `save_path` に記載したパスにSymfonyのセッションメタデータを保存 * [その他詳細](https://symfony.com/doc/current/reference/configuration/framework.html#session) ##### 基本的な使い方 ```php= use Symfony\Component\HttpFoundation\RequestStack; class SomeService { private $requestStack; public function __construct(RequestStack $requestStack) { $this->requestStack = $requestStack; // Accessing the session in the constructor is *NOT* recommended, since // it might not be accessible yet or lead to unwanted side-effects // $this->session = $requestStack->getSession(); } public function someMethod() { $session = $this->requestStack->getSession(); // stores an attribute in the session for later reuse $session->set('attribute-name', 'attribute-value'); // gets an attribute by name $foo = $session->get('foo'); // the second argument is the value returned when the attribute doesn't exist $filters = $session->get('filters', []); // ... } } ``` * 公式にはコンストラクタ内でセッションを利用することはおすすめしていない。 * Symfony 6.0 より、旧方式のセッションは[廃止](https://symfony.com/blog/new-in-symfony-5-3-session-service-deprecation)された模様 ##### [SessionInterface](https://symfony.com/doc/current/controller.html#managing-the-session) から取得するパターン `SessionInterface` でタイプヒントしてコントローラ引数に渡すだけ。 ##### 基本的な使い方 ```php= use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\SessionInterface; // ... public function index(SessionInterface $session): Response { // stores an attribute for reuse during a later user request $session->set('foo', 'bar'); // gets the attribute set by another controller in another request $foobar = $session->get('foobar'); // uses a default value if the attribute doesn't exist $filters = $session->get('filters', []); // ... } ``` ### CakePHP - PHP のネイティブ session 拡張上に、ユーティリティ機能のスイートとラッパーを提供 - https://book.cakephp.org/4/ja/development/sessions.html #### 設定 ##### データベースセッション ```php 'Session' => [ 'defaults' => 'database', 'handler' => [ 'engine' => 'DatabaseSession', 'model' => 'CustomSessions' ] ] ``` - 1行目:cakePHPにセッションはデータベースに保持することを伝える - セッション保持するためのカスタムモデルを定義することもできる(`model => 'CustomSessions'`) ##### キャッシュセッション ```php Configure::write('Session', [ 'defaults' => 'cache', 'handler' => [ 'config' => 'session' ] ]); ``` - これは Session に `CacheSession` クラスをセッション保存先として 委任する ##### セッションを利用する -  セッションはリクエストオブジェクトを呼び出せる場所ならどこでも呼び出せる -  Controllers -  Views -  Helpers -  Cells -  Components ```php $name = $this->getRequest()->getSession()->read('User.name'); // 複数回セッションにアクセスする場合、 // ローカル変数にしたくなるでしょう。 $session = $this->getRequest()->getSession(); $name = $session->read('User.name'); ``` - Session::read($key) - Session::write($key) - Session::check($key) - Session::destroy() - ユーザーがログインやログアウトした時、 `AuthComponent` は自動的にセッション ID を更新 ### Slim 実装なし ## リクエスト管理 ### Laravel https://laravel.com/docs/9.x/requests #### リクエストの内容を取得する Illuminate\Http\Requestクラスのインスタンスを生成して取得する ```php= <?php $name = $request->input('name'); $name = $request->query('name'); ``` ### Symfony https://symfony.com/doc/current/components/http_kernel.html ```php= use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; public function index(Request $request): Response { $request->isXmlHttpRequest(); // is it an Ajax request? $request->getPreferredLanguage(['en', 'fr']); // retrieves GET and POST variables respectively $request->query->get('page'); $request->request->get('page'); // retrieves SERVER variables $request->server->get('HTTP_HOST'); // retrieves an instance of UploadedFile identified by foo $request->files->get('foo'); // retrieves a COOKIE value $request->cookies->get('PHPSESSID'); // retrieves an HTTP request header, with normalized, lowercase keys $request->headers->get('host'); $request->headers->get('content-type'); } ``` ### CakePHP $this->request を使用して取得 ```php= $controllerName = $this->request->getParam('controller'); // URL は /posts/index?page=1&sort=title の場合に page を取得するとき $page = $this->request->getQuery('page'); // POSTデータにアクセスするとき $title = $this->request->getData('MyModel.title'); ``` ### Slim https://www.slimframework.com/docs/v4/objects/request.html ```php= <?php use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); $app->get('/hello', function (Request $request, Response $response) { $response->getBody()->write('Hello World'); return $response; }); $app->run(); ``` ## エラーハンドリング ### Laravel https://readouble.com/laravel/9.x/ja/errors.html * `App\Exceptions\Handler`クラスによって、アプリケーションが投げるすべての例外がログに記録され、ユーザーへレンダーされる #### エラーハンドリングのカスタマイズ * `Handler`クラスは、カスタム例外レポートとレンダリングコールバックを登録できる`register`メソッドを持っている。 * `reportable`メソッドで、例外をさまざまな方法で報告できる。(エラー監視ツールに登録するなど。デフォルトではログに記録される。) * `renderable`メソッドで、特定の例外に対して、個別にレンダリング方法を指定することができる。(デフォルトでは例外はHTTPレスポンスに変換される) * HTTPエラーが返された場合、`resources/views/errors`下のHTTPステータスコード名のbladeファイルがレンダリングされる(`404.blade.php`など) ```php= use App\Exceptions\InvalidOrderException; /** * アプリケーションの例外処理コールバックを登録 * * @return void */ public function register() { $this->reportable(function (InvalidOrderException $e) { // 例外を報告 }); $this->renderable(function (InvalidOrderException $e, $request) { return response()->view('errors.invalid-order', [], 500); }); } ``` ### Symfony Symfony アプリケーションでは、エラーが 404 Not Found エラーであろうと、 コードで何らかの例外をスローすることによってトリガーされた致命的なエラーであろうと、 すべてのエラーを例外として扱う。 組み込みの Twig エラーレンダラーを使用して、デフォルトのエラーテンプレートをオーバーライド可能。 ```bash composer require symfony/twig-pack ``` これらのテンプレートをオーバーライドするには、標準の Symfony メソッドを使用し て、バンドル内にあるテンプレートをオーバーライドし、それらをtemplates/bundles/TwigBundle/Exception/ディレクトリに配置する。 HTML ページを返す典型的なプロジェクトは次のようになります。 ``` Copy templates/ └─ bundles/ └─ TwigBundle/ └─ Exception/ ├─ error404.html.twig ├─ error403.html.twig └─ error.html.twig # All other HTML errors (including 500) ``` HTML ページの 404 エラー テンプレートをオーバーライドするには、次の場所にある新しい error404.html.twigテンプレートを作成しtemplates/bundles/TwigBundle/Exception/ます。 ```htmlembedded {# templates/bundles/TwigBundle/Exception/error404.html.twig #} {% extends 'base.html.twig' %} {% block body %} <h1>Page not found</h1> <p> The requested page couldn't be located. Checkout for any URL misspelling or <a href="{{ path('homepage') }}">return to the homepage</a>. </p> {% endblock %} ``` [error_controller](https://github.com/symfony/symfony/blob/6.1/src/Symfony/Component/HttpKernel/Controller/ErrorController.php) [参考](https://symfony.com/doc/current/controller/error_pages.html) ### CakePHP https://book.cakephp.org/3/ja/development/errors.html ErrorController にてエラーページを描画 ```php= namespace App\Controller\Admin; use App\Controller\AppController; use Cake\Event\EventInterface; class ErrorController extends AppController { /** * Initialization hook method. * * @return void */ public function initialize(): void { $this->loadComponent('RequestHandler'); } /** * beforeRender callback. * * @param \Cake\Event\EventInterface $event Event. * @return void */ public function beforeRender(EventInterface $event) { $this->viewBuilder()->setTemplatePath('Error'); } } ``` ### Slim https://www.slimframework.com/docs/v4/middleware/error-handling.html ```php= use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); /** * The routing middleware should be added earlier than the ErrorMiddleware * Otherwise exceptions thrown from it will not be handled by the middleware */ $app->addRoutingMiddleware(); /** * Add Error Middleware * * @param bool $displayErrorDetails -> Should be set to false in production * @param bool $logErrors -> Parameter is passed to the default ErrorHandler * @param bool $logErrorDetails -> Display error details in error log * @param LoggerInterface|null $logger -> Optional PSR-3 Logger * * Note: This middleware should be added last. It will not handle any exceptions/errors * for middleware added after it. */ $errorMiddleware = $app->addErrorMiddleware(true, true, true); // ... $app->run(); ``` * slimが用意したエラー画面を出すかどうかを選択できたり、カスタムエラー画面を表示するなど柔軟な設定が可能。 ## DBサポート ### Laravel https://readouble.com/laravel/9.x/ja/database.html #### コネクション Lavavelでは以下のDBがサポートされる * MariaDB * MySQL * PostgreSQL * SQLite * SQL Server config/database.phpで設定を行う データベースにアクセスする方法は以下 * DBファサード ``` $users = DB::select('select * from users where active = ?', [1]); ``` * クエリビルダ ``` $users = DB::table('users')->where('active', $isActive)->get(); ``` * Eloquent ``` $users = User::where('active', $isActive)->get(); ``` ### Symfony https://symfony.com/doc/current/doctrine.html コネクション * Doctrine(ORM)を使用 ``` composer require doctrine maker ``` インストールが完了すると .env ファイルにデータベースへの接続設定に関する項目が書き足されます。 DATABASE_URL の箇所を接続するデータベースに合わせて書き換えて下さい。 ``` DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name ``` ``` php bin/console doctrine:database:create ``` エンティティクラスを作成する ``` symfony console make:entity hoge ``` ### CakePHP SELECT文の実行 ```php= use Cake\Datasource\ConnectionManager; $connection = ConnectionManager::get('default'); $results = $connection->execute('SELECT * FROM articles')->fetchAll('assoc'); ``` INSERT文の実行 ```php= use Cake\Datasource\ConnectionManager; use DateTime; $connection = ConnectionManager::get('default'); $connection->insert('articles', [ 'title' => 'A New Article', 'created' => new DateTime('now') ], ['created' => 'datetime']); ``` UPDATE文の実行 ```php= use Cake\Datasource\ConnectionManager; $connection = ConnectionManager::get('default'); $connection->update('articles', ['title' => 'New title'], ['id' => 10]); ``` DELETE文の実行 ```php= use Cake\Datasource\ConnectionManager; $connection = ConnectionManager::get('default'); $connection->delete('articles', ['id' => 10]); ``` ### Slim なし ## バリデーション ### Laravel https://readouble.com/laravel/9.x/ja/validation.html 複数のバリデーション方法がある 例を2つ紹介 #### Requestクラスを使う方法 連想配列形式で各パラメータに適応したいバリデーションルールを指定する [他のバリデーションルール](https://readouble.com/laravel/9.x/ja/validation.html?header=unique:_%25E3%2583%2586%25E3%2583%25BC%25E3%2583%2596%25E3%2583%25AB_,_%25E3%2582%25AB%25E3%2583%25A9%25E3%2583%25A0_#rule-accepted) ```php= <?php public function rules() { return [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]; } ``` #### Validatorファサードを使用する方法 ファサードを使ってバリデーションをすることも可能 第一引数に対象のデータ、第二引数にバリデーションルールを指定する ```php= <?php $validator = Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]); ``` ### Symfony config/validator/ ディレクトリ内の .yaml または .xml ファイルとして定義する。 (例)$nameプロパティが空 ```php= Attributes // src/Entity/Author.php namespace App\Entity; // ... use Symfony\Component\Validator\Constraints as Assert; class Author { #[Assert\NotBlank] private $name; } ``` YAML ```yml= # config/validator/validation.yaml App\Entity\Author: properties: name: - NotBlank: ~ ``` XML ```xml= <!-- config/validator/validation.xml --> <?xml version="1.0" encoding="UTF-8" ?> <constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd"> <class name="App\Entity\Author"> <property name="name"> <constraint name="NotBlank"/> </property> </class> </constraint-mapping> ``` ```php= PHP // src/Entity/Author.php namespace App\Entity; // ... use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Mapping\ClassMetadata; class Author { private $name; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('name', new NotBlank()); } } ``` ### CakePHP https://book.cakephp.org/4/en/core-libraries/validation.html#namespace-Cake\Validation ```php= $validator ->requirePresence('title') ->notEmptyString('title', 'このフィールドに入力してください') ->add('title', [ 'length' => [ 'rule' => ['minLength', 10], 'message' => 'タイトルは10文字以上必要です。', ] ]) ->allowEmptyDateTime('published') ->add('published', 'boolean', [ 'rule' => 'boolean' ]) ->requirePresence('body') ->add('body', 'length', [ 'rule' => ['minLength', 50], 'message' => '記事の内容は意味がなければなりません。' ]); ``` ### Slim ドキュメントに記述なし ## マイグレーション ### Laravel https://readouble.com/laravel/9.x/ja/migrations.html * マイグレージョン関連のコマンドがartisanコマンドで準備されている * マイグレーションの生成 ``` php artisan make:migration create_flights_table ``` * マイグレーションの構造 ```php= <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateFlightsTable extends Migration { /** * マイグレーションの実行 * * @return void */ public function up() { Schema::create('flights', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('airline'); $table->timestamps(); }); } /** * マイグレーションを戻す * * @return void */ public function down() { Schema::drop('flights'); } } ``` ### Symfony Doctrine Migrationsを使用。 ``` symfony console make:migration ``` 生成されたファイル名が出力される(migrations/Version20191019083640.php のような名前のファイル): ```php= namespace DoctrineMigrations; use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration; final class Version00000000000000 extends AbstractMigration { public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->addSql('CREATE SEQUENCE comment_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); $this->addSql('CREATE SEQUENCE conference_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); $this->addSql('CREATE TABLE comment (id INT NOT NULL, conference_id INT NOT NULL, author VARCHAR(255) NOT NULL, text TEXT NOT NULL, email VARCHAR(255) NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, photo_filename VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE INDEX IDX_9474526C604B8382 ON comment (conference_id)'); $this->addSql('CREATE TABLE conference (id INT NOT NULL, city VARCHAR(255) NOT NULL, year VARCHAR(4) NOT NULL, is_international BOOLEAN NOT NULL, PRIMARY KEY(id))'); $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526C604B8382 FOREIGN KEY (conference_id) REFERENCES conference (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); } public function down(Schema $schema): void { // ... } } ``` ### CakePHP https://book.cakephp.org/migrations/3/ja/index.html * Cake PHP 本体には含まれていない * Cake PHP コアメンバが開発するプラグインとして利用可能 ``` composer require cakephp/migrations "@stable" ``` ```PHP= <?php use Migrations\AbstractMigration; class CreateProducts extends AbstractMigration { /** * Change Method. * * More information on this method is available here: * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method * @return void */ public function change() { $table = $this->table('products'); $table->addColumn('name', 'string', [ 'default' => null, 'limit' => 255, 'null' => false, ]); $table->addColumn('description', 'text', [ 'default' => null, 'null' => false, ]); $table->addColumn('created', 'datetime', [ 'default' => null, 'null' => false, ]); $table->addColumn('modified', 'datetime', [ 'default' => null, 'null' => false, ]); $table->create(); } } ``` * 主キーとなるカラム id は、 勝手に追加される ### Slim なし

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully