2015年10月14日水曜日

【Symfony2.7ドキュメント読んだ?】ルーティング

ルートの定義

# app/config/config.yml
framework:
    # ...
    router: { resource: "%kernel.root_dir%/config/routing.yml" }

# app/config/routing.yml
app:
    resource: "@AppBundle/Controller/"
    type:     annotation

基本的なルート設定

// src/AppBundle/Controller/MainController.php
// ...
class MainController extends Controller
{
    /**
     * @Route("/")
     */
    public function homepageAction()
    {
        // ...
    }
}

プレースホルダーを使ったルーティング

// src/AppBundle/Controller/BlogController.php

/**
 * @Route("/blog/{page}", defaults={"page" = 1})
 */
public function indexAction($page)
{
    // ...
}
URL Route Parameters
/blog blog {page}=1
/blog/1 blog {page}=1
/blog/2 blog {page}=2

プレースホルダーの値の条件

// src/AppBundle/Controller/BlogController.php
// ...
/**
 * @Route("/blog/{page}", defaults={"page": 1}, requirements={
 *     "page": "\d+"
 * })
 */
public function indexAction($page)
{
    // ...
}

/**
  * @Route("/blog/{slug}")
  */
public function showAction($slug)
{
    // ...
}
URL Route Parameters
/blog/2 blog {page}=2
/blog/my-blog-post blog_show {slug}=my-blog-post
/blog/2-my-blog-post blog_show {slug}=2-my-blog-post

ルーティングは、先に条件にマッチしたメソッドを実行する

// src/AppBundle/Controller/MainController.php
// ...
class MainController extends Controller
{
    /**
     * @Route("/{_locale}", defaults={"_locale": "en"}, requirements={
     *     "_locale": "en|fr"
     * })
     */
    public function homepageAction($_locale)
    {
    }
}
Path Parameters
/ {_locale} = "en"
/en {_locale} = "en"
/fr {_locale} = "fr"
/es won't match this route

HTTPメソッドの指定

/ src/AppBundle/Controller/MainController.php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class MainController extends Controller
{
    /**
     * @Route("/news")
     * @Method("GET")
     */
    public function newsAction()
    {
        // ... display your news
}
    /**
     * @Route("/contact")
     * @Method({"GET", "POST"})
     */
    public function contactFormAction()
    {
        // ... display and process a contact form
    }
}

ホスト名でコントローラを振り分け

# ホスト名を指定
mobile_homepage:
    path:     /
    host:     m.example.com
    defaults: { _controller: AcmeDemoBundle:Main:mobileHomepage }

homepage:
    path:     /
    defaults: { _controller: AcmeDemoBundle:Main:homepage }

# プレースホルダーを用いる場合
projects_homepage:
    path:     /
    host:     "{project_name}.example.com"
    defaults: { _controller: AcmeDemoBundle:Main:mobileHomepage }

homepage:
    path:     /
    defaults: { _controller: AcmeDemoBundle:Main:homepage }

# プレースホルダーを用いる場合(サブドメインを指定する)
mobile_homepage:
    path:     /
    host:     "{subdomain}.example.com"
    defaults:
        _controller: AcmeDemoBundle:Main:mobileHomepage
        subdomain: m
    requirements:
        subdomain: m|mobile

homepage:
    path:     /
    defaults: { _controller: AcmeDemoBundle:Main:homepage }

# パラメータを用いる場合
mobile_homepage:
    path:     /
    host:     "m.{domain}"
    defaults:
        _controller: AcmeDemoBundle:Main:mobileHomepage
        domain: "%domain%"
    requirements:
        domain: "%domain%"

homepage:
    path:  /
    defaults: { _controller: AcmeDemoBundle:Main:homepage }

# ホスト名で読み込むルーティング定義ファイルを指定する
acme_hello:
    resource: "@AcmeHelloBundle/Resources/config/routing.yml"
    host:     "hello.example.com"

高度なルーティングの例

/ src/AppBundle/Controller/ArticleController.php
// ...
class ArticleController extends Controller
{
/**
* @Route(
*        "/articles/{_locale}/{year}/{title}.{_format}",
*        defaults={"_format": "html"},
*        requirements={
*            "_locale": "en|fr",
*            "_format": "html|rss",
*            "year": "\d+"
*        }
*)
*/
    public function showAction($_locale, $year, $title)
    {
    }
}

# マッチするURLの例
/articles/en/2010/my-post
/articles/en/2010/my-post.rss
/articles/en/2010/my-latest-post.html

コントローラのネーミングパターン

bundle:controller:action
Bundle Controller Class Method Name
AppBundle BlogController showAction

ルーティングのテスト

$crawler = $client->request(
    'GET',
    '/homepage',
    array(),
    array(),
    array('HTTP_HOST' => 'm.' . $client->getContainer()->getParameter('domain'))
);

ルートマッチングの条件指定

contact:
    path:     /contact
    defaults: { _controller: AcmeDemoBundle:Main:contact }
    condition: "context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'"

ルートの確認

# ルートの一覧
php app/console debug:router

#  詳細
php app/console debug:router homepage

# マッチするルートの確認
php app/console router:match /blog/my-latest-post

関連サイト


前の記事 | 次の記事

2015年10月13日火曜日

【Symfony2.7ドキュメント読んだ?】コントローラー

リクエスト、コントローラ、レスポンスのライフサイクル

リクエストは、フロントコントローラ(app.php, app_dev.php)からアプリケーションが実行され、 RouterがURIを元にマッチするルートのコントローラを実行する。 コントローラがレスポンスオブジェクトを返し、HTTPヘッダー情報とレスポンスオブジェクトの内容を クライアントへ返す。

開発用フロントコントローラのIP制限解除

app_dev.phpの次のようにコメントアウトする
ローカルで開発する場合は不要
/* IP制限解除
if (isset($_SERVER['HTTP_CLIENT_IP'])
    || isset($_SERVER['HTTP_X_FORWARDED_FOR'])
    || !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1')) || php_sapi_name() === 'cli-server')
) {
    header('HTTP/1.0 403 Forbidden');
    exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
}
*/

アノテーションによるURLとコントローラのマッピング

// src/AppBundle/Controller/HelloController.php
namespace AppBundle\Controller;

use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class HelloController
{
    /**
     * @Route("/hello/{name}", name="hello")
     */
    public function indexAction($name)
    {
        return new Response('Hello '.$name.'!');
    }
}

ベースコントローラの継承

よく使われそうなヘルパーメソッドが使えるようになる
namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class HelloController extends Controller
{
    // ...
}

複数の引数

引数の順番は関係がなく、対応した変数名があることが重要
public function indexAction($firstName, $lastName, $foo = 'bar')
{
    // ...
}

リダイレクト

return $this->redirectToRoute('homepage'); // 引数はルート
// redirectToRoute is equivalent to using redirect() and generateUrl() together:
// return $this->redirect($this->generateUrl('homepage'), 301);

# デフォルトは302リダイレクト
return $this->redirect('http://symfony.com/doc');

return $this->redirectToRoute('homepage', array(), 301);

# 元はレスポンスオブジェクト
return new RedirectResponse($this->generateUrl('homepage'));

テンプレートのレンダリング

// renders app/Resources/views/hello/index.html.twig
return $this->render('hello/index.html.twig', array('name' => $name));

// renders app/Resources/views/hello/greetings/index.html.twig
return $this->render('hello/greetings/index.html.twig', array(
    'name' => $name
));

他のサービスのアクセス

$templating = $this->get('templating');

$router = $this->get('router');

$mailer = $this->get('mailer');

サービスの確認コマンド

cd project_name
php app/console debug:container

エラーと404レスポンスの管理

// 404
throw $this->createNotFoundException('The product does not exist');

// 500
throw new \Exception('Something went wrong!');

フラッシュメッセージ

# コントローラ
use Symfony\Component\HttpFoundation\Request;

public function updateAction(Request $request)
{
    $form = $this->createForm(...);
    $form->handleRequest($request);
    if ($form->isValid()) {
        // do some sort of processing
        $this->addFlash(
            'notice',
            'Your changes were saved!'
        );
        // $this->addFlash is equivalent to $this->get('session')->getFlashBag()->add
        return $this->redirectToRoute(...);
    }
    return $this->render(...);
}

# テンプレート
{% for flashMessage in app.session.flashbag.get('notice') %}
    
{{ flashMessage }}
{% endfor %}

リクエストオブジェクト

リクエストオブジェクトを使ってパラメータの値など取得できる
ルーティングパラメータにマッチしない変数名がある場合に、RuntimeExceptionが発生する
use Symfony\Component\HttpFoundation\Request;

// create a simple Response with a 200 status code (the default)
$response = new Response('Hello '.$name, Response::HTTP_OK);

// create a JSON-response with a 200 status code
$response = new Response(json_encode(array('name' => $name)));
$response->headers->set('Content-Type', 'application/json');
use Symfony\Component\HttpFoundation\Response;

public function indexAction(Request $request)
{
    $request->isXmlHttpRequest(); // is it an Ajax request?

    $request->getPreferredLanguage(array('en', 'fr'));

    $request->query->get('page'); // get a $_GET parameter

    $request->request->get('page'); // get a $_POST parameter
}

他のコントローラへフォワードする

public function indexAction($name)
{
    $response = $this->forward('AppBundle:Something:fancy', array(
        'name'  => $name,
        'color' => 'green',
    ));
    // ... further modify the response or return it directly
    return $response;
}

# forward先のコントローラ
public function fancyAction($name, $color)
{
   // 
}

関連サイト


2015年10月9日金曜日

【Symfony2.7ドキュメント読んだ?】パーミッションの設定

パーミッションの設定

Webサーバの実行ユーザーとディレクトリのパーミッションが同じ場合

特に設定変更なし

ACLをサポートしている場合

rm -rf app/cache/*
rm -rf app/logs/*
HTTPDUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\  -f1`
sudo chmod +a "$HTTPDUSER allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs
sudo chmod +a "`whoami

ACLをサポートしている場合(chmod +aをサポートしていない場合)

# この記事ではこの方法で設定しました。
HTTPDUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\  -f1`
sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs
sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs

ACLが使えない場合

# 次のファイルを修正する
# app/console
# web/app.php
# web/app_dev.php

# コメントを外す
umask(0002); // This will let the permissions be 0775

# または
umask(0000); // This will let the permissions be 0777

関連サイト


2015年10月7日水曜日

【Symfony2.7ドキュメント読んだ?】ビルトインWebサーバの使い方

ビルトインWebサーバの起動、停止、確認コマンド

cd project_name
php app/console server:run

# Webサーバ起動後に次のURLにアクセスします。
# http://localhost:8000/

# IPアドレスおよびポート指定で起動
php app/console server:run 192.168.0.1:8080

# バックグラウンドで実行させたい場合
php app/console server:start
php app/console server:start 192.168.0.1:8080

# サーバの停止
php app/console server:stop
php app/console server:stop 192.168.0.1:8080

# サーバ状態の確認
php app/console server:status
php app/console server:status 192.168.0.1:8080

# 環境変数やルータースクリプトの指定
php app/console server:start --env=test --router=app/config/router_test.php

# ドキュメントルートを指定する
php app/console server:start --docroot=public_html

関連サイト


2015年10月6日火曜日

【Symfony2.7ドキュメント読んだ?】インストールと更新

Symfonyインストーラのインストール

Linux、MacOSの場合

sudo curl -LsS http://symfony.com/installer -o /usr/local/bin/symfony
sudo chmod a+x /usr/local/bin/symfony

Symfonyアプリケーションの作成

Linux、MacOSの場合

# [project_name]はプロジェクト名です。適宜変更してください。
# この記事ではこのコマンドを使用してインストールしました。
symfony new project_name

# インストールするSymfonyのバージョンを指定する場合
symfony new project_name 2.6
symfony new project_name 2.6.5

# LTSバージョンの場合 ※1
symfony new project_name lts

# composerを使ってSymfonyアプリケーションを作成する場合
composer create-project symfony/framework-standard-edition project_name

# バージョン指定の場合
composer create-project symfony/framework-standard-edition project_name "2.6.*"
※1 LTSは36ヶ月サポートするようです。 バージョン毎のサポート期間は、こちらで確認できます。

composerのインストール

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

1行の場合
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
SymfonyはWebサーバ機能があるのでインストール後すぐに動作確認できます。

Symfonyアプリケーションの更新

# 依存関係ライブラリのインストール
cd  project_name
composer install

# 更新
cd  project_name
composer update

関連サイト



【Symfony2.7ドキュメント読んだ?】 動作検証環境

Symfony2.7の公式ドキュメントを読んでメモを残します。

公式ドキュメント


この記事は、次の環境で動作確認します。

  • CentOS 6.7

  • PHP 5.6.14

  • nginx/1.8.0

  • Symfony 2.7






2015年1月7日水曜日

MySQL予約語のググらビリティーが低いので自分用リンク

更新日 2017-09-10

MySQL 予約語


Keywords and Reserved Words in MySQL 5.5

Keywords and Reserved Words in MySQL 5.6

Keywords and Reserved Words in MySQL 5.7

Keywords and Reserved Words in MySQL 8.0


以下リンク切れのため削除 (2017-09-10)
MySQL 5.7 予約語
http://dev.mysql.com/doc/refman/5.7/en/reserved-words.html

MySQL 5.6 予約語
http://dev.mysql.com/doc/refman/5.6/en/reserved-words.html

MySQL 5.5 予約語<
http://dev.mysql.com/doc/refman/5.5/en/reserved-words.html

MySQL 5.1 予約語
http://dev.mysql.com/doc/refman/5.1/en/reserved-words.html

MySQL 5.0 予約語
http://dev.mysql.com/doc/refman/5.0/en/reserved-words.html

MySQL 3.23/4.0/4.1 予約語
http://dev.mysql.com/doc/refman/4.1/en/reserved-words.html