Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
377181a0
Commit
377181a0
authored
Nov 12, 2012
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
new AR WIP
parent
794df816
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
628 additions
and
80 deletions
+628
-80
ar.md
docs/internals/ar.md
+15
-0
database.md
docs/internals/database.md
+28
-0
model.md
docs/model.md
+178
-0
Model.php
framework/base/Model.php
+2
-2
ActiveMetaData.php
framework/db/ar/ActiveMetaData.php
+8
-11
ActiveQuery.php
framework/db/ar/ActiveQuery.php
+335
-1
ActiveRecord.php
framework/db/ar/ActiveRecord.php
+0
-0
Connection.php
framework/db/dao/Connection.php
+11
-0
Customer.php
tests/unit/data/ar/Customer.php
+10
-8
Item.php
tests/unit/data/ar/Item.php
+1
-8
Order.php
tests/unit/data/ar/Order.php
+21
-30
OrderItem.php
tests/unit/data/ar/OrderItem.php
+9
-10
ActiveRecordTest.php
tests/unit/framework/db/ar/ActiveRecordTest.php
+0
-0
QueryTest.php
tests/unit/framework/db/dao/QueryTest.php
+10
-10
No files found.
docs/internals/ar.md
View file @
377181a0
ActiveRecord
============
Query
-----
### Basic Queries
### Relational Queries
### Scopes
docs/internals/database.md
View file @
377181a0
Working with Database
=====================
Architecture
------------
### Data Access Object (DAO)
*
Connection
*
Command
*
DataReader
*
Transaction
### Schema
*
TableSchema
*
ColumnSchema
### Query Builder
*
Query
*
QueryBuilder
### ActiveRecord
*
ActiveRecord
*
ActiveQuery
\ No newline at end of file
docs/model.md
View file @
377181a0
Model
=====
Attributes
----------
Attributes store the actual data represented by a model and can
be accessed like object member variables. For example, a
`Post`
model
may contain a
`title`
attribute and a
`content`
attribute which may be
accessed as follows,
~~~
php
$post
->
title
=
'Hello, world'
;
$post
->
content
=
'Something interesting is happening'
;
echo
$post
->
title
;
echo
$post
->
content
;
~~~
A model should list all its available attributes in the
`attributes()`
method.
Attributes may be implemented in various ways. The
[
[\yii\base\Model
]
] class
implements attributes as public member variables of the class, while the
[
[\yii\db\ar\ActiveRecord
]
] class implements them as DB table columns. For example,
~~~
php
// LoginForm has two attributes: username and password
class
LoginForm
extends
\yii\base\Model
{
public
$username
;
public
$password
;
}
// Post is associated with the tbl_post DB table.
// Its attributes correspond to the columns in tbl_post
class
Post
extends
\yii\db\ar\ActiveRecord
{
public
function
table
()
{
return
'tbl_post'
;
}
}
~~~
### Attribute Labels
Scenarios
---------
A model may be used in different scenarios. For example, a
`User`
model may be
used to collect user login inputs, and it may also be used for user registration
purpose. For this reason, each model has a property named
`scenario`
which stores
the name of the scenario that the model is currently being used. As we will explain
in the next few sections, the concept of scenario is mainly used in validation and
massive attribute assignment.
Associated with each scenario is a list of attributes that are
*active*
in that
particular scenario. For example, in the
`login`
scenario, only the
`username`
and
`password`
attributes are active; while in the
`register`
scenario,
additional attributes such as
`email`
are
*active*
.
Possible scenarios should be listed in the
`scenarios()`
method which returns an array
whose keys are the scenario names and whose values are the corresponding
active attribute lists. Below is an example:
~~~
php
class
User
extends
\yii\db\ar\ActiveRecord
{
public
function
table
()
{
return
'tbl_user'
;
}
public
function
scenarios
()
{
return
array
(
'login'
=>
array
(
'username'
,
'password'
),
'register'
=>
array
(
'username'
,
'email'
,
'password'
),
);
}
}
~~~
Sometimes, we want to mark that an attribute is not safe for massive assignment
(but we still want it to be validated). We may do so by prefixing an exclamation
character to the attribute name when declaring it in
`scenarios()`
. For example,
~~~
php
array
(
'username'
,
'password'
,
'!secret'
)
~~~
Validation
----------
When a model is used to collect user input data via its attributes,
it usually needs to validate the affected attributes to make sure they
satisfy certain requirements, such as an attribute cannot be empty,
an attribute must contain letters only, etc. If errors are found in
validation, they may be presented to the user to help him fix the errors.
The following example shows how the validation is performed:
~~~
php
$model
=
new
LoginForm
;
$model
->
username
=
$_POST
[
'username'
];
$model
->
password
=
$_POST
[
'password'
];
if
(
$model
->
validate
())
{
// ...login the user...
}
else
{
$errors
=
$model
->
getErrors
();
// ...display the errors to the end user...
}
~~~
The possible validation rules for a model should be listed in its
`rules()`
method. Each validation rule applies to one or several attributes
and is effective in one or several scenarios. A rule can be specified
using a validator object - an instance of a
[
[\yii\validators\Validator
]
]
child class, or an array with the following format:
~~~
php
array
(
'attribute1, attribute2, ...'
,
'validator class or alias'
,
// specifies in which scenario(s) this rule is active.
// if not given, it means it is active in all scenarios
'on'
=>
'scenario1, scenario2, ...'
,
// the following name-value pairs will be used
// to initialize the validator properties...
'name1'
=>
'value1'
,
'name2'
=>
'value2'
,
....
)
~~~
When
`validate()`
is called, the actual validation rules executed are
determined using both of the following criteria:
*
the rules must be associated with at least one active attribute;
*
the rules must be active for the current scenario.
### Active Attributes
An attribute is
*active*
if it is subject to some validations in the current scenario.
### Safe Attributes
An attribute is
*safe*
if it can be massively assigned in the current scenario.
Massive Access of Attributes
----------------------------
Massive Attribute Retrieval
---------------------------
Attributes can be massively retrieved via the
`attributes`
property.
The following code will return
*all*
attributes in the
`$post`
model
as an array of name-value pairs.
~~~
php
$attributes
=
$post
->
attributes
;
var_dump
(
$attributes
);
~~~
Massive Attribute Assignment
----------------------------
Safe Attributes
---------------
Safe attributes are those that can be massively assigned. For example,
Validation rules and mass assignment
------------------------------------
...
...
framework/base/Model.php
View file @
377181a0
...
...
@@ -586,7 +586,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
// use validators to determine active attributes
$attributes
=
array
();
foreach
(
$this
->
attributes
()
as
$attribute
)
{
if
(
$this
->
getActiveValidators
(
$attribue
)
!==
array
())
{
if
(
$this
->
getActiveValidators
(
$attribu
t
e
)
!==
array
())
{
$attributes
[]
=
$attribute
;
}
}
...
...
@@ -614,7 +614,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
*/
public
function
offsetExists
(
$offset
)
{
return
property_exists
(
$this
,
$offset
)
&&
$this
->
$offset
!==
null
;
return
$this
->
$offset
!==
null
;
}
/**
...
...
framework/db/ar/ActiveMetaData.php
View file @
377181a0
...
...
@@ -26,9 +26,9 @@ class ActiveMetaData
*/
public
$modelClass
;
/**
* @var
array list of relation
s
* @var
ActiveRecord the model instance that can be used to access non-static method
s
*/
public
$
relations
=
array
()
;
public
$
model
;
/**
* Returns an instance of ActiveMetaData for the specified model class.
...
...
@@ -55,21 +55,18 @@ class ActiveMetaData
public
function
__construct
(
$modelClass
)
{
$this
->
modelClass
=
$modelClass
;
$tableName
=
$modelClass
::
tableName
();
$this
->
table
=
$modelClass
::
getDbConnection
()
->
getDriver
()
->
getTableSchema
(
$tableName
);
$this
->
model
=
new
$modelClass
;
$tableName
=
$this
->
model
->
tableName
();
$this
->
table
=
$this
->
model
->
getDbConnection
()
->
getDriver
()
->
getTableSchema
(
$tableName
);
if
(
$this
->
table
===
null
)
{
throw
new
Exception
(
"Unable to find table '
$tableName
' for ActiveRecord class '
$modelClass
'."
);
}
$primaryKey
=
$
modelClass
::
primaryKey
();
if
(
$primaryKey
!==
null
)
{
$primaryKey
=
$
this
->
model
->
primaryKey
();
if
(
$primaryKey
!==
$this
->
table
->
primaryKey
)
{
$this
->
table
->
fixPrimaryKey
(
$primaryKey
);
}
elseif
(
$
this
->
table
->
primaryKey
===
null
)
{
}
elseif
(
$primaryKey
===
null
)
{
throw
new
Exception
(
"The table '
$tableName
' for ActiveRecord class '
$modelClass
' does not have a primary key."
);
}
foreach
(
$modelClass
::
relations
()
as
$name
=>
$config
)
{
$this
->
addRelation
(
$name
,
$config
);
}
}
/**
...
...
framework/db/ar/ActiveQuery.php
View file @
377181a0
This diff is collapsed.
Click to expand it.
framework/db/ar/ActiveRecord.php
View file @
377181a0
This diff is collapsed.
Click to expand it.
framework/db/dao/Connection.php
View file @
377181a0
...
...
@@ -461,6 +461,17 @@ class Connection extends \yii\base\ApplicationComponent
}
/**
* Obtains the metadata for the named table.
* @param string $name table name. The table name may contain schema name if any. Do not quote the table name.
* @param boolean $refresh whether to reload the table schema even if it is found in the cache.
* @return TableSchema table metadata. Null if the named table does not exist.
*/
public
function
getTableSchema
(
$name
,
$refresh
=
false
)
{
return
$this
->
getDriver
()
->
getTableSchema
(
$name
,
$refresh
);
}
/**
* Returns the ID of the last inserted row or sequence value.
* @param string $sequenceName name of the sequence object (required by some DBMS)
* @return string the row ID of the last row inserted, or the last value retrieved from the sequence object
...
...
tests/unit/data/ar/Customer.php
View file @
377181a0
<?php
namespace
yiiunit\data\ar
;
use
yii\db\ar\ActiveQuery
;
class
Customer
extends
ActiveRecord
{
const
STATUS_ACTIVE
=
1
;
const
STATUS_INACTIVE
=
2
;
public
static
function
tableName
()
public
function
tableName
()
{
return
'tbl_customer'
;
}
public
static
function
relation
s
()
public
function
order
s
()
{
return
array
(
'orders:Order[]'
=>
array
(
'link'
=>
array
(
'customer_id'
=>
'id'
),
),
);
return
$this
->
hasMany
(
'Order'
,
array
(
'customer_id'
=>
'id'
));
}
/**
* @param ActiveQuery $query
* @return ActiveQuery
*/
public
function
active
(
$query
)
{
return
$query
->
andWhere
(
'
@.
`status` = '
.
self
::
STATUS_ACTIVE
);
return
$query
->
andWhere
(
'`status` = '
.
self
::
STATUS_ACTIVE
);
}
}
\ No newline at end of file
tests/unit/data/ar/Item.php
View file @
377181a0
...
...
@@ -4,14 +4,8 @@ namespace yiiunit\data\ar;
class
Item
extends
ActiveRecord
{
public
static
function
tableName
()
public
function
tableName
()
{
return
'tbl_item'
;
}
public
static
function
relations
()
{
return
array
(
);
}
}
\ No newline at end of file
tests/unit/data/ar/Order.php
View file @
377181a0
...
...
@@ -4,40 +4,30 @@ namespace yiiunit\data\ar;
class
Order
extends
ActiveRecord
{
public
static
function
tableName
()
public
function
tableName
()
{
return
'tbl_order'
;
}
public
static
function
relations
()
public
function
customer
()
{
return
array
(
'customer:Customer'
=>
array
(
'link'
=>
array
(
'id'
=>
'customer_id'
),
),
'orderItems:OrderItem'
=>
array
(
'link'
=>
array
(
'order_id'
=>
'id'
),
),
'items:Item[]'
=>
array
(
'via'
=>
'orderItems'
,
'link'
=>
array
(
'id'
=>
'item_id'
,
),
'order'
=>
'@.id'
,
),
'books:Item[]'
=>
array
(
'joinType'
=>
'INNER JOIN'
,
'via'
=>
array
(
'table'
=>
'tbl_order_item'
,
'link'
=>
array
(
'order_id'
=>
'id'
,
),
),
'link'
=>
array
(
'id'
=>
'item_id'
,
),
'on'
=>
'@.category_id = 1'
,
),
);
return
$this
->
hasOne
(
'Customer'
,
array
(
'id'
=>
'customer_id'
));
}
public
function
orderItems
()
{
return
$this
->
hasMany
(
'OrderItem'
,
array
(
'order_id'
=>
'id'
));
}
public
function
items
()
{
return
$this
->
hasMany
(
'Item'
,
array
(
'id'
=>
'item_id'
))
->
via
(
'orderItems'
)
->
orderBy
(
'id'
);
}
public
function
books
()
{
return
$this
->
manyMany
(
'Item'
,
array
(
'id'
=>
'item_id'
),
'tbl_order_item'
,
array
(
'item_id'
,
'id'
))
->
where
(
'category_id = 1'
);
}
}
\ No newline at end of file
tests/unit/data/ar/OrderItem.php
View file @
377181a0
...
...
@@ -4,20 +4,18 @@ namespace yiiunit\data\ar;
class
OrderItem
extends
ActiveRecord
{
public
static
function
tableName
()
public
function
tableName
()
{
return
'tbl_order_item'
;
}
public
static
function
relations
()
public
function
order
()
{
return
array
(
'order:Order'
=>
array
(
'link'
=>
array
(
'order_id'
=>
'id'
),
),
'item:Item'
=>
array
(
'link'
=>
array
(
'item_id'
=>
'id'
),
),
);
return
$this
->
hasOne
(
'Order'
,
array
(
'id'
=>
'order_id'
));
}
public
function
item
()
{
return
$this
->
hasOne
(
'Item'
,
array
(
'id'
=>
'item_id'
));
}
}
\ No newline at end of file
tests/unit/framework/db/ar/ActiveRecordTest.php
View file @
377181a0
This diff is collapsed.
Click to expand it.
tests/unit/framework/db/dao/QueryTest.php
View file @
377181a0
...
...
@@ -56,14 +56,14 @@ class QueryTest extends \yiiunit\MysqlTestCase
function
testGroup
()
{
$query
=
new
Query
;
$query
->
group
(
'team'
);
$this
->
assertEquals
(
'team'
,
$query
->
group
);
$query
->
group
By
(
'team'
);
$this
->
assertEquals
(
'team'
,
$query
->
group
By
);
$query
->
addGroup
(
'company'
);
$this
->
assertEquals
(
array
(
'team'
,
'company'
),
$query
->
group
);
$this
->
assertEquals
(
array
(
'team'
,
'company'
),
$query
->
group
By
);
$query
->
addGroup
(
'age'
);
$this
->
assertEquals
(
array
(
'team'
,
'company'
,
'age'
),
$query
->
group
);
$this
->
assertEquals
(
array
(
'team'
,
'company'
,
'age'
),
$query
->
group
By
);
}
function
testHaving
()
...
...
@@ -85,14 +85,14 @@ class QueryTest extends \yiiunit\MysqlTestCase
function
testOrder
()
{
$query
=
new
Query
;
$query
->
order
(
'team'
);
$this
->
assertEquals
(
'team'
,
$query
->
order
);
$query
->
order
By
(
'team'
);
$this
->
assertEquals
(
'team'
,
$query
->
order
By
);
$query
->
addOrder
(
'company'
);
$this
->
assertEquals
(
array
(
'team'
,
'company'
),
$query
->
order
);
$query
->
addOrder
By
(
'company'
);
$this
->
assertEquals
(
array
(
'team'
,
'company'
),
$query
->
order
By
);
$query
->
addOrder
(
'age'
);
$this
->
assertEquals
(
array
(
'team'
,
'company'
,
'age'
),
$query
->
order
);
$query
->
addOrder
By
(
'age'
);
$this
->
assertEquals
(
array
(
'team'
,
'company'
,
'age'
),
$query
->
order
By
);
}
function
testLimitOffset
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment