summaryrefslogtreecommitdiff
path: root/demos/blog-tutorial/protected/pages/Day2
diff options
context:
space:
mode:
authorwei <>2007-05-10 23:00:04 +0000
committerwei <>2007-05-10 23:00:04 +0000
commite2cb0b52aaa02a3f3f41d0df377d189529713738 (patch)
treeee4c2a3fece40c9a2d4dde75f6e758f7ef05f8f6 /demos/blog-tutorial/protected/pages/Day2
parentef2fc3942664d4d7131542080e838f7754a3081f (diff)
Update blog tutorial
Diffstat (limited to 'demos/blog-tutorial/protected/pages/Day2')
-rw-r--r--demos/blog-tutorial/protected/pages/Day2/CreateAR.page105
-rw-r--r--demos/blog-tutorial/protected/pages/Day2/CreateDB.page11
-rw-r--r--demos/blog-tutorial/protected/pages/Day2/ER.gifbin5172 -> 4444 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Day2/ER.vsdbin73216 -> 73216 bytes
4 files changed, 93 insertions, 23 deletions
diff --git a/demos/blog-tutorial/protected/pages/Day2/CreateAR.page b/demos/blog-tutorial/protected/pages/Day2/CreateAR.page
index 00ac1166..c8684ee0 100644
--- a/demos/blog-tutorial/protected/pages/Day2/CreateAR.page
+++ b/demos/blog-tutorial/protected/pages/Day2/CreateAR.page
@@ -3,7 +3,7 @@
<h1>Creating Active Record Classes</h1>
<p>
-We need to create two <a href="http://www.pradosoft.com/demos/quickstart/?page=Database.ActiveRecord">Active Record</a> classes, <tt>UserRecord</tt> and <tt>PostRecord</tt>, to represent data records in the <tt>users</tt> and <tt>posts</tt> tables, respectively. Active Record classes must extend from the base class <tt>ActiveRecord</tt>, and their properties must match exactly to the fields of the corresponding tables.
+We need to create two <a href="http://www.pradosoft.com/demos/quickstart/?page=Database.ActiveRecord">Active Record</a> classes, <tt>UserRecord</tt> and <tt>PostRecord</tt>, to represent data records in the <tt>users</tt> and <tt>posts</tt> tables, respectively. Active Record classes must extend from the base class <tt>ActiveRecord</tt>, and must define property names that matches with the field names of the corresponding table.
</p>
<p>
@@ -11,9 +11,9 @@ To better organize our directories, we create a new directory <tt>protected/data
</p>
<com:TTextHighlighter CssClass="source" Language="xml">
- <paths>
- <using namespace="Application.database.*" />
- </paths>
+<paths>
+ <using namespace="Application.database.*" />
+</paths>
</com:TTextHighlighter>
<p>
@@ -24,7 +24,7 @@ Instead of writing the classes manually, we will use the <a href="http://www.pra
Under the <tt>blog</tt> directory, run the following command to enter into the interactive mode of the command line tool:
</p>
-<com:TTextHighlighter CssClass="source">
+<com:TTextHighlighter CssClass="source cli">
php path/to/prado-cli.php shell .
</com:TTextHighlighter>
@@ -32,7 +32,7 @@ php path/to/prado-cli.php shell .
We should see
</p>
-<com:TTextHighlighter CssClass="source" Language="text">
+<com:TTextHighlighter CssClass="source cli" Language="text">
Command line tools for Prado 3.1.0.
** Loaded PRADO appplication in directory "protected".
PHP-Shell - Version 0.3.1
@@ -47,7 +47,7 @@ PHP-Shell - Version 0.3.1
At the prompt, enter the following two commands to create <tt>UserRecord</tt> and <tt>PostRecord</tt> classes:
</p>
-<com:TTextHighlighter CssClass="source" Language="text">
+<com:TTextHighlighter CssClass="source cli" Language="text">
>> generate users Application.database.UserRecord
>> generate posts Application.database.PostRecord
@@ -70,17 +70,18 @@ If we check the <tt>PostRecord</tt> class file, we should see the following cont
<com:TTextHighlighter CssClass="source" Language="php">
class PostRecord extends TActiveRecord
{
- const TABLE='posts';
- public $post_id;
- public $author;
- public $create_time;
- public $title;
- public $content;
-
- public static function finder($className=__CLASS__)
- {
- return parent::finder($className);
- }
+ const TABLE='posts';
+ public $post_id;
+ public $author_id;
+ public $create_time;
+ public $title;
+ public $content;
+ public $status;
+
+ public static function finder($className=__CLASS__)
+ {
+ return parent::finder($className);
+ }
}
</com:TTextHighlighter>
@@ -92,17 +93,18 @@ As we see, for each field in the <tt>posts</tt> table, the class has a correspon
We can use the command line tool to do some testing with our newly created Active Record classes. Still in the interactive mode of the command line tool, we enter a PHP statement and should see the following. Interested readers may try some other PHP statements, such as <tt>UserRecord::finder()->findAll()</tt>.
</p>
-<com:TTextHighlighter CssClass="source" Language="text">
+<com:TTextHighlighter CssClass="source cli" Language="text">
>> PostRecord::finder()->findAll()
array
(
[0] => PostRecord#1
(
[post_id] => '1'
- [author] => 'admin'
+ [author_id] => 'admin'
[create_time] => '1175708482'
[title] => 'first post'
[content] => 'this is my first post'
+ [status] => '0'
[TActiveRecord:_readOnly] => false
[TActiveRecord:_connection] => null
[TComponent:_e] => array()
@@ -110,4 +112,67 @@ array
)
</com:TTextHighlighter>
+<h1>Relationship Between Posts and Users</h1>
+<p>
+Recall that there was a foreign key relationship between the <tt>users</tt> and <tt>posts</tt> table. The entity-relationship diagram is shown below for convienence.
+</p>
+
+<img src="<%~ ER.gif %>" class="output" />
+
+<p>
+From the entity-relationship diagram above, we see that the <tt>posts</tt> table contains a field named <tt>author_id</tt>. This <tt>author_id</tt> field is a foreign key to the reference table <tt>users</tt>. In particular, the values in the <tt>author_id</tt> field should be of that from the <tt>users</tt> table's <tt>username</tt> field. One of the consequence of this relationship, thinking in terms of objects, is that each "post" belongs to an "author" and one "author" may have many "posts".
+</p>
+
+<p>
+We can model the relationship between <tt>posts</tt> and <tt>users</tt> table in Active Record by modifying the <tt>PostRecord</tt> and <tt>UserRecord</tt> classes as follows.
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="php">
+class PostRecord extends TActiveRecord
+{
+ //... properties and methods as before
+
+ public $author; //holds an UserRecord
+
+ protected static $RELATIONS=array
+ (
+ 'author' => array(self::BELONGS_TO, 'UserRecord'),
+ );
+}
+</com:TTextHighlighter>
+
+<p>
+The static <tt>$RELATIONS</tt> property of <tt>PostRecord</tt> defines that the property <tt>$author</tt> belongs to an <tt>UserRecord</tt>. In <tt>array(self::BELONGS_TO, 'UserRecord')</tt>, the first element defines the relationship type, in this case <tt>self::BELONGS_TO</tt>. The second element is the name of related record, in this case an <tt>UserRecord</tt>. The <tt>UserRecord</tt> is defined similarly below, the difference is that, the user record has many <tt>PostRecord</tt>s.
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="php">
+class UserRecord extends TActiveRecord
+{
+ //... properties and methods as before
+
+ public $posts=array(); //holds an array of PostRecord
+
+ protected static $RELATIONS=array
+ (
+ 'posts' => array(self::HAS_MANY, 'PostRecord'),
+ );
+}
+</com:TTextHighlighter>
+
+<p>
+An array of <tt>UserRecord</tt> with and its corresponding posts may be fetched as follows.
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="php">
+$users = UserRecord::finder()->withPosts()->findAll();
+</com:TTextHighlighter>
+
+<com:TipBox>
+The method <tt>withXXX()</tt> (where XXX is the relationship property name, in this case, <tt>Posts</tt>) fetches the corresponding <tt>PostRecords</tt> using a second query (not by using a join). The <tt>withXXX()</tt> method accepts the same arguments as other finder methods of TActiveRecord, e.g. <tt>withPosts('status = ?', 0)</tt>.
+</com:TipBox>
+
+<p>
+Further detailed documentation can be found in the quickstart <a href="http://www.pradosoft.com/demos/quickstart/?page=Database.ActiveRecord">Active Record</a> docs.
+</p>
+
</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day2/CreateDB.page b/demos/blog-tutorial/protected/pages/Day2/CreateDB.page
index eebda4c1..de4e2436 100644
--- a/demos/blog-tutorial/protected/pages/Day2/CreateDB.page
+++ b/demos/blog-tutorial/protected/pages/Day2/CreateDB.page
@@ -30,9 +30,11 @@ CREATE TABLE users (
/* create posts table */
CREATE TABLE posts (
post_id INTEGER NOT NULL PRIMARY KEY,
- author VARCHAR(128) NOT NULL, /* references users.username */
+ author_id VARCHAR(128) NOT NULL
+ CONSTRAINT fk_author REFERENCES users(username),
create_time INTEGER NOT NULL, /* UNIX timestamp */
title VARCHAR(256) NOT NULL, /* title of the post */
+ content TEXT, /* post body */
status INTEGER NOT NULL /* 0: published; 1: draft; 2: pending; 2: denied */
);
@@ -43,14 +45,17 @@ INSERT INTO posts VALUES (NULL, 'admin', 1175708482, 'first post', 'this is my f
</com:TTextHighlighter>
<com:NoteBox>
-SQLite does not support <a href="http://www.sqlite.org/omitted.html">foreign key constraint</a>. Therefore, we will write PHP code to ensure that the <tt>posts.author</tt> field contains valid data. Also, we are exploiting the fact that the <tt>posts.post_id</tt> field is <a href="http://www.sqlite.org/autoinc.html">auto-incremental</a> if we assign NULL to it.
+SQLite does not support <a href="http://www.sqlite.org/omitted.html">foreign key constraint</a> such that
+the constraints can still be defined but will be ignored by SQLite.
+Therefore, we will write PHP code to ensure that the <tt>posts.author_id</tt> field contains valid data.
+Also, we are exploiting the fact that the <tt>posts.post_id</tt> field is <a href="http://www.sqlite.org/autoinc.html">auto-incremental</a> if we assign NULL to it.
</com:NoteBox>
<p>
We then use the <a href="http://www.sqlite.org/download.html">SQLite command line tool</a> to create the SQLite database. We create a directory <tt>protected/data</tt> to hold the SQLite database file. We now execute the following command under the directory <tt>protected/data</tt>:
</p>
-<com:TTextHighlighter CssClass="source">
+<com:TTextHighlighter CssClass="source cli">
sqlite3 blog.db < ../schema.sql
</com:TTextHighlighter>
diff --git a/demos/blog-tutorial/protected/pages/Day2/ER.gif b/demos/blog-tutorial/protected/pages/Day2/ER.gif
index 90e4c1ea..7a5397b3 100644
--- a/demos/blog-tutorial/protected/pages/Day2/ER.gif
+++ b/demos/blog-tutorial/protected/pages/Day2/ER.gif
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day2/ER.vsd b/demos/blog-tutorial/protected/pages/Day2/ER.vsd
index 95cf7f32..474833fd 100644
--- a/demos/blog-tutorial/protected/pages/Day2/ER.vsd
+++ b/demos/blog-tutorial/protected/pages/Day2/ER.vsd
Binary files differ