Symfonyに挑戦09「Jobeet 2日目〜3日目」

Jobeet2日目。

ここではどんなプログラムを作るのかを決めているだけのようだ。手書きの画面がかわいい。

Jobeetを使う人

今から作るサイトをどんな人が使うのかを想定。

Jobeetのユーザーストーリー

サイトを使う人がどんな機能を求めているのか想定。

フロントエンド(frontend)の機能
  • ホームページ上でユーザーは最新の有効な状態の仕事を見れます
  • ユーザーはカテゴリーに属する全ての仕事を見ることができます
  • ユーザーはキーワードで仕事のリストを絞り込めます
  • ユーザーは仕事をクリックすることで詳細な情報を見ることができます
  • ユーザーは仕事を掲載できます
  • ユーザーがアフィリエイトの申し込みをする
  • アフィリエイトをする人は現在の有効な仕事のリストを取得できます
バックエンド(backend)の機能
  • 管理者はWebサイトを設定します
  • 管理者は仕事を管理します
  • 管理者はアフィリエイトユーザーを管理します


どうやら求人募集の掲示板サイトのようだ。



Jobeet3日目。

データモデル。ここではJobeet用のデータベースを作る。
Symfonyではconfig/schema.ymlというファイルにデータベースのテーブル名やカラムなどの情報を記入して、コマンドラインからSymfonyコマンドを実行してやると、自動でデータベースやらデータベース接続用のプログラムやらを作ってくれるらしい。

早速やってみる。訳のわからないところは読み飛ばしながらやってみる。


★/jobeet/config/schema.ymlファイルにをテキストエディタで開き、下記コピペ。

# config/schema.yml
propel:
  jobeet_category:
    id:           ~
    name:         { type: varchar(255), required: true, index: unique }
 
  jobeet_job:
    id:           ~
    category_id:  { type: integer, foreignTable: jobeet_category, foreignReference: id, required: true }
    type:         { type: varchar(255) }
    company:      { type: varchar(255), required: true }
    logo:         { type: varchar(255) }
    url:          { type: varchar(255) }
    position:     { type: varchar(255), required: true }
    location:     { type: varchar(255), required: true }
    description:  { type: longvarchar, required: true }
    how_to_apply: { type: longvarchar, required: true }
    token:        { type: varchar(255), required: true, index: unique }
    is_public:    { type: boolean, required: true, default: 1 }
    is_activated: { type: boolean, required: true, default: 0 }
    email:        { type: varchar(255), required: true }
    expires_at:   { type: timestamp, required: true }
    created_at:   ~
    updated_at:   ~
 
  jobeet_affiliate:
    id:           ~
    url:          { type: varchar(255), required: true }
    email:        { type: varchar(255), required: true, index: unique }
    token:        { type: varchar(255), required: true }
    is_active:    { type: boolean, required: true, default: 0 }
    created_at:   ~
 
  jobeet_category_affiliate:
    category_id:  { type: integer, foreignTable: jobeet_category, foreignReference: id, required: true, primaryKey: true, onDelete: cascade }
    affiliate_id: { type: integer, foreignTable: jobeet_affiliate, foreignReference: id, required: true, primaryKey: true, onDelete: cascade }


★ターミナルでmysqladminコマンドを使えるようにして、jobeetと言う名前のデータベース作成。

Mac:~ kaneda$ sudo ln -s /Applications/xampp/xamppfiles/bin/mysqladmin /usr/local/bin/mysqladmin
Mac:~ kaneda$ mysqladmin -uroot -p create jobeet
Enter password: (MySQLのパスワード)
Mac:~ kaneda$ 

http://localhost/phpmyadminで作ってもいい。


★次に/jobeet/config/schema.ymlで書いた設定をjobeetデータベースにつっこむ。

Mac:~ kaneda$ cd ~/Sites/jobeet
Mac:jobeet kaneda$ php symfony configure:database "mysql:host=localhost;dbname=jobeet" root (MySQLのパスワード)
Mac:jobeet kaneda$ php symfony propel:build-sql
Mac:jobeet kaneda$ php symfony propel:insert-sql
Execution of target "insert-sql" failed for the following reason: /Applications/xampp/xamppfiles/lib/php/pear/symfony/plugins/sfPropelPlugin/lib/vendor/propel-generator/build-propel.xml:275:1:  [wrapped: could not find driver]
    [phing] /Applications/xampp/xamppfiles/lib/php/pear/symfony/plugins/sfPropelPlugin/lib/vendor/propel-generator/build-propel.xml:275:1:  [wrapped: could not find driver]
                                                                                                    
  Some problems occurred when executing the task:                                                   
    build-propel.xml:275:1:  [wrapped: could not find driver]                                       
    If the exception message is not clear enough, read the output of the task for more information 

ひどい色のエラーがでた。このエラーでかなり悩んだけど、下のようにphpの場所を指定してあげるとサクッといけた。

Mac:jobeet kaneda$ /Applications/xampp/xamppfiles/bin/php symfony propel:insert-sql

ショートカットの作り方が悪かったのか、どうやらpdo_mysqlというモジュールがphpプログラムから読み込めないことが原因らしい。でも出来たのでこれでよし。


★次はデータベースとやりとりするためのPHPファイルを生成するためのコマンド。

Mac:jobeet kaneda$ php symfony propel:build-model

/jobeet/lib/model/フォルダにいろいろファイルが出来た。


★とりあえずここまでの流れがプログラムでデータベースを使う場合の初期プロセスらしい。

  1. schema.ymlファイルにどんなデータベースにするのかを書いて
  2. データベースを作り、
  3. propel:build-sqlでデータベース用のsqlファイルを作り、
  4. insert-sqlでデータベースにschema.ymlで書いたのテーブルを作り、
  5. build-modelでデータベースとやりとりするためのPHPファイルを生成する。


★ちなみに上の3〜5は下記コマンドで一気にやってくれる。

Mac:jobeet kaneda$ php symfony propel:build-all --no-confirmation


★そしてキャッシュを削除。

Mac:jobeet kaneda$ php symfony cc


★初期データ用のYML作成
/jobeet/data/fixtures/010_categories.ymlというファイルを作り、下記コピペ

JobeetCategory:
  design:        { name: Design }
  programming:   { name: Programming }
  manager:       { name: Manager }
  administrator: { name: Administrator }

次に/jobeet/data/fixtures/020_jobs.ymlというファイルを作り、下記コピペ

JobeetJob:
  job_sensio_labs:
    category_id:  programming
    type:         full-time
    company:      Sensio Labs
    logo:         sensio-labs.gif
    url:          http://www.sensiolabs.com/
    position:     Web Developer
    location:     Paris, France
    description:  |
      You've already developed websites with symfony and you want to
      work with Open-Source technologies. You have a minimum of 3
      years experience in web development with PHP or Java and you
      wish to participate to development of Web 2.0 sites using the
      best frameworks available.
    how_to_apply: |
      Send your resume to fabien.potencier [at] sensio.com
    is_public:    true
    is_activated: true
    token:        job_sensio_labs
    email:        job@example.com
    expires_at:   2010-10-10
 
  job_extreme_sensio:
    category_id:  design
    type:         part-time
    company:      Extreme Sensio
    logo:         extreme-sensio.gif
    url:          http://www.extreme-sensio.com/
    position:     Web Designer
    location:     Paris, France
    description:  |
      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
      eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
      enim ad minim veniam, quis nostrud exercitation ullamco laboris
      nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
      in reprehenderit in.
 
      Voluptate velit esse cillum dolore eu fugiat nulla pariatur.
      Excepteur sint occaecat cupidatat non proident, sunt in culpa
      qui officia deserunt mollit anim id est laborum.
    how_to_apply: |
      Send your resume to fabien.potencier [at] sensio.com
    is_public:    true
    is_activated: true
    token:        job_extreme_sensio
    email:        job@example.com
    expires_at:   2010-10-10

ファイルが二つに分かれているけど、1つにまとめることもできるようだ。
ファイル名の先頭の数字は、このファイルを読み込む順番。


★画像ファイルを拾ってくる
下の画像をダウンロードして/jobeet/web/uploads/の中にjobsフォルダを作成し、その中に画像をぶち込む。
http://www.symfony-project.org/get/jobeet/sensio-labs.gif
http://www.symfony-project.org/get/jobeet/extreme-sensio.gif


★データベースに初期データを投入
データベースにアクセスする場合のコマンドはPHPのパスをフルパスで。

Mac:jobeet kaneda$ /Applications/xampp/xamppfiles/bin/php symfony propel:data-load

http://localhost/phpmyadminで確認すると無事データが入っていた。


★モジュールを作る
jobリストの表示やjobを編集する画面、jobを削除する機能などのアクションを自動で作ってくれる魔法のコマンドだっ。

Mac:jobeet kaneda$ php symfony propel:generate-module --with-show --non-verbose-templates frontend job JobeetJob
[?php include_stylesheets_for_form($form) ?]
[?php include_javascripts_for_form($form) ?]


Fatal error: Class 'JobeetJobForm' not found in /Applications/xampp/xamppfiles/lib/php/pear/symfony/generator/sfModelGenerator.class.php on line 321

しかし変なエラーが。調べたところ、フォームのなにかが無いと言っているらしいので、下記コマンドでフォーム部分のファイルを生成するコマンドを実行してあげるとうまくいった。

Mac:jobeet kaneda$ php symfony propel:build-forms
↓そしてもう一回モジュール作成
Mac:jobeet kaneda$ php symfony propel:generate-module --with-show --non-verbose-templates frontend job JobeetJob
↓キャッシュ削除
Mac:jobeet kaneda$ php symfony cc

/jobeet/apps/modules/にjobというフォルダが出来て、いろいろファイルが生成された。
そして、http://jobeet.local/frontend_dev.php/jobにアクセス。

レイアウトが変だけど、020_jobs.ymlに書いた初期データが表示されている。しかし、編集画面(http://jobeet.local/frontend_dev.php/job/edit/id/1)を表示してみると、

500 | Internal Server Error | RuntimeException
Class "JobeetCategory" must implement a "__toString" method to be rendered in a "sfWidgetFormPropelChoice" widget
〜

またしてもエラー。すんなり進んでくれない。
調べてみたところ、このチュートリアルの説明順序が間違っているらしく、先にプログラムを編集するステップをやってあげないとエラーがでるものらしい。

/jobeet/lib/model/JobeetCategory.phpを開いて、下記の通り編集。

<?php

class JobeetCategory extends BaseJobeetCategory
{
  public function __toString()
  {
    return $this->getName();
  }
}

次に/jobeet/lib/model/JobeetJob.phpを開いて、下記の通り編集。

<?php

class JobeetJob extends BaseJobeetJob
{
  public function __toString()
  {
    return sprintf('%s at %s (%s)', $this->getPosition(), $this->getCompany(), $this->getLocation());
  }
}

最後に/jobeet/lib/model/JobeetAffiliate.phpを開いて、下記の通り編集。

<?php

class JobeetAffiliate extends BaseJobeetAffiliate
{
  public function __toString()
  {
    return $this->getUrl();
  }
}

再度編集画面にアクセス。
http://jobeet.local/frontend_dev.php/job/edit/id/1


チュートリアルの通りちゃんと表示された。