symfony advent calendar day two: setting up a data model
μ§λ μ€κ±°λ¦¬
μ§λ μκ°μλ μ¬ν¬λ μ€μΉ λ°©λ², μλ‘μ΄ μ΄ν리μΌμ΄μ κ³Ό κ·Έ κ°λ°νκ²½μ μ€μ νλ λ°©λ², κ·Έλ¦¬κ³ μμ€ λ²μ 컨νΈλ‘€ μννΈμ¨μ΄λ₯Ό ν΅ν΄ μμ€λ₯Ό μμ νκ² κ΄λ¦¬νλ λ°©λ²λ€μ μμ보μμ΅λλ€. μ§λ μκ°μ λ§λ€μ΄μ§ μμ€λ askeet SVN μ μ₯μμμ λ€μ΄λ‘λ κ°λ₯ν©λλ€.
http://svn.askeet.com/
μ€λμ κΈ°λ₯μ μΈ μΈ‘λ©΄μμ μ°λ¦¬κ° λ§λ€κ³ μ νλ κ²μ΄ 무μμΈμ§ μ μνκ³ , λ°μ΄ν° λͺ¨λΈμ λΌλλ₯Ό λ§λ νμ μ½λ©μ μμν κ²μ λλ€. μ΄λ₯Ό μν΄ κ°μ²΄-κ΄κ³ μ°κ²° (object-relational mapping) μ μμ±νκ³ , μ΄λ₯Ό λ°νμΌλ‘ λ°μ΄ν°λ² μ΄μ€ λ μ½λλ₯Ό μμ±, κ²μ, κ·Έλ¦¬κ³ μμ νλ μ΄ν리μΌμ΄μ κ±°νΈμ§ (scaffolding) μ λ§λ€κ²μ λλ€.
ν΄, λ§κ΅°μ. μ μμν΄ λ³Όκ² μ΅λλ€.
νλ‘μ νΈ κ³΅κ°
무μμ μκ³ μΆμΌμλκΉ? λ§€μ° ν₯λ―Έλ‘μ΄ μ§λ¬Έμ΄μ£ . μΈμμλ μ λ§ λ§μ ν₯λ―Έλ‘μ΄ μ§λ¬Έλ€μ΄ μμ΅λλ€.
- μ€λ λ°€μ μ¬μμΉκ΅¬μ 무μμ νλ©΄ μ’μκΉ?
- λ΄ λΈλ‘κ·Έμ μ¬λλ€μ μ΄λ»κ² λμ΄λ€μΌκΉ?
- 무μμ΄ κ°μ₯ νλ₯ν μΉ μ΄ν리μΌμ΄μ νλ μμμΈκ°?
- ν리μμ κ°μ₯ μ λ ΄ν μλΉμ μ΄λμΌκΉ?
- μΆμ λν, μ°μ£Όμ λν, κ·Έλ¦¬κ³ λ€λ₯Έ λͺ¨λ κ²λ€μ λν λ΅μ 무μμΈκ°?
μ΄ λͺ¨λ μ§λ¬Έλ€μ λν λ΅μ νλλ§ μλ κ²λ μλκ³ , μ΅κ³ μ λλ΅μ΄λ κ²λ κ°μΈμ λ°λΌ λ€λ₯Ό μ μμ΅λλ€. μ¬μ€ 1+1 μ?
μ²λΌ λ΅μ΄ νλλΏμΈ μ§λ¬Έλ€μ λ³΄ν΅ μ¬λ―Έμλ κ²μ΄ λ§μ§μ.
askeet μ λ¬Όμ΄λ³΄μμμ€. askeet μ μ¬λλ€μ΄ κΆκΈν΄ νλ κ²λ€μ λν λ΅μ μ£ΌκΈ° μν΄ λ§λ€μ΄μ§ μ¬μ΄νΈμ λλ€. κ»λλ½κ³ μ΄λ €μ΄ μ§λ¬Έλ€μλ λκ° λ΅λ³μ νλμ? λͺ¨λμ λλ€. λν λͺ¨λ μ¬λλ€μ λ€λ₯Έ μ¬λλ€μ΄ ν λ΅λ³μ νκ°ν μ μκ³ , κ°μ₯ λκ² νκ°λ°μ λ΅λ³μ΄ κ°μ₯ μ 보μ΄λλ‘ λ κ²μ λλ€. μ§λ¬Έμ΄ λ§μμ§ μλ‘ μΉ΄ν κ³ λ¦¬λ₯Ό ν΅ν΄ μ§λ¬Έλ€μ μ 리νκΈ° μ΄λ €μΈ κ²μ΄λ―λ‘, del.icio.us "μ€νμΌλ‘", μ§λ¬Έμλ μμ μ΄ μνλ μ΄λ ν λ¨μ΄λ‘λ νκ·Έλ₯Ό λ§λ€ μ μλλ‘ ν κ²μ λλ€. νκ·Έκ° μΈκΈ°λμ λ°λΌμ νκ·Έ λ²λΈ ννλ‘ λ³΄μ¬μ§λ κ²μ λΉμνκ² μ§μ. λ§μ½ ν μ§λ¬Έμ λͺ¨λν°νκ³ μΆμ κ²½μ°λ₯Ό μν΄ κ°κ°μ μ§λ¬Έλ€μ RSS ννλ‘λ μ 곡λ κ²μ λλ€. μ΄ λͺ¨λ κΈ°λ₯λ€μ΄ λ©μ§κ³ κ°λ³κΈ°λλ¬Έμ νΉλ³ν μλ‘μ΄ νμ΄μ§κ° νμν κ²½μ°κ° μλλΌλ©΄ AJAX ννλ‘ λ§λ€μ΄μ§ κ²μ λλ€. κ·Έλ¦¬κ³ λ§μ§λ§μΌλ‘ κ΄λ¦¬μ λͺ¨λμμλ μ€νΈμΌλ‘ μ κ³ λ μ§λ¬Έμ΄λ λ΅λ³λ€μ μμ νκ±°λ, κ΄λ¦¬μκ° μ°Ύμ μ’μ μ§λ¬Έλ€μ μ’ λ λ ΈμΆλλλ‘ ν μ μμ΄μΌ ν κ²μ λλ€.
"μ΄λ° μΉ μ¬μ΄νΈλ€μ μ΄λ―Έ μμ§ μλ?" νκ³ μκ°ν μ§λ λͺ¨λ₯΄κ² μ΅λλ€. μ€μ λ‘ κ·Έλ κ² μκ°νμ λ€λ©΄, μ, λ€μΌ°λμ? νμ§λ§ faqt, eHow, Ask Jeeves λλ μ΄μ μ μ¬ν λ€λ₯Έ μ¬μ΄νΈλ€μ ν λ² μ΄ν΄λ³΄μΈμ. μ¬λ¬ μ¬λμ΄ νλμ λ΅λ³μ ν¨κ» λ§λ€μ΄ κ° μλ μκ³ , AJAX κΈ°λ₯λ μκ³ , RSS κΈ°λ₯λ μκ³ , νκ·Έ κΈ°λ₯λ μμΌλ, λκ°μ μΉ μ¬μ΄νΈλΌκ³ ν μ μλ μμ΅λλ€. μ°λ¦¬λ μΉ 2.0 μ΄ν리μΌμ΄μ μ λ§λ€κ²μ λλ€.
askeet μ κ°μ₯ ν° λ€λ₯Έ μ μ, κ·Έκ²μ΄ λ¨μν μΉ μ¬μ΄νΈκ° μλλΌ, λꡬλ λ€μ΄λ‘λν΄μ μ€μ μ λ°κΎΈκ³ κΈ°λ₯μ μΆκ°ν ν μ§μ΄λ νμ¬ μΈνΈλΌλ·μμ μ¬μ© κ°λ₯ν μ΄ν리μΌμ΄μ μ΄λΌλ μ μ λλ€. μμ€ μ½λλ μ€ν μμ€ λΌμ΄μ μ€λ‘ λ°°ν¬λ κ²μ λλ€. μ¬λ¬λΆμ HR νμ₯μ΄ μ§μ κ΄λ¦¬ μμ€ν μ μ°Ύκ³ κ³μλκΉ? μ°¨λ₯Ό κ³ μΉλλ° νμνλ νΈλ¦λ€μ μ λ¦¬ν΄ λκ³ μΆμΌμΈμ? μ¬λ¬λΆμ μΉμ¬μ΄νΈλ₯Ό μν΄ FAQ λ₯Ό κ°λ°νκ³ μΆμ§ μμΌμκ² μ£ ? μ΄μ κ·Έλ§ μ°ΎμΌμ λ μ’μ΅λλ€. askeet μ΄ μμΌλκΉμ. μ, askeet μ΄ μμ κ²μ λλ€. μ°λ¦¬μ ν¬λ¦¬μ€ λ§μ€ μ λ¬Όμ΄λΌκ³ μκ°ν΄μ£ΌμΈμ.
μ΄λμλΆν° μμν΄μΌ ν κΉ?
μ¬ν¬λ μ΄ν리μΌμ΄μ μ λ§λλ μΌμ μ΄λ»κ² μμν μ§λ μ¬λ¬λΆκ» λ¬λ €μμ΅λλ€. μ¬λ¬λΆμ΄ λ§μ½ XP μ μ΅μνλ€λ©΄, λ¨Όμ μ€ν 리λ₯Ό μμ±νκ³ , κ³νμ μΈμ΄ ν, μ§ νλ‘κ·Έλλ° (pair programming) μ ν¨κ» ν ννΈλλ₯Ό μ°ΎμΌμΌ ν κ²μ λλ€. λ§μ½ λΉμ μ΄ UML μ λλΌλ©΄ λ¨Όμ μΉμ¬μ΄νΈμ κ΄ν μμΈν μ€νμ μμ±νκ³ , λͺ¨λ κ°μ²΄λ€κ³Ό μνλ€, κ·Έλ¦¬κ³ κ·Έλ€κ°μ μνΈμμ©μ κ΄ν νλ₯Ό 그릴κ²μ λλ€.
νμ§λ§ μ΄ νν 리μΌμ μΌλ°μ μΈ μμ©νλ‘κ·Έλ¨ κ°λ°μ κ΄ν κ²μ΄ μλκΈ° λλ¬Έμ, μ°λ¦¬λ κ°λ¨ν κ΄κ³ν μλ£ λͺ¨λΈμ μΈμ΄ ν νλμ© κΈ°λ₯μ μΆκ°νλ λ°©ν₯μΌλ‘ μΌμ μ§ννκ³ μ ν©λλ€. μ°λ¦¬κ° νκ³ μ νλ κ²μ νλ£¨κ° λλ λ μ―€μλ μλ²½νκ² μλνλ μ΄ν리μΌμ΄μ μ λ§λ€κ³ μΆμ κ²μ΄μ§, μμ²λ μμ μ λλ‘ μλνμ§ μλ μ§νμ€μΈ μ½λλ₯Ό λ§λ€κ³ μΆμ§ μμ΅λλ€. μ΄μμ μΌλ‘λ μ°λ¦¬κ° μΆκ°νκ³ μ νλ λͺ¨λ κΈ°λ₯μ λν΄μ μ λ ν μ€νΈλ₯Ό μμ±ν΄μΌ νμ§λ§, μμ§ν κ·Έλ κ² ν μκ°μ΄ λΆμ‘±ν©λλ€. μ΄ νν 리μΌμ μ§νν 24μΌμ€ ν루λ μ λ ν μ€νΈμ μ§μ€νλλ‘ ν ν λ κ³μ μ½μ΄μ£ΌμΈμ.
ν΅ν©μ±μ μν μ μ½μ‘°κ±΄ (integrity constraints) κ³Ό νΈλμμ
(transaction) μ μ¬μ©νκΈ° μν΄, μ΄λ² νλ‘μ νΈμλ MySQL λ°μ΄ν°λ² μ΄μ€μ InnoDB ν
μ΄λΈμ μ¬μ©ν κ²μ
λλ€. μ€μ λ°μ΄ν°λ² μ΄μ€ μ¬μ©μ ν μ μλ κ²½μ°μλ μ΄λ°μ κ²½μ°μ νν΄ SQLite λ°μ΄ν°λ² μ΄μ€λ₯Ό μ¬μ©ν μλ μμ΅λλ€. μ΄λ₯Ό μν΄μλ databases.yml
νμΌμ μμ ν΄μΌ νλλ°, μ΄λ μ¬λ¬λΆμκ² λ§‘κΈ°λλ‘ νκ² μ΅λλ€.
λ°μ΄ν° λͺ¨λΈ
κ΄κ³ν λͺ¨λΈ
λͺ λ°±νκ²λ μ°λ¦¬λ 'question' ν μ΄λΈκ³Ό 'answer' ν μ΄λΈμ΄ νμν©λλ€. 'user' ν μ΄λΈλ νμν κ²μ΄λ©°, μ¬μ©μλ€μ ν₯λ―Έλ‘μ νλ μ§λ¬Έμ λν μ 보λ₯Ό μ μ₯ν 'interest' ν μ΄λΈ, κ·Έλ¦¬κ³ μ¬μ©μλ€μ΄ λ΅λ³μ λν νκ°μ κ΄ν μ 보λ₯Ό μ μ₯ν 'relevancy' ν μ΄λΈλ νμν©λλ€.
μ¬μ©μ μ 보λ μ§λ¬Έμ μΆκ°νκ³ , λ΅λ³μ νκ°νκ±°λ μ§λ¬Έμ λν κ΄μ¬μ νκ°νλλ° μ¬μ©λ κ²μ λλ€. λ΅λ³μ λ±λ‘νλ κ³Όμ μλ μ¬μ©μ μ λ³΄κ° νμμμ§λ§, λ΅λ³λ€μ μ¬μ©μμ μ°κ²°λλλ‘ ν΄μ μ’μ λ΅λ³μ νλ μ¬μ©μλ₯Ό ꡬλ³ν΄ λΌ μ μλλ‘ ν κ²μ λλ€. μ¬μ©μ μ 보 μμ΄ μ λ ₯λ λ΅λ³μ 'Anonymous Coward' λΌκ³ λΆλ¦¬λ μΌλ°μ μΈ μ¬μ©μ μ΄λ¦μΌλ‘ νμλ κ²μ λλ€. μν°ν° κ΄κ³νλ₯Ό 보면 ν¨μ¬ μ΄ν΄νκΈ° μ¬μΈ κ²μ λλ€.
κ° ν
μ΄λΈμ΄ created_at
νλλ₯Ό κ°μ§κ³ μλκ²μ μ£Όλͺ©νμμμ€. μ¬ν¬λλ created_at
νλλ₯Ό μΈμν΄μ, μλ£κ° μμ±λ λ μλμΌλ‘ μμ±μκ°μ κΈ°λ‘ν κ²μ
λλ€. λΉμ·ν κ²μΌλ‘ updated_at
νλκ° μμ΅λλ€. μ¬ν¬λλ λ μ½λκ° μ
λ°μ΄νΈλ λ, ν΄λΉ νλμ μ
λ°μ΄νΈλλ μκ°μ κΈ°λ‘ν κ²μ
λλ€.
schema.xml
μ¬ν¬λκ° μ΄ν΄νκΈ° μν΄μλ κ΄κ³λͺ¨λΈμ μ€μ νμΌλ‘ λ°κΎΈμ΄μ£Όμ΄μΌ ν©λλ€. μ¬ν¬λκ° μ΄ν΄ν μ μλ κ΄κ³λͺ¨λΈμ κΈ°μ νλ κ²μ΄ askeet/config/
λλ ν 리μ μλ schema.xml
νμΌμ
λλ€.
μ΄ νμΌμ λ§λλ λ°©λ²μλ λκ°μ§κ° μμ΅λλ€. 첫λ²μ§Έλ μμΌλ‘ μ§μ λ§λλ κ²μ΄κ³ (μ΄κ²μ΄ μ°λ¦¬κ° μ’μνλ λ°©λ²μ λλ€.), κΈ°μ‘΄μ λ°μ΄ν°λ² μ΄μ€ ꡬ쑰λ₯Ό λ°νμΌλ‘ μμ±νλ λ°©λ²μ΄ μμ΅λλ€. λ¨Όμ 첫λ²μ§Έ λ°©λ²μ μ΄ν΄λ³΄λλ‘ νκ² μ΅λλ€. μμνκΈ° μ μ, μ€μΉμμ ν¨κ» μ€μΉλλ μμ νμΌμ μ΄λ¦μ λ°κΏλλ€.
$ svn rename config/schema.xml.sample config/schema.xml
schema.xml
νμΌμ μμΈν ꡬ쑰λ Propel μΉμ¬μ΄νΈ μμ μμΈν μ μ μμ§λ§, μλμ μΌλ‘ κ°λ¨ν ννμ
λλ€. μ΄ νμΌμ <column>
, <foreign-key>
κ·Έλ¦¬κ³ <index>
νκ·Έλ₯Ό ν¬ν¨νλ <table>
ν
κ·Έλ€μ κ°μ§λ XML νμΌμ
λλ€. ν λ²λ§ μ΄ νμΌμ λ§λ€μ΄ 보면, κΈλ°© μ΅μν΄μ§μ€ κ²μ
λλ€. μλμλ μ°λ¦¬κ° μμ μ€λͺ
νλ κ΄κ³μλ£ λͺ¨λΈμ
λλ€.
<?xml version="1.0" encoding="UTF-8"?> <database name="propel" defaultIdMethod="native" noxsd="true"> <table name="ask_question" phpName="Question"> <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" /> <column name="user_id" type="integer" /> <foreign-key foreignTable="ask_user"> <reference local="user_id" foreign="id"/> </foreign-key> <column name="title" type="longvarchar" /> <column name="body" type="longvarchar" /> <column name="created_at" type="timestamp" /> <column name="updated_at" type="timestamp" /> </table> <table name="ask_answer" phpName="Answer"> <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" /> <column name="question_id" type="integer" /> <foreign-key foreignTable="ask_question"> <reference local="question_id" foreign="id"/> </foreign-key> <column name="user_id" type="integer" /> <foreign-key foreignTable="ask_user"> <reference local="user_id" foreign="id"/> </foreign-key> <column name="body" type="longvarchar" /> <column name="created_at" type="timestamp" /> </table> <table name="ask_user" phpName="User"> <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" /> <column name="nickname" type="varchar" size="50" /> <column name="first_name" type="varchar" size="100" /> <column name="last_name" type="varchar" size="100" /> <column name="created_at" type="timestamp" /> </table> <table name="ask_interest" phpName="Interest"> <column name="question_id" type="integer" primaryKey="true" /> <foreign-key foreignTable="ask_question"> <reference local="question_id" foreign="id"/> </foreign-key> <column name="user_id" type="integer" primaryKey="true" /> <foreign-key foreignTable="ask_user"> <reference local="user_id" foreign="id"/> </foreign-key> <column name="created_at" type="timestamp" /> </table> <table name="ask_relevancy" phpName="Relevancy"> <column name="answer_id" type="integer" primaryKey="true" /> <foreign-key foreignTable="ask_answer"> <reference local="answer_id" foreign="id"/> </foreign-key> <column name="user_id" type="integer" primaryKey="true" /> <foreign-key foreignTable="ask_user"> <reference local="user_id" foreign="id"/> </foreign-key> <column name="score" type="integer" /> <column name="created_at" type="timestamp" /> </table> </database>
(μ£Ό - μλ schema.yml νμΌμ schema.xml νμΌκ³Ό λμΌν ꡬ쑰λ₯Ό κΈ°μ ν©λλ€.)
propel: ask_question: _attributes: { phpName: Question } id: user_id: title: longvarchar body: longvarchar created_at: updated_at: ask_answer: _attributes: { phpName: Answer } id: question_id: user_id: body: longvarchar created_at: ask_user: _attributes: { phpName: User } id: nickname: varchar(50) firstname: varchar(100) lastname: varchar(100) created_at: ask_interest: _attributes: { phpName: Interest } question_id: user_id: created_at: ask_relevancy: _attributes: { phpName: Relevancy } answer_id: user_id: score: integer created_at:
μ€μ λ°μ΄ν°λ² μ΄μ€ μ΄λ¦κ³Ό κ΄κ³μμ΄ μ΄ νμΌμλ propel
μ΄λΌλ λ°μ΄ν° λ² μ΄μ€ μ΄λ¦μ΄ μ¬μ©λμμ΅λλ€. μ΄ κ°μ μ¬ν¬λ νλ μμμ΄ Propel κ³Ό μλ£λ₯Ό μ£Όκ³ λ°μλ μ¬μ©νλ κ°μ
λλ€. μ€μ λ°μ΄ν°λ² μ΄μ€ κ΄λ ¨ μ 보λ μ‘°κΈ νμ μ€μ νμΌλ€ μ€ databases.yml
μ κΈ°λ‘λμ΄μ§ κ²μ
λλ€.
schema.xml
νμΌμ κΈ°λ‘νλ λ€λ₯Έ λ°©λ²μ μ€μ λ°μ΄ν°λ² μ΄μ€μ ꡬ쑰λ₯Ό νμ©νλ κ²μ
λλ€. λ§μ½ μ¬λ¬λΆμ΄ κ·Έλν½ λ°μ΄ν°λ² μ΄μ€ λμμΈ ν΄μ μ¬μ©νλλ° μ΅μνμλ€λ©΄, μμ±λ MySQL λ°μ΄ν°λ² μ΄μ€λ‘ λΆν° νμΌμ μμ±νλκ² νΈλ¦¬ν κ²μ
λλ€. μ΄λ₯Ό μμνκΈ° μ μ, μ¬λ¬λΆμ askeet/config/
λλ ν 리μ μλ propel.ini
νμΌμ μμ ν΄μ λ°μ΄ν°λ² μ΄μ€μ μ°κ²°μ΄ κ°λ₯νλλ‘ ν΄μΌ ν©λλ€.
propel.database.url = mysql://username:password@localhost/databasename
username
, password
, localhost
κ·Έλ¦¬κ³ databasename
λΆλΆμ΄ μ¬λ¬λΆμ΄ μ¬λ¬λΆμ λ°μ΄ν°λ² μ΄μ€ μ°κ²° μ λ³΄λ‘ λ°κΎΈμ΄ μ£Όμ΄μΌ νλ νλͺ©λ€μ
λλ€. μ΄μ askeet/
λλ ν 리μμ propel-build-schema
λͺ
λ Ήμ λ΄λ¦ΌμΌλ‘μ¨ schema.xml
νμΌμ λ§λ€ μ μμ΅λλ€.
$ symfony propel-build-schema
μ°Έκ³ : λͺλͺ ν΄λ€μ λ°μ΄ν°λ² μ΄μ€ ꡬ쑰λ₯Ό κ·Έλν½μ μΌλ‘ λ§λ€ μ μλλ‘ λμμ£Όκ³ (μλ₯Ό λ€λ©΄ Fabforce μ Dbdesigner),
schema.xml
νμΌκΉμ§ μμ±μμΌ μ€λλ€. (DB Designer 4 TO Propel Schema Converter).
κ°μ²΄ λͺ¨λΈ μμ±
InnoDB μμ§μ μ¬μ©νκΈ° μν΄μ askeet/config/
λλ ν 리μ propel.ini
νμΌμ μλ μ€μ μΆκ°ν©λλ€.
propel.mysql.tableType = InnoDB
schema.xml
μ΄ μμ±λ νμλ, λ°μ΄ν°λ² μ΄μ€ κ΄κ³ λͺ¨λΈμ λ°νμΌλ‘ κ°μ²΄λͺ¨λΈμ μμ±ν μ μμ΅λλ€. κ°μ²΄-κ΄κ³ μ°κ²°μ Propel μ΄ λ΄λΉνμ§λ§, μλμ κ°μ μ¬ν¬λ 컀맨λ λΌμΈ ν΄μ ν΅ν΄μ μ¬μ©μ΄ κ°λ₯ν©λλ€.
$ symfony propel-build-model
μ΄ λͺ
λ ΉμΌλ‘ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§μ μ μλ ν
μ΄λΈμ μμνλ ν΄λμ€λ€μ΄ μμ±λλ©°, μ΄λ€ ν΄λμ€λ νμ€ μ κ·Όμ (->get()
, ->set()
λ©μ¨λ) λ€μ κ°μ§κ³ μμ΅λλ€. (askeet νλ‘μ νΈμ κ°μ₯ μμ λλ ν 리μμ λͺ
λ Ήμ λ΄λ €μΌ ν©λλ€.) μμ±λ μ½λλ€μ askeet/lib/model/om/
λλ ν 리μ μμ΅λλ€. ν΄λΉ λλ ν 리λ₯Ό 보μλ©΄ κ°κ°μ ν
μ΄λΈλ§λ€ λκ°μ ν΄λμ€κ° μλ κ²μ λ°κ²¬νμ€ κ²μ
λλ€. (μ΄μ λν μ΄μ λ₯Ό μκ³ μΆμΌμλ©΄ μ¨λΌμΈ λ¬Έμλ€ μ€ λͺ¨λΈ μ±ν° λ₯Ό μ°Έκ³ νμκΈ° λ°λλλ€.) μ΄λ€ ν΄λμ€λ μ¬λ¬λΆμ΄ build-model
λͺ
λ Ήμ λ΄λ¦΄λλ§λ€ μλ‘ μ°μ¬μ§ κ²μ
λλ€. νλ‘μ νΈλ₯Ό μ§ννλ λμ κ΄κ³ λͺ¨λΈμ μμ μ΄ νμν κ²½μ°λ μλΉν λ§κΈ° λλ¬Έμ, λ§μ½ μ¬λ¬λΆμ΄ κ°μ²΄ λͺ¨λΈμ λ©μ¨λλ₯Ό μΆκ°νκ³ μΆμΌμλ€λ©΄, askeet/lib/model/
λλ ν 리μ ν΄λμ€λ₯Ό μμ νμλκ² μ’μ΅λλ€. μ΄λ€ ν΄λμ€λ /om
λλ ν 리μ ν΄λμ€λ€μ μμνκΈ° λλ¬Έμ μ΄λ° λ¬Έμ λ‘λΆν° μμ λ‘μ΅λλ€.
λ°μ΄ν° λ² μ΄μ€
μ°κ²°
μ΄μ μ¬ν¬λκ° λ°μ΄ν°λ² μ΄μ€μ κ°μ²΄ λͺ¨λΈμ κ°μ§κ² λμμΌλ, MySQL λ°μ΄ν° λ² μ΄μ€μ μ°κ²°ν μ°¨λ‘μ λλ€. λ¨Όμ , MySQL λ°μ΄ν° λ² μ΄μ€λ₯Ό μμ±ν©λλ€.
$ mysqladmin -u youruser -p create askeet
μ μ΄μ askeet/config/databases.yml
νμΌμ μ½λλ€. λ§μ½ μ΄λ²μ΄ μ¬ν¬λλ₯Ό μ²μ μ¬μ©νμλ κ²μ΄λΌλ©΄, μ¬ν¬λ μ€μ νμΌμ΄ YAML νμμΌλ‘ μ°μ¬μ‘λ€λ κ²μ μ²μ λ°κ²¬νμ€ κ²λλ€. YAML λ¬Έλ²μ νκ°μ§ μ μ½μ μ μΈνκ³€ μλΉν κ°λ¨ν©λλ€. YAML μ μ μ½μ‘°κ±΄μ νμ μ¨μ μ λλ€λ κ²μ
λλ€. νλμ μ€νμ΄μ€λ₯Ό μ°μμμ€. μ΄κ²λ§ μκ³ κ³μλ©΄ λ€λ₯Έ κ²μ λ¬Έμ λ κ²μ΄ μμ΅λλ€. μ¬λ¬λΆμ μ€μ λ°μ΄ν°λ² μ΄μ€ μ°κ²° μ 보λ₯Ό all:
μΉ΄ν
κ³ λ¦¬ μλμ κΈ°λ‘νμμμ€.
all: propel: class: sfPropelDatabase param: phptype: mysql host: localhost database: askeet username: youruser password: yourpasswd
λ§μ½ YAML νμΌκ³Ό μ¬ν¬λ μ€μ μ κ΄ν΄ λ μκ³ μΆμΌμλ€λ©΄ μ¨λΌμΈ λ¬Έμ μ€ μ€μ λΆλΆμ μ°Έκ³ νμκΈ° λ°λλλ€.
ν μ΄λΈ μμ±
μ¬λ¬λΆμ΄ schema.xml
νμΌμ μ§μ μμ±νλλμ κΈ°μ‘΄ λ°μ΄ν°λ² μ΄μ€ ꡬ쑰λ₯Ό λ°νμΌλ‘ ν΄λΉ νμΌμ μμ±νλ€λ©΄, μ¬λ¬λΆμ μ΄λ―Έ μ΄ νμΌμ κ°μ§κ³ μμ΅λλ€. μ΄λ² λ¨κ³λ 건λ λ°μ
λ μ’μ΅λλ€.
ν€λ³΄λλ₯Ό μ’μνμλ μ¬λ¬λΆλ€κ» λλΌμ΄ μμμ΄ μμ΅λλ€. μ¬λ¬λΆμ MySQL λ°μ΄ν°λ² μ΄μ€μ ν
μ΄λΈμ΄λ 컬λΌμ λ§λμ€ νμκ° μμ΅λλ€. μ¬λ¬λΆμ μ΄λ―Έ schema.xml
νμΌμ λ§λ€μκ³ , μ¬ν¬λκ° μ΄λ₯Ό λ°νμΌλ‘ SQL λ¬Έμ₯μ λ§λ€μ΄ μ€ κ²μ
λλ€.
$ symfony propel-build-sql
μ΄ λͺ
λ Ήμ askeet/data/sql
λλ ν 리μ lib.model.schema.sql
νμΌμ λ§λλλ€. μ΄λ₯Ό MySQL μ μ¬μ©νλ©΄ λ©λλ€.
$ mysql -u youruser -p askeet < data/sql/lib.model.schema.sql
CRUD λ₯Ό μ΄μ©ν ν μ€νΈ λ°μ΄ν° μ λ ₯
μμ μ΄ μ λμλμ§ νμΈνλ κ²μ μΈμ λ μ’μ μΌμ λλ€. μ°λ¦¬λ μΉ μ΄ν리μΌμ΄μ μ λ§λ€κ³ μμμλ λΆκ΅¬νκ³ , μμ§κΉμ§ λΈλΌμ°μ λ₯Ό μ¬μ©νμ μ΄ μλ€μ... μ, κ·ΈλΌ κΈ°λ³Έμ μΈ μ¬ν¬λ ν¬νλ¦Ώκ³Ό μ‘μ λ€μ μΆκ°ν΄μ 'question' ν μ΄λΈμ ν μ΄ν°λ₯Ό μ‘°μν΄λ³΄λλ‘ ν©μλ€. μ΄λ₯Ό ν΅ν΄ μ§λ¬Έλ€μ μ λ ₯νκ³ λ³΄μ¬μ£Όλ κ²μ΄ κ°λ₯ν κ²μ λλ€.
askeet/
λλ ν 리μμ λ€μμ μ
λ ₯νμμμ€.
$ symfony propel-generate-crud frontend question Question
μ΄ λͺ
λ Ήμ Question
Propel κ°μ²΄ λͺ¨λΈμ λ°νμΌλ‘νλ κ±°νΈμ§ (scaffolding) μ frontend
μ΄ν리μΌμ΄μ
μ question
λͺ¨λμ μΆκ°ν©λλ€. κ±°νΈμ§μλ κΈ°λ³Έμ μΈ μμ± (Create), κ²μ (Retrieve), μμ (Update), μμ (Delete) κΈ°λ₯μ΄ ν¬ν¨λ©λλ€. (CRUD μ½μκ° μ¬κΈ°μ μ겨λ¬μ΅λλ€.) μ§κΈ μμ±λ κ±°νΈμ§μ μμ±λ μ΄ν리μΌμ΄μ
μ΄ μλλλ€. νΌλνμ§ λ§μμμ€. μ΄λ€μ μ¬λ¬λΆμ΄ μλ‘μ΄ κΈ°λ₯μ μΆκ°νκ³ , λΉμ¦λμ€ λ‘μ§μ μΆκ°νκ³ , μΈκ΄μ λ³κ²½ν μ μλ κΈ°λ³Έμ μΈ κ΅¬μ‘°μ
λλ€.
CRUD μ λλ μ΄ν°μ μν΄ μμ±λ μ‘μ λ€μ λ€μκ³Ό κ°μ΅λλ€.
μ‘μ | μ€λͺ |
---|---|
list | ν μ΄λΈμ λͺ¨λ λ μ½λλ₯Ό 보μ¬μ€λ€. |
index | list μ‘μ μΌλ‘ μ λ¬ (forward) νλ€. |
show | ν΄λΉ λ μ½λμ λͺ¨λ νλλ₯Ό 보μ¬μ€λ€. |
edit | μλ‘μ΄ μ΄μ μ½μ νκ±°λ κΈ°μ‘΄ μλ£λ₯Ό μμ νκΈ° μν νΌμ 보μ¬μ€λ€. |
update | μμ² μ 보λ₯Ό λ°νμΌλ‘ λ μ½λλ₯Ό μμ νκ³ , show μ‘μ μΌλ‘ μ λ¬ (forward) νλ€. |
delete | λ μ½λλ₯Ό μμ νλ€. |
λ€λ₯Έ μ‘μ λ€μ κ΄ν΄μλ μ¨λΌμΈ λ¬Έμμ€ κ±°νΈμ§ κ΄λ ¨ λΆλΆμ μ€λͺ λμ΄ μμ΅λλ€.
askeet/apps/frontend/modules/
λλ ν 리μ question
λͺ¨λμ΄ μμ±λμμΌλ, ν λ² μμ€λ₯Ό λλ¬λ³΄μκΈΈ λ°λλλ€.
μλμΌλ‘ μ μ¬λμ΄μΌ νλ μλ‘μ΄ ν΄λμ€λ₯Ό μΆκ°νμ κ²½μ° μ€μ νμΌμ μλ‘ μ μ¬ν΄μΌ νλ€λ μ¬μ€μ μμ§λ§μΈμ. μλ λͺ λ Ήμ΄λ‘ μ€μ νμΌμ μλ‘κ² μ μ¬ν μ μμ΅λλ€.
$ symfony cc frontend config
μ΄μ λ€μ URL λ‘ ν μ€νΈλ₯Ό ν μ μμ΅λλ€.
http://askeet/question
μ, μ°λ¦¬ μμ€ν μ κ°μ§κ³ μ’ λμ보μΈμ. μ§λ¬Έλ μΆκ°νκ³ , μμ νκΈ°λ νκ³ , μμ νκΈ°λ νμλ©΄μ λ§μ΄μ£ . λ§μ½ μ¬λ¬λΆ μμ€ν μ΄ μ μλνλ€λ κ²μ μ°λ¦¬μ κ°μ²΄ λͺ¨λΈμ΄ μ μ§μ¬μ Έ μκ³ , λ°μ΄ν°λ² μ΄μ€ κ΄κ³ λͺ¨λΈκ³Ό μ¬ν¬λ κ°μ²΄ λͺ¨λΈμ΄ μλ‘ ν¨κ» μ μμ§μ΄κ³ μλ€λ λ»μ΄κΈ°λν©λλ€.
λ€μ μ΄ μκ°μ
PHP μ½λ ν μ€ μ°μ§ μκ³ κΈ°λ³Έμ μΈ μ΄ν리μΌμ΄μ μ κ°κ² λμμ΅λλ€. μ΄νμ§Έ μΉκ³€ λμμ§ μμ κ² κ°λ€μ. λ΄μΌμλ μ§λ¬Έλͺ©λ‘λ€μ κ°μ§λ λ©μΈ νμ΄μ§λ₯Ό λ§λ€κΈ° μν μ½λλ₯Ό μμ±ν κ²μ λλ€. λν μΌκ΄ μμ (batch process) λ₯Ό ν΅ν΄ ν μ€νΈ λ°μ΄ν°λ₯Ό λ±λ‘νκ³ λͺ¨λΈμ νμ₯νλ λ°©λ²μ λ°°μΈ κ²μ λλ€.
μ΄μ μ¬λ¬λΆμ μ°λ¦¬μ μ΄ν리μΌμ΄μ μ΄ λ¬΄μμ ν κ²μΈμ§ μμ ¨μ κ²μ λλ€. μ΄λ€ κΈ°λ₯λ€μ΄ μΆκ°λλ©΄ μ’μμ§λ₯Ό ν λ² μκ°ν΄λ³΄μκ³ μ¬λ¬λΆμ μ견μ λ©μΌλ§ 리μ€νΈ μ μλ €μ£ΌμΈμ. κ°μ₯ μΈκΈ°μ’μ μμ΄λμ΄κ° 21μΌμ§Έμ μΆκ°λ κ²μ λλ€.
μ€λ μ¬μ©λμλ μ½λλ€μ μλ SVN μ£Όμμ μμ΅λλ€. (release_day_2
ν
κ·Έ)
http://svn.askeet.com/tags/release_day_2
This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.