mylxiaoyi的专栏

在探索中求知,在思考中前进

用户操作
[即时聊天] [发私信] [加为好友]
萧易ID:mylxiaoyi
182458次访问,排名406好友55人,关注者58
在探索中求知,在思考中前进
mylxiaoyi的文章
原创 123 篇
翻译 62 篇
转载 13 篇
评论 31 篇
萧易的公告

声援SOFF|声援珊瑚虫:如果你是珊瑚虫用户,请坚决力挺声援珊瑚虫!

Name:
mylxiaoyi(萧易)
E-mail:
网易:
Google:

MSN:

mylxiaoyi新窝:
http://mylxiaoyi.cublog.cn
Google 网上论坛
订阅 myidea
电子邮件:
访问此论坛
最近评论
liuqun69:# 补充:Apache2.2对应的php5模块是php5apache2_2.dll,在httpd.conf的中配置如下:
LoadModule php5_module "c:/php/php5apache2_2.dll"
AddType application/x-httpd-php .php
ananai:你好, 我想装virtualbox,但到第四步的时候,就出错了

Bad luck,the kernel headers for the target kernel version could not be found and you did not specify other valid kernel headers to use

我试了很多种方法……
lujianjian:我发现了
http://www.watir.cn/?cat=5
已经翻译了所有的24天教程。还有实践中遇到的问题,很有参考价值。
博主可以考虑直接转载啊,就不用翻译了。

lujianjian:遇到了第3个问题
http://askeet/frontend_dev.php/question
发生错误
[PropelException]
No connection params set for [yml] propel
说没有找到propel的设置,可是这些设置完全按照教程设置的。
这时注意到错误信息是
No co……
lujianjian:遇到的第2个问题,
【通过CRUD测试数据访问】
执行下面URL时
http://askeet/question
发生错误,404找不到页面。
再看看
在web(我的机器是 E:\work\ECSite\askeet\web)目录下
并不存在 question这个目录,当然是会404.
难道是教程有错误吗?
文章分类
收藏
    相册
    MyPictures
    Pictures
    Linux
    LinuxFans
    LinuxForum
    LinuxSir
    Linux伊甸园
    OldLinux
    Some
    CSDN
    小友blog
    Fly
    fp862
    mylxiaoyi's Weblog
    刺刀特遣队
    萧易的Blog
    萧易的小窝
    飞翔的梦
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    翻译 第二天--设置一个数据模型收藏

    新一篇: 请大家支持珊瑚虫~~请大家帮帮soff~~ | 旧一篇: 第一天--开始一个工程

     

    第二天--设置一个数据模型

    Symfony回顾

    在这份长长的但是却十分有趣的指南的第一天内容中,我们了解了如何安装Symfony框架,设置一个新程序以及开发环境,并且使用了源码版本控制安全的存放源码。顺便说一句,在第一天所生成的程序源码可以在askeet的源码仓库得到:
    http://svn.askeet.com/

    第二天的目标是从功能的角度来定义最终的结果应是什么样子的,设计数据模型以及编码。这包括生成一个对象关系映射,并且使用他们来创建,取出以及更新程序框架数据中的记录。

    这确实是相当多的内容。让我们开始吧。

    揭开程序面纱

    我们希望了解什么呢?这是一个有趣的问题。对于这个问题有许多有趣的答案,如:

    如何带来我的blog的流量?
    什么是最好的web程序框架?

    所有这些问题不只有一个答案,而最好的答案在于我们的观点。实际上,只有一个答案的问题通常是最无趣的,但是在web上要解决的只有一个。这不公平。

    来askeet 吧。这是一个帮助人们查找问题答案的网站。谁会回答这些问题呢?所有人。而每一个人都可以评价其他人的答案,所以最受欢迎的答案会更可见。随着问题数量的 增加,使用类与子类的方式来组织就变得不可行了,所以问题的提出者就可以使用他希望的任何单词来进行标签化。当然,标签的流行程序是由一个标签集合来表示 的。如果一个希望跟随一个答案来找到一个问题,他可以订阅这个问题RSS反馈。所有这些功能都必须是优雅和轻量级的,从而所有这些交互不必需要一个 AJAX类型式的新页。事实上,需要一个后端来组织问题与答案,或是手工添加一个管理员认为有意义的问题。

    也许你会问:我还没有在web 上见到过这样的网站吗?当然,如果你确实是这样,那么我们正好,但是如果你见过如faqts,eHow,Ask leeves或是相似的内容,没有聚合答案,没有AJAX,没有RSS,没有标签,那么这些与我们的网站并不一样。我们这里在讨论一个web2.0的程 序。

    askeet的目录不只是一个网站,他是一个程序,任何人都可以下载,在家里或是在公司的网站上安全,修改或是添加新的特性。源码将 会以开放源码许可证的形式发布。你的HR经理正是寻找一个知识管理系统?你希望记录你学到的关于修理汽车的技艺?你并不希望为你的网站开发一个FAQ部 分?不必再寻找了,因为有askeet。当然,他将会存在,那是我们的圣诞礼物。

    从哪里开始?

    那么你如何开始一个Symfony程序呢?这取决于你自己。如果你是一个XP能手,你可以写一个故事,计划一个游戏,并且找到一个合作者来进行结对编程,或者如果你是一个UML迷,你可以编写一个详细的网站需要说明,附带一个所有对象,状态以及交互的框架。

    但 是这个教程并不是关于通常的程序开发的,所以我们从一个基本的关系数据模型开始,并且一步一步的添加工作特性。我们所需要的只是一个在每天结束时可用的程 序,而不是一个不会输出任何内容的巨大的程序代码。在理想的情况下,我们应为我们添加的每一个新特性编写单元测试,但是实际上我们并没有时间来这样做。如 果要进行单元测试,则需要一天的时间。所以我们还是继续阅读吧。

    对于这个工程,我们将使用一个带有InonoDB表类型的MySQL数据 库,这样可以充发利用集中控制与事务支持。在前面的步骤中,我们将会使用一个SQLite数据库,来避免设计一个实际的数据库。这需要 databases.yml文件中时行一些小的修改,我们会将这些工作作为探索的练习留给你。

    数据模型

    关系模型

    很明显,需要有一个'question'与一个'answer'数据表。我们需要一个'user'数据表,并且我们需要一个'interest'数据表来存储对一个问题感兴趣的用户,以及在一个'relevancy'数据表中记录一个用户对于一个答案所做出的中肯的评价。

    用 户需要进行确认来添加一个问题,评价答案,或者是删除对于一个问题的兴趣。用户添加答案并不需要进行确认,但是一个答案总是会链接到一个用户,这样给出最 受欢迎答案的用户可以进行区分。没有经过确认而发布的答案将会显示为一个通常用户的贡献,称之为'Anonymous Coward'。很容易理解整个关系数据表:
    ERD

    注意,对于每一个数据表,我们都声明了一个created_at域。Symfony会识别这样的域,并且在记录创建时会将其设置当前的系统时间。这也updated_at域相似:当记录更新时会将其设置为系统时间。

    schema.xml

    关系模型已经转换为一个Symfony可以理解的配置文件。这也就是schema.xml或是schema.yml文件的目的,这个文件位于askeet/config/目录下。Symfony支持XML或是YAML的格式语法。

    有两种方法来编写这个文件:手写,这也我们喜欢的方法,或者由一个已存在的数据库生成。让我们看一下第一种解决方法。

    首先,我们需要移除默认安装的YAML样式文件:

    $ svn delete config/schema.yml

    schema.yml 文件的语法是相当简单:他是一个XML文件,在其中<table>标记包含<column>,<foreign- key>以及<index>标记。一旦我们编写了一个,我们就可以编写所有的。下面是我们在前面所描述的关系模型的对应 schema.yml文件:

    <?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>

    注意,在这个文件中将数据名字设置为propel,而无论实际的数据库名字是什么。这个是一个用来连接Propel层与Symfony框架的参数。数据库的实际名字将会在databases.yml配置文件中定义。

    如 果我们有一个数据库,我们还有另外的一个方法来创建schema.yml文件。也就是说,如果我们熟悉一个图形化的数据库设计工具,我们会更喜欢由生成的 MySQL数据库来构建schema。在我们做这项工作之前,我们只需要编辑位于askeet/config/目录下的propel.ini文件,输入到 我们数据库的连接字符串:

    propel.database.url = mysql://username:password@localhost/databasename

    这里的username,password,localhost以及databasename是我们数据库的实际连接设置。现在我们可以调用propel-build-schema命令(在askeet/目录下)来由数据库生成schema.xml:

    $ symfony propel-build-schema

    除了创建一个schema.xml文件,我们也可以使用YAML的语法格式来创建一个schema.yml文件:

    [yml] propel: _attributes: { noXsd: false, defaultIdMethod: none, package: lib.model }

        ask_question:
          _attributes: { phpName: Question, idMethod: native }
          id:          { type: integer, required: true, primaryKey: true, autoIncrement: true }
          user_id:     { type: integer, foreignTable: ask_user, foreignReference: id }
          title:       { type: longvarchar }
          body:        { type: longvarchar }
          created_at:  ~
          updated_at:  ~

        ask_answer:
          _attributes: { phpName: Answer, idMethod: native }
          id:          { type: integer, required: true, primaryKey: true, autoIncrement: true }
          question_id: { type: integer, foreignTable: ask_question, foreignReference: id }
          user_id:     { type: integer, foreignTable: ask_user, foreignReference: id }
          body:        { type: longvarchar }
          created_at:  ~

        ask_user:
          _attributes: { phpName: User, idMethod: native }
          id:          { type: integer, required: true, primaryKey: true, autoIncrement: true }
          nickname:    { type: varchar(50), required: true, index: true }
          first_name:  varchar(100)
          last_name:   varchar(100)
          created_at:  ~

        ask_interest:
          _attributes: { phpName: Interest, idMethod: native }
          question_id: { type: integer, foreignTable: ask_question, foreignReference: id }
          user_id:     { type: integer, foreignTable: ask_user, foreignReference: id }
          created_at:  ~

        ask_relevancy:
          _attributes: { phpName: Relevancy, idMethod: native }
          answer_id:   { type: integer, foreignTable: ask_answer, foreignReference: id }
          user_id:     { type: integer, foreignTable: ask_user, foreignReference: id }
          score:       { type: integer }
          created_at:  ~

    构建对象模型

    要使用InonoDB引擎,必须在askeet/config/目录下的propel.ini文件中加入下面一行:

    propel.mysql.tableType = InnoDB

    一旦构建了schema.xml文件,我们可以基于这个关系模型生成一个对象模型。在Symfony中,对像关系映射是由Propel来处理的,但是封装到Symfony命令中:

    $ symfony propel-build-model

    这 个命令生成(我们需要在askeet工程的根目录下调用)与schema中定义的表相对应的类,并带有标准的访问方法(->get()与-> set()方法)。我们可以在askeet/lib/model/om/目录下查看这些生成的代码。如果我们想知道对于每一个数据表为什么需要两个类,我 们可以查看Symfony一书的model一章。每次我们执行build-model时,这些类就会被覆盖,而这在这个工程中是经常发生的。所以如果我们 需要在模型对象添加方法,我们必须修改位于askeet/lib/model/目录下的类--他们由/om继承来的。

    数据库

    连接

    现在数据库拥有一个数据库模型,现在我们要将工程连接到MySQL数据库。首先,我们需要在MySQL中创建一个数据库:

    $ mysqladmin -u youruser -p create askeet

    现 在打开askeet/config/databases.yml配置文件。如果这是我们第一次使用Symfony,我们就会发现Symfony的配置文件 是使用YAML语法编写的。这个语法非常简单,但是却有一个约定:不可以使用tab,只可以使用空格。我们知道了这些,我们就可以编写文件,在all:类 别下添加到我们数据库的连接设置:
    all:
      propel:
        class:      sfPropelDatabase
        param:
          phptype:  mysql
          host:     localhost
          database: askeet
          username: youruser
          password: yourpasswd

    如果我们希望了解更多的关于Symfony配置与YAML文件的内容,我们可以查看Symfony一书实际配置一章。

    构建

    如果我们没有手工编写schema.yml文件,而在我们的数据库中已有相应的数据表,我们可以跳过这一部分。

    对于键盘迷的我们来说,这里是一个叫人惊奇的地方:我们并不需要在MySQL数据库创建数据表与相应的数据列。我们已经在schema.xml中完成了工作,所以Symfony会为我们创建所有的SQL构建语句:

    $ symfony propel-build-sql

    这个命令会在askeet/data/sql/目录下创建一个lib.model.schema.sql文件。在MySQL中将其作为一条SQL命令:

    $ mysql -u youruser -p askeet < data/sql/lib.model.schema.sql

    相应的,我们也可以使用propel-insert-sql任务:

    $ symfony propel-insert-sql

    通过CRUD测试数据访问

    现在可以测试这些工作是否可以正常工作了。到现在为止,我们的浏览器还没有任何作用,而我们还在希望创建一个web程序。所以让我们来创建一个基本的Symfony模板与动作集合来处理'question'数据表的数据。这可以允许我们创建一些问题一些问题并进行显示。

    在askeet/目录下,输入下面命令:

    $ symfony propel-generate-crud frontend question Question

    这 会在frontend程序中为一个question模块生成一个框架,这个框架基于Question Propel对象模型,并且具有基本的创建,取出,更新与删除动作。不要感到迷惑:一个框架并不是一个完成的程序,而只是一个基本结构,在其上我们可以开 发新的特性,添加业务规则,自定义显示等。

    由一个CRUD生成器创建的动作列表如下:

    名字        描述
    list        显示一个数据表的所有记录
    index        转向到list
    show        显示一个指定记录的所有数据域
    edit        显示一个表单来创建一个新的记录或是编辑一个已存在的记录
    update        通过在请求中指定的参数来修改一个记录,然后转向到show
    delete        从数据表中删除一个指定的记录

    我们可以在Symfony一书的框架一节了解到更多的关于生成的动作的内容。

    无论何时当我们添加一个需要自动装入的新类时,不要忘记清除配置缓存(来重新装入自动载入缓存):
    $ symfony cc frontend config

    现在我们可以通过下面的URL来进行在线测试了:
    http://askeet/question

    现在我们可以执行一些操作。添加一些问题,编辑他们,删除他们。如果可以正常工作,这就意味着对象模型是正确的,也就是说到数据库的连接是正确的,数据库的关系模型到数据库的对象模型是正确的。这就是一个良好的功能测试。

    明天见

    我们并没有编写一行PHP代码,而我们已经有了一个可用的基本程序。这对于第二天并不坏。明天,我们将会编写一些代码来创建一个来显示问题列表的欢迎首页。我们也可以使用一个处理操作来向我们的数据库添加数据,并且学习如何扩展模块。

     原文地址 http://www.symfony-project.com

    发表于 @ 2007年11月16日 09:26:00|评论(loading...)|编辑

    新一篇: 请大家支持珊瑚虫~~请大家帮帮soff~~ | 旧一篇: 第一天--开始一个工程

    评论

    #lujianjian 发表于2007-12-01 13:59:01  IP: 218.242.184.*
    我在Windows环境下
    在执行
    【构建对象模型】的
    $symfony propel-build-model
    时发生错误,称未加载XSLT模块,但是检查 php5目录下的php.ini,
    extension=php_xsl.dll
    前面的 分号 “;” 已经被去除,而且,通过 phpinfo.php
    <?
    phpinfo();
    ?>
    查看,xsl模块已经被加载。
    同样的,在执行【构建】中
    $ symfony propel-build-sql
    的时候,报错,称MySQL模块未被加载,同样的,在php.ini中extension=php_mysql.dll
    已经去除了前面的 ";"
    最后,这个问题在
    http://www.symfony-project.org/forum/index.php/m/6574/
    找到答案,
    因为,Pake (Symfony's command line) 用的是CLI版本的PHP,和我们在 phpinfo.php中看到的并不一致。
    在我的机器上,Apache2的httpd.conf文件的最后有
    PHPIniDir C:\php5\
    也就是说,使用的是 C:\php5\下的php.ini,而很不幸的是我的机器上以前安装过PHP4,因此在系统目录(D:\WINNT\)下存在一个PHP4版本用的php.ini,似乎 Pake 去参照了这个php.ini里的设置来载入模块。
    解决办法是,备份系统目录下的php.ini然后删除它。


    解决上述问题,花了我超过两个小时,因此记录在这里,希望对其他碰到类似问题的开发者有所帮助。
    2007-12-01 19:58:48作者回复
    呵呵~~谢谢~~<br />个人的经历不同,发现的问题也是不同。在我的Debian上,是用的PHP5+Apache来搭建的,没有PHP版本混用的问题,所以还算是顺利。
    #lujianjian 发表于2007-12-01 16:02:55  IP: 218.242.184.*
    遇到的第2个问题,
    【通过CRUD测试数据访问】
    执行下面URL时
    http://askeet/question
    发生错误,404找不到页面。
    再看看
    在web(我的机器是 E:\work\ECSite\askeet\web)目录下
    并不存在 question这个目录,当然是会404.
    难道是教程有错误吗?
    教程也没有错,其实这句话完整的写法是
    http://askeet/index.php/question
    注意到教程第一天中有使用mode_rewrite来改写 /为 /index.php,那么如果按照教程来设置了mode_rewrite的话,http://askeet/question应该可以得到正确结果。可惜至今我不知道怎样在WINDOWS下设置mode_rewrite,因此没有按照教程做这一步,结果就是必须输入
    http://askeet/index.php/question
    或者
    http://askeet:82/frontend_dev.php/question
    来看到教程上的结果。


    2007-12-01 20:01:32作者回复
    嗯~~比较有同感~~我照着做的时候似乎也是这个样子~~<br />一直觉得这应是Apache配置的问题,可以Apache的配置又不是太懂得,一直想找个Apache配置的教程来看一下,不过一直没有看到合适的,Apache的文档又那么多,一下还找不到正确的地方。汗啊~~
    #lujianjian 发表于2007-12-01 16:11:58  IP: 218.242.184.*
    遇到了第3个问题
    http://askeet/frontend_dev.php/question
    发生错误
    [PropelException]
    No connection params set for [yml] propel
    说没有找到propel的设置,可是这些设置完全按照教程设置的。
    这时注意到错误信息是
    No connection params set for [yml] propel
    而不是
    No connection params set for propel
    那么这个[yml] propel是哪里来的呢,在【关系模型】部分,创建yml形式的 schema.yml时候,第1行就是
    [yml] propel: _attributes: { noXsd: false, defaultIdMethod: none, package: lib.model }
    这句话很奇怪的以[yml]开头,而不是<?yml 之类的tag定义。
    似乎[yml]是多余的。
    去掉试试看。
    1,去掉schema.yml开头的[yml]
    2, 重新执行
    $ symfony propel-generate-crud frontend question Question

    $ symfony cc frontend config
    3,再试试看
    http://askeet/frontend_dev.php/question

    结果,成功看到了 第一页面。

    2007-12-01 20:03:57作者回复
    呵呵~~关于这个文件的写法,开头的yml确实叫人搞不清楚,第一次照着来做的时候,发现也是这里出现问题,最后是自己试着改来改去的,才得到一个希望的结果。不过在这里并没有记下自己改错的经历。<br /><br />呵呵~~总之,还是很谢谢这位朋友~~
    #lujianjian 发表于2007-12-06 14:48:42  IP: 218.242.184.*
    我发现了
    http://www.watir.cn/?cat=5
    已经翻译了所有的24天教程。还有实践中遇到的问题,很有参考价值。
    博主可以考虑直接转载啊,就不用翻译了。

    2007-12-07 09:15:06作者回复
    呵呵~~谢谢~~去看下~~<br />不过有时觉得这也是强迫自己看点东西的一个办法~~呵呵~~谢谢~~
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © 萧易