php5フレームワークsymfonyを勉強しました。その4

前回の続き。8章を勉強しました。

デルレイヤーの内側

symfonyのデータベーススキーマ

サンプルのschema.yml

propel:
  blog_article:
    _attributes: { phpName: Article }
    id:
    title:       varchar(255)
    content:     longvarchar
    created_at:
  blog_comment:
    _attributes: { phpName: Comment }
    id:
    article_id:
    author:      varchar(255)
    content:     longvarchar
    created_at:

モデルクラスをビルド

symfony propel-build-model

レコードカラムのためのゲッターはオブジェクトクラスで利用できる

$article = new Article();
...
$title = $article->getTitle();

レコードを読み取る静的メソッドはpeerクラスの中で利用できる

$articles = ArticlePeer::retrieveByPks(array(123, 124, 125));
// $articlesはArticleクラスのオブジェクトの配列

生成されたオブジェクトクラスのメソッド

$article = new Article();
$article->setTitle('初めての記事');
$article->setContent('これは初めての記事です。\n 皆様が楽しんで下さることを祈っています!');
 
$title   = $article->getTitle();
$content = $article->getContent();

fromArray()メソッドは複数のセッター

$article->fromArray(array(
  'title'   => '初めての記事',
  'content' => 'これは初めての記事です。\n 皆様が楽しんで下さることを祈っています!',
));

関連するレコードを読み取る

$comment->getArticle(): 関連するArticleオブジェクトを取得するため
$comment->getArticleId(): 関連するArticleオブジェクトのIDを取得するため
$comment->setArticle($article): 関連するArticleオブジェクトを定義するため
$comment->setArticleId($id): IDから関連するArticleオブジェクトを定義するため
$article->getComments(): 関連するCommentオブジェクトを取得するため

外部キーは特別なセッターに翻訳される

$comment = new Comment();
$comment->setAuthor('Steve');
$comment->setContent('うわ〜、すごい、感動的だ: 最高の記事だよ!');
 
// このコメントを以前の$articleオブジェクトに加える
$comment->setArticle($article);
 
// 代替構文は
// オブジェクトが既にデータベースに保存されている場合のみ意味をなす
$comment->setArticleId($article->getId());

外部キーは特別なゲッターに翻訳される

// 多対一のリレーション
echo $comment->getArticle()->getTitle();
 => 初めての記事
echo $comment->getArticle()->getContent();
 => これは初めての記事です。
    皆様が楽しんで下さることを祈っています!
 
// 一対多のリレーション
$comments = $article->getComments();

データの保存

$article->save();

関連したオブジェクト上のdelete()メソッドでデータベースからレコードを削除する

foreach ($article->getComments() as $comment)
{
  $comment->delete();
}

主キーでレコードを取り出す

$article = ArticlePeer::retrieveByPk(7);

Criteriaでレコードを読み取る

$c = new Criteria();
$articles = ArticlePeer::doSelect($c);
 
// 上記のコードは下記のSQLクエリーになります
SELECT blog_article.ID, blog_article.TITLE, blog_article.CONTENT,
       blog_article.CREATED_AT
FROM   blog_article;

doSelect()を持つCriteriaによってレコードを読み取る -- Criteriaは条件付き

$c = new Criteria();
$c->add(CommentPeer::AUTHOR, 'Steve');
$c->addAscendingOrderByColumn(CommentPeer::CREATED_AT);
$comments = CommentPeer::doSelect($c);
 
// 上記のコードは下記のようなSQLクエリーになる
SELECT blog_comment.ARTICLE_ID, blog_comment.AUTHOR, blog_comment.CONTENT,
       blog_comment.CREATED_AT
FROM   blog_comment
WHERE  blog_comment.author = 'Steve'
ORDER BY blog_comment.CREATED_AT ASC;

doSelect()を持つCriteriaによってレコードを読み取る別の例-- Criteriaは条件付き

$c = new Criteria();
$c->add(CommentPeer::AUTHOR, 'Steve');
$c->addJoin(CommentPeer::ARTICLE_ID, ArticlePeer::ID);
$c->add(ArticlePeer::CONTENT, '%enjoy%', Criteria::LIKE);
$c->addAscendingOrderByColumn(CommentPeer::CREATED_AT);
$comments = CommentPeer::doSelect($c);
 
// 上記のコードは次のようなSQLクエリーになる
SELECT blog_comment.ID, blog_comment.ARTICLE_ID, blog_comment.AUTHOR,
       blog_comment.CONTENT, blog_comment.CREATED_AT
FROM   blog_comment, blog_article
WHERE  blog_comment.AUTHOR = 'Steve'
       AND blog_article.CONTENT LIKE '%enjoy%'
       AND blog_comment.ARTICLE_ID = blog_article.ID
ORDER BY blog_comment.CREATED_AT ASC

生のSQLクエリーを使う

CreoleでカスタムのSQLクエリー

$connection = Propel::getConnection();
$query = 'SELECT MAX(%s) AS max FROM %s';
$query = sprintf($query, ArticlePeer::CREATED_AT, ArticlePeer::TABLE_NAME);
$statement = $connection->prepareStatement($query);
$resultset = $statement->executeQuery();
$resultset->next();
$max = $resultset->getInt('max');

特別な日付カラムを使う

created_atとupdated_atカラムは自動的に処理される

$comment = new Comment();
$comment->setAuthor('Steve');
$comment->save();
 
// 作成時点の日付を表示する
echo $comment->getCreatedAt();
  => [date of the database INSERT operation]

加えて、日付カラムのためのゲッターは日付フォーマットを引数として受け取ります:

echo $comment->getCreatedAt('Y-m-d');

データベースの接続

myproject/config/databases.ymlの中の、サンプルのデータベースの接続設定

prod:
  propel:
    param:
      hostspec:           mydataserver
      username:           myusername
      password:           xxxxxxxxxx
 
all:
  propel:
    class:                sfPropelDatabase
    param:
      phptype:            mysql     # デフォルトのベンダー
      hostspec:           localhost
      database:           blog
      username:           login
      password:           passwd
      port:               80
      encoding:           utf8      # テーブルに対するデフォルトの文字セット
      persistent:         true      # 永続的接続を使う

省略記法によるデータベースの接続設定

all:
  propel:
    class:          sfPropelDatabase
    param:
      dsn:          mysql://login:passwd@localhost/blog

SQliteのためのデータベースの接続設定はファイルパスをホストとして使う

all:
  propel:
    class:          sfPropelDatabase
      param:
        phptype:  sqlite
        database: %SF_DATA_DIR%/blog.db

モデルを拡張する

lib/model/Article.phpの中で、モデルをカスタマイズする

class Article extends BaseArticle
{
  public function __toString()
  {
    return $this->getTitle();  // getTitle()はBaseArticleから継承される
  }
}

lib/model/ArticlePeer.phpの中で、モデルをカスタマイズする

class ArticlePeer extends BaseArticlePeer
{
  public static function getAllOrderedByDate()
  {
    $c = new Criteria();
    $c->addAscendingOrderByColumn(self::CREATED_AT);
    return self::doSelect($c);
 
  }
}

基本的なカラム属性

propel:
  blog_article:
    id:                 # symfonyに仕事を任せる
    title: varchar(50)  # あなた自身が型を指定する

複雑なカラム属性

propel:
  blog_article:
    id:       { type: integer, required: true, primaryKey: true, autoIncrement: true }
    name:     { type: varchar(50), default: foobar, index: true }
    group_id: { type: integer, foreignTable: db_group, foreignReference: id, onDelete: cascade }

カラムのパラメータ

type: カラムの型。選択肢はboolean、tinyint、smallint、integer、bigint、double、float、real、decimal、char、varchar(size)、longbarchar、date、time、timestamp、bu_date、bu_timestamp、blob、とclobです。
required: 論理値。カラムをrequiredにしたい場合これをtrueに設定します。
default: デフォルトの値。
primaryKey: 論理値。主キーに対してこれをtrueに設定します。
autoIncrement: 論理値。オートインクリメントされた値を取る必要のあるinteger型のカラムに対してこれをtrueに設定します。
sequence: autoIncrementカラムに対してシーケンスを使うデータベース(例えばPostgreSQLOracle)のためのシーケンス名。
index: 論理値。シンプルなインデックスが欲しい場合はtrueに、カラムにユニークなインデックスを作りたい場合はuniqueに設定します。
foreignTable: 別のテーブルに外部キーを作るために使われる、テーブル名。
foreignReference: foreingTable経由で外部キーが定義された場合の関連カラムの名前。
onDelete: 関連テーブルに存在するレコードが削除されたときにアクションを起動させるために指定します。setnullに設定したとき、外部キーのカラムはnullに設定されます。cascadeに設定したとき、レコードは削除されます。データベースエンジンがsetのビヘイビアをサポートしない場合、ORMがエミュレートします。これはforeignTableとforeingReferenceを持つカラムだけに該当します。
isCulture: 論理値。ローカライズされた内容テーブルにあるcultureのカラムに対してこれをtrueに設定して下さい。

外部キーの代替構文

propel:
  blog_article:
    id:
    title:   varchar(50)
    user_id: { type: integer }
    _foreignKeys:
      -
        foreignTable: blog_user
        onDelete:     cascade
        references:
          - { local: user_id, foreign: id }

インデックスとユニークインデックスの代替構文

propel:
  blog_article:
    id:
    title:            varchar(50)
    created_at:
    _indexes:
      my_index:       [title(10), user_id]
    _uniques:
      my_other_index: [created_at]

カラムの名前から推定されたカラムの詳細内容

// idという名前で空のカラムは主キーと見なされる
id:         { type: integer, required: true, primaryKey: true, autoIncrement: true }

// XXX_idという名前で空のカラムは外部キーと見なされる
foobar_id:  { type: integer, foreignTable: db_foobar, foreignReference: id }

// created_at、updated at、created_onとupdated_onという名前を持つ空のカラムは
// 日付と見なされ自動的にtimestamp型を取る
created_at: { type: timestamp }
updated_at: { type: timestamp }

暗黙的な国際化のメカニズム

propel:
  db_group:
    id:
    created_at:
 
  db_group_i18n:
    name:        varchar(50)

明示的な国際化のメカニズム

propel:
  db_group:
    _attributes: { isI18N: true, i18nTable: db_group_i18n }
    id:
    created_at:
 
  db_group_i18n:
    id:       { type: integer, required: true, primaryKey: true,foreignTable: db_group, foreignReference: id, onDelete: cascade }
    culture:  { isCulture: true, type: varchar(7), required: true,primaryKey: true }
    name:     varchar(50)

既存のスキーマに基づいてSQLのデータベース構造をビルドする

symfony propel-build-sql

テーブルを直接ビルドするためにschema.ymlファイルを利用

mysqladmin -u root -p create blog
mysql -u root -p blog < data/sql/lib.model.schema.sql

既存のデータベースからYAMLのデータモデルを生成する

symfony propel-build-schema

[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/