第二天--设置一个数据模型
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代码,而我们已经有了一个可用的基本程序。这对于第二天并不坏。明天,我们将会编写一些代码来创建一个来显示问题列表的欢迎首页。我们也可以使用一个处理操作来向我们的数据库添加数据,并且学习如何扩展模块。
相关推荐
在构建“第二天-在线点餐淘宝风格”的项目中,我们可以看到 ASP 技术的应用,这表明这个系统可能是基于 ASP(Active Server Pages)开发的。ASP 是微软推出的一种服务器端脚本环境,主要用于创建动态交互式网页。在...
根据LSTM层的需求,输入的数据应该为 [送入样本数, 循环核时间展开步数, 每个时间步输入特征个数] ,循环核时间展开步数我在代码中设计为使用前30天的数据,预测出第31天的数据,以此类推,每个时间步的输入特征个...
在“华清远见作业第二十七天-网络编程(第二天)”的主题中,我们主要探讨的是在网络编程领域的相关知识,特别是与机械臂模拟相关的编程实践。网络编程是计算机科学中的一个重要分支,它涉及到如何通过网络在不同的...
本篇将基于“学习Hibernate第二天”的主题,结合“源码”和“工具”这两个标签,深入探讨Hibernate的一对一主键关联双向映射,以及如何在实际开发中利用这一特性。 在Java对象关系映射(ORM)框架中,数据模型通常...
在本课程的"spring5mvc第二天【大纲笔记】"中,我们将深入探讨 Spring MVC 的核心概念和关键功能,包括响应数据和结果视图的处理、文件上传、异常处理以及拦截器的使用。以下是对这些主题的详细解释: 1. 响应数据...
- **起源与演变:** 数据仓库作为一个专门用于数据分析的数据库,最早出现于20世纪80年代末,由比尔·恩门提出。 - **未来趋势:** 随着大数据、云计算以及人工智能技术的发展,未来的数据仓库将更加智能化、自动化...
标题和描述中提到的是“传智黑马赵星老师hadoop七天课程资料笔记-第二天(全)”,这表明这是一个关于Hadoop技术的深度学习资源,主要聚焦于赵星老师的Hadoop教学课程中的第二天内容。通常,这样的课程会涵盖Hadoop的...
### 数据模型分析 - **表结构分析**: - 用户表`user`:存储用户基本信息。 - 订单表`orders`:记录用户创建的所有订单信息。 - 订单明细表`orderdetail`:记录订单中每项商品的具体信息。 - 商品表`items`:...
总的来说,这个压缩包为玩家提供了一个深入了解《第二银河》舰船设计和战术运用的机会,同时也展示了游戏与3D技术的结合,为玩家带来更丰富的游戏体验。无论是从游戏策略还是艺术创作的角度,这些模型都是宝贵的资源...
#### 九、订单商品数据模型分析 - **用户表 (user)**:存储购买商品的用户信息。 - **订单表 (orders)**:记录用户创建的所有订单。 - **订单明细表 (orderdetail)**:记录每个订单中的商品详情。 - **商品表 ...
特征选择是基于数据挖掘的短期负荷预测方法的第二步骤,目的是选择最相关的特征来建立预测模型。 6. 模型建立 模型建立是基于数据挖掘的短期负荷预测方法的第三步骤,包括使用决策树、神经网络等算法来建立预测模型...
在第二天的教程中,重点是实现Employee类的MVC逻辑,这对于理解模型-视图-控制器(MVC)架构至关重要。 模型(Model)是应用的核心,它封装了业务逻辑和数据。Employee类在这里就是模型,可能包含了员工的相关属性...
"iOS开发 - 第02篇 - UI进阶 - 15 - 彩票(第二天)"是这个系列教程的第二部分,主要探讨了如何在iOS平台上构建一个具有吸引力和交互性的彩票应用界面。 首先,我们要了解iOS中的用户界面框架UIKit,它是构建iOS应用...
在第二天的课程中,你可能会了解如何初始化Vue实例,配置选项,以及如何使用`new Vue()`来创建一个实例。 2. **模板语法**:Vue的模板语法允许我们在HTML中直接编写声明式的代码,将数据和DOM元素关联起来。这包括...
第二种是利用远期利率预测未来的无风险利率和股权成本,这种方法考虑了利率期限结构的影响;第三种是采用长期国债利率,基于长期国债计算市场风险溢价。这三种方法在利率稳定且β值接近1时可能得出相似结果,但在...
在“spring培训第二天”的课程中,我们深入学习了Spring框架的核心概念和关键功能。作为一款广泛应用的Java企业级开发框架,Spring以其强大的依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented ...
在深入探讨Hibernate学习笔记第二天的源码之前,我们先来理解一下Hibernate的核心概念。Hibernate是一个开源的对象关系映射(ORM)框架,它允许Java开发者将数据库操作转化为对象模型,大大简化了数据访问层的开发...
该数据集提供了 2024 年和 2025 年期间从美国 20 个主要城市收集的综合天气数据。它包含各种天气属性,这些属性对于预测第二...目标要素 “Rain Tomorrow” 是一个二进制标签(1 = 是,0 = 否),指示第二天是否下雨。