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
c5cdcab6
Commit
c5cdcab6
authored
Feb 06, 2012
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
...
parent
da4b7afe
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
243 additions
and
144 deletions
+243
-144
ActiveMetaData.php
framework/db/ar/ActiveMetaData.php
+13
-2
ActiveQuery.php
framework/db/ar/ActiveQuery.php
+79
-17
ActiveRecord.php
framework/db/ar/ActiveRecord.php
+52
-95
JoinElement.php
framework/db/ar/JoinElement.php
+65
-28
QueryBuilder.php
framework/db/dao/QueryBuilder.php
+1
-1
Customer.php
tests/unit/data/ar/Customer.php
+10
-0
Order.php
tests/unit/data/ar/Order.php
+10
-0
mysql.sql
tests/unit/data/mysql.sql
+1
-1
ActiveRecordTest.php
tests/unit/framework/db/ar/ActiveRecordTest.php
+12
-0
No files found.
framework/db/ar/ActiveMetaData.php
View file @
c5cdcab6
...
...
@@ -18,6 +18,10 @@ class ActiveMetaData
*/
public
$table
;
/**
* @var string the model class name
*/
public
$modelClass
;
/**
* @var array list of relations
*/
public
$relations
=
array
();
...
...
@@ -30,6 +34,7 @@ class ActiveMetaData
{
$tableName
=
$modelClass
::
tableName
();
$this
->
table
=
$modelClass
::
getDbConnection
()
->
getDriver
()
->
getTableSchema
(
$tableName
);
$this
->
modelClass
=
$modelClass
;
if
(
$this
->
table
===
null
)
{
throw
new
Exception
(
"Unable to find table '
$tableName
' for ActiveRecord class '
$modelClass
'."
);
}
...
...
@@ -64,11 +69,16 @@ class ActiveMetaData
}
$relation
=
ActiveRelation
::
newInstance
(
$config
);
$relation
->
name
=
$matches
[
1
];
$relation
->
modelClass
=
'\\'
.
$matches
[
2
];
$modelClass
=
$matches
[
2
];
if
(
strpos
(
$modelClass
,
'\\'
)
!==
false
)
{
$relation
->
modelClass
=
'\\'
.
ltrim
(
$modelClass
,
'\\'
);
}
else
{
$relation
->
modelClass
=
dirname
(
$this
->
modelClass
)
.
'\\'
.
$modelClass
;
}
$relation
->
hasMany
=
isset
(
$matches
[
3
]);
$this
->
relations
[
$relation
->
name
]
=
$relation
;
}
else
{
throw
new
Exception
(
"
Relation name in bad format
:
$name
"
);
throw
new
Exception
(
"
{
$this
->
modelClass
}
has an invalid relation
:
$name
"
);
}
}
}
\ No newline at end of file
framework/db/ar/ActiveQuery.php
View file @
c5cdcab6
...
...
@@ -18,6 +18,18 @@ use yii\db\Exception;
* ActiveFinder.php is ...
* todo: add SQL monitor
*
* todo: add ActiveQueryBuilder
* todo: quote join/on part of the relational query
* todo: modify QueryBuilder about join() methods
* todo: unify ActiveQuery and ActiveRelation in query building process
* todo: intelligent table aliasing (first table name, then relation name, finally t?)
* todo: allow using tokens in primary query fragments
* todo: findBySql
* todo: base limited
* todo: lazy loading
* todo: scope
* todo: test via option
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
...
...
@@ -692,7 +704,7 @@ class ActiveQuery extends \yii\base\Object implements \IteratorAggregate, \Array
{
if
(
!
empty
(
$this
->
with
))
{
// todo: handle findBySql() and limit cases
$
this
->
init
RelationalQuery
();
$
joinTree
=
$this
->
build
RelationalQuery
();
}
if
(
$this
->
sql
===
null
)
{
...
...
@@ -703,9 +715,16 @@ class ActiveQuery extends \yii\base\Object implements \IteratorAggregate, \Array
$command
=
$this
->
getDbConnection
()
->
createCommand
(
$this
->
sql
);
$command
->
bindValues
(
$this
->
query
->
params
);
}
echo
$command
->
sql
;
$rows
=
$command
->
queryAll
();
if
(
!
empty
(
$this
->
with
))
{
foreach
(
$rows
as
$row
)
{
$joinTree
->
populateData
(
$row
);
}
return
array_values
(
$joinTree
->
records
);
}
if
(
$this
->
asArray
)
{
if
(
$this
->
indexBy
===
null
)
{
return
$rows
;
...
...
@@ -759,45 +778,76 @@ class ActiveQuery extends \yii\base\Object implements \IteratorAggregate, \Array
}
}
protected
function
init
RelationalQuery
()
protected
function
build
RelationalQuery
()
{
$joinTree
=
new
JoinElement
(
null
,
null
);
$
joinCount
=
0
;
$this
->
build
JoinTree
(
$joinTree
,
$this
->
with
,
$joinCount
);
$joinTree
=
new
JoinElement
(
$this
,
null
,
null
);
$
this
->
buildJoinTree
(
$joinTree
,
$this
->
with
)
;
$this
->
build
TableAlias
(
$joinTree
);
$query
=
new
Query
;
foreach
(
$joinTree
->
children
as
$child
)
{
$child
->
buildQuery
(
$query
);
}
$select
=
$joinTree
->
buildSelect
(
$this
->
query
->
select
);
if
(
!
empty
(
$query
->
select
))
{
$this
->
query
->
select
=
array_merge
(
$select
,
$query
->
select
);
}
else
{
$this
->
query
->
select
=
$select
;
}
if
(
!
empty
(
$query
->
where
))
{
$this
->
query
->
andWhere
(
'('
.
implode
(
') AND ('
,
$query
->
where
)
.
')'
);
}
if
(
!
empty
(
$query
->
having
))
{
$this
->
query
->
andHaving
(
'('
.
implode
(
') AND ('
,
$query
->
having
)
.
')'
);
}
if
(
!
empty
(
$query
->
join
))
{
if
(
$this
->
query
->
join
===
null
)
{
$this
->
query
->
join
=
$query
->
join
;
}
else
{
$this
->
query
->
join
=
array_merge
(
$this
->
query
->
join
,
$query
->
join
);
}
}
if
(
!
empty
(
$query
->
orderBy
))
{
$this
->
query
->
addOrderBy
(
$query
->
orderBy
);
}
if
(
!
empty
(
$query
->
groupBy
))
{
$this
->
query
->
addGroupBy
(
$query
->
groupBy
);
}
if
(
!
empty
(
$query
->
params
))
{
$this
->
query
->
addParams
(
$query
->
params
);
}
return
$joinTree
;
}
/**
* @param JoinElement $parent
* @param array|string $with
* @param integer $joinCount
* @param array $config
* @return null|JoinElement
* @throws \yii\db\Exception
*/
protected
function
buildJoinTree
(
$parent
,
$with
,
&
$joinCount
,
$config
=
array
())
protected
function
buildJoinTree
(
$parent
,
$with
,
$config
=
array
())
{
if
(
is_array
(
$with
))
{
foreach
(
$with
as
$name
=>
$value
)
{
if
(
is_string
(
$value
))
{
$this
->
buildJoinTree
(
$parent
,
$value
,
$joinCount
);
$this
->
buildJoinTree
(
$parent
,
$value
);
}
elseif
(
is_string
(
$name
)
&&
is_array
(
$value
))
{
$this
->
buildJoinTree
(
$parent
,
$name
,
$
joinCount
,
$
value
);
$this
->
buildJoinTree
(
$parent
,
$name
,
$value
);
}
}
return
null
;
}
if
((
$pos
=
strrpos
(
$with
,
'.'
))
!==
false
)
{
$parent
=
$this
->
buildJoinTree
(
$parent
,
substr
(
$with
,
0
,
$pos
)
,
$joinCount
);
$parent
=
$this
->
buildJoinTree
(
$parent
,
substr
(
$with
,
0
,
$pos
));
$with
=
substr
(
$with
,
$pos
+
1
);
}
if
(
isset
(
$parent
->
children
[
$with
]))
{
$child
=
$parent
->
children
[
$with
];
$child
->
joinOnly
=
false
;
}
else
{
$modelClass
=
$parent
->
relation
->
modelClass
;
$relations
=
$modelClass
::
getMetaData
()
->
relations
;
...
...
@@ -805,20 +855,32 @@ class ActiveQuery extends \yii\base\Object implements \IteratorAggregate, \Array
throw
new
Exception
(
"
$modelClass
has no relation named '
$with
'."
);
}
$relation
=
clone
$relations
[
$with
];
if
(
$relation
->
tableAlias
===
null
)
{
$relation
->
tableAlias
=
't'
.
(
$joinCount
++
);
if
(
$relation
->
via
!==
null
&&
isset
(
$relations
[
$relation
->
via
]))
{
$relation
->
via
=
null
;
$parent2
=
$this
->
buildJoinTree
(
$parent
,
$relation
->
via
);
if
(
$parent2
->
joinOnly
===
null
)
{
$parent2
->
joinOnly
=
true
;
}
$child
=
new
JoinElement
(
$relation
,
$parent2
,
$parent
);
}
else
{
$child
=
new
JoinElement
(
$relation
,
$parent
,
$parent
);
}
$child
=
new
JoinElement
(
$parent
,
$relation
);
}
foreach
(
$config
as
$name
=>
$value
)
{
$child
->
relation
->
$name
=
$value
;
}
if
(
!
empty
(
$child
->
relation
->
with
))
{
$this
->
buildJoinTree
(
$child
,
$child
->
relation
->
with
,
$joinCount
);
return
$child
;
}
return
$child
;
protected
function
buildTableAlias
(
$element
,
&
$count
=
0
)
{
if
(
$element
->
relation
->
tableAlias
===
null
)
{
$element
->
relation
->
tableAlias
=
't'
.
(
$count
++
);
}
foreach
(
$element
->
children
as
$child
)
{
$this
->
buildTableAlias
(
$child
,
$count
);
}
}
}
framework/db/ar/ActiveRecord.php
View file @
c5cdcab6
...
...
@@ -373,21 +373,13 @@ abstract class ActiveRecord extends \yii\base\Model
{
if
(
isset
(
$this
->
_attributes
[
$name
]))
{
return
true
;
}
elseif
(
isset
(
$this
->
getMetaData
()
->
columns
[
$name
]))
{
}
elseif
(
isset
(
$this
->
getMetaData
()
->
columns
[
$name
]))
{
return
false
;
}
elseif
(
isset
(
$this
->
_related
[
$name
]))
{
}
elseif
(
isset
(
$this
->
_related
[
$name
]))
{
return
true
;
}
elseif
(
isset
(
$this
->
getMetaData
()
->
relations
[
$name
]))
{
}
elseif
(
isset
(
$this
->
getMetaData
()
->
relations
[
$name
]))
{
return
$this
->
getRelatedRecord
(
$name
)
!==
null
;
}
else
{
}
else
{
return
parent
::
__isset
(
$name
);
}
}
...
...
@@ -402,13 +394,9 @@ abstract class ActiveRecord extends \yii\base\Model
{
if
(
isset
(
$this
->
getMetaData
()
->
columns
[
$name
]))
{
unset
(
$this
->
_attributes
[
$name
]);
}
elseif
(
isset
(
$this
->
getMetaData
()
->
relations
[
$name
]))
{
}
elseif
(
isset
(
$this
->
getMetaData
()
->
relations
[
$name
]))
{
unset
(
$this
->
_related
[
$name
]);
}
else
{
}
else
{
parent
::
__unset
(
$name
);
}
}
...
...
@@ -426,9 +414,7 @@ abstract class ActiveRecord extends \yii\base\Model
if
(
isset
(
$this
->
getMetaData
()
->
relations
[
$name
]))
{
if
(
empty
(
$parameters
))
{
return
$this
->
getRelatedRecord
(
$name
,
false
);
}
else
{
}
else
{
return
$this
->
getRelatedRecord
(
$name
,
false
,
$parameters
[
0
]);
}
}
...
...
@@ -442,6 +428,20 @@ abstract class ActiveRecord extends \yii\base\Model
return
parent
::
__call
(
$name
,
$parameters
);
}
public
function
initRelatedRecord
(
$relation
)
{
$this
->
_related
[
$relation
->
name
]
=
$relation
->
hasMany
?
array
()
:
null
;
}
public
function
addRelatedRecord
(
$relation
,
$record
)
{
if
(
$relation
->
hasMany
)
{
$this
->
_related
[
$relation
->
name
][]
=
$record
;
}
else
{
$this
->
_related
[
$relation
->
name
]
=
$record
;
}
}
/**
* Returns the related record(s).
* This method will return the related record(s) of the current record.
...
...
@@ -464,8 +464,7 @@ abstract class ActiveRecord extends \yii\base\Model
$md
=
$this
->
getMetaData
();
if
(
!
isset
(
$md
->
relations
[
$name
]))
{
throw
new
Exception
(
Yii
::
t
(
'yii'
,
'{class} does not have relation "{name}".'
,
array
(
'{class}'
=>
get_class
(
$this
),
'{name}'
=>
$name
)));
throw
new
Exception
(
Yii
::
t
(
'yii'
,
'{class} does not have relation "{name}".'
,
array
(
'{class}'
=>
get_class
(
$this
),
'{name}'
=>
$name
)));
}
Yii
::
trace
(
'lazy loading '
.
get_class
(
$this
)
.
'.'
.
$name
,
'system.db.ar.ActiveRecord'
);
...
...
@@ -481,8 +480,7 @@ abstract class ActiveRecord extends \yii\base\Model
$save
=
$this
->
_related
[
$name
];
}
$r
=
array
(
$name
=>
$params
);
}
else
{
}
else
{
$r
=
$name
;
}
unset
(
$this
->
_related
[
$name
]);
...
...
@@ -493,13 +491,9 @@ abstract class ActiveRecord extends \yii\base\Model
if
(
!
isset
(
$this
->
_related
[
$name
]))
{
if
(
$relation
instanceof
CHasManyRelation
)
{
$this
->
_related
[
$name
]
=
array
();
}
elseif
(
$relation
instanceof
CStatRelation
)
{
}
elseif
(
$relation
instanceof
CStatRelation
)
{
$this
->
_related
[
$name
]
=
$relation
->
defaultValue
;
}
else
{
}
else
{
$this
->
_related
[
$name
]
=
null
;
}
}
...
...
@@ -508,14 +502,11 @@ abstract class ActiveRecord extends \yii\base\Model
$results
=
$this
->
_related
[
$name
];
if
(
$exists
)
{
$this
->
_related
[
$name
]
=
$save
;
}
else
{
}
else
{
unset
(
$this
->
_related
[
$name
]);
}
return
$results
;
}
else
{
}
else
{
return
$this
->
_related
[
$name
];
}
}
...
...
@@ -617,9 +608,7 @@ abstract class ActiveRecord extends \yii\base\Model
{
if
(
property_exists
(
$this
,
$name
))
{
return
$this
->
$name
;
}
elseif
(
isset
(
$this
->
_attributes
[
$name
]))
{
}
elseif
(
isset
(
$this
->
_attributes
[
$name
]))
{
return
$this
->
_attributes
[
$name
];
}
}
...
...
@@ -636,13 +625,9 @@ abstract class ActiveRecord extends \yii\base\Model
{
if
(
property_exists
(
$this
,
$name
))
{
$this
->
$name
=
$value
;
}
elseif
(
isset
(
$this
->
getMetaData
()
->
table
->
columns
[
$name
]))
{
}
elseif
(
isset
(
$this
->
getMetaData
()
->
table
->
columns
[
$name
]))
{
$this
->
_attributes
[
$name
]
=
$value
;
}
else
{
}
else
{
return
false
;
}
return
true
;
...
...
@@ -660,31 +645,24 @@ abstract class ActiveRecord extends \yii\base\Model
public
function
getAttributes
(
$names
=
true
)
{
$attributes
=
$this
->
_attributes
;
foreach
(
$this
->
getMetaData
()
->
columns
as
$name
=>
$column
)
{
foreach
(
$this
->
getMetaData
()
->
columns
as
$name
=>
$column
)
{
if
(
property_exists
(
$this
,
$name
))
{
$attributes
[
$name
]
=
$this
->
$name
;
}
elseif
(
$names
===
true
&&
!
isset
(
$attributes
[
$name
]))
{
}
elseif
(
$names
===
true
&&
!
isset
(
$attributes
[
$name
]))
{
$attributes
[
$name
]
=
null
;
}
}
if
(
is_array
(
$names
))
{
$attrs
=
array
();
foreach
(
$names
as
$name
)
{
foreach
(
$names
as
$name
)
{
if
(
property_exists
(
$this
,
$name
))
{
$attrs
[
$name
]
=
$this
->
$name
;
}
else
{
}
else
{
$attrs
[
$name
]
=
isset
(
$attributes
[
$name
])
?
$attributes
[
$name
]
:
null
;
}
}
return
$attrs
;
}
else
{
}
else
{
return
$attributes
;
}
}
...
...
@@ -716,9 +694,7 @@ abstract class ActiveRecord extends \yii\base\Model
{
if
(
!
$runValidation
||
$this
->
validate
(
$attributes
))
{
return
$this
->
getIsNewRecord
()
?
$this
->
insert
(
$attributes
)
:
$this
->
update
(
$attributes
);
}
else
{
}
else
{
return
false
;
}
}
...
...
@@ -798,8 +774,7 @@ abstract class ActiveRecord extends \yii\base\Model
$event
=
new
CModelEvent
(
$this
);
$this
->
onBeforeSave
(
$event
);
return
$event
->
isValid
;
}
else
{
}
else
{
return
true
;
}
}
...
...
@@ -830,8 +805,7 @@ abstract class ActiveRecord extends \yii\base\Model
$event
=
new
CModelEvent
(
$this
);
$this
->
onBeforeDelete
(
$event
);
return
$event
->
isValid
;
}
else
{
}
else
{
return
true
;
}
}
...
...
@@ -910,11 +884,8 @@ abstract class ActiveRecord extends \yii\base\Model
if
(
$table
->
sequenceName
!==
null
)
{
if
(
is_string
(
$primaryKey
)
&&
$this
->
$primaryKey
===
null
)
{
$this
->
$primaryKey
=
$builder
->
getLastInsertID
(
$table
);
}
elseif
(
is_array
(
$primaryKey
))
{
foreach
(
$primaryKey
as
$pk
)
{
}
elseif
(
is_array
(
$primaryKey
))
{
foreach
(
$primaryKey
as
$pk
)
{
if
(
$this
->
$pk
===
null
)
{
$this
->
$pk
=
$builder
->
getLastInsertID
(
$table
);
break
;
...
...
@@ -955,8 +926,7 @@ abstract class ActiveRecord extends \yii\base\Model
$this
->
_pk
=
$this
->
getPrimaryKey
();
$this
->
afterSave
();
return
true
;
}
else
{
}
else
{
return
false
;
}
}
...
...
@@ -984,13 +954,10 @@ abstract class ActiveRecord extends \yii\base\Model
if
(
!
$this
->
getIsNewRecord
())
{
Yii
::
trace
(
get_class
(
$this
)
.
'.saveAttributes()'
,
'system.db.ar.ActiveRecord'
);
$values
=
array
();
foreach
(
$attributes
as
$name
=>
$value
)
{
foreach
(
$attributes
as
$name
=>
$value
)
{
if
(
is_integer
(
$name
))
{
$values
[
$value
]
=
$this
->
$value
;
}
else
{
}
else
{
$values
[
$name
]
=
$this
->
$name
=
$value
;
}
}
...
...
@@ -1000,12 +967,10 @@ abstract class ActiveRecord extends \yii\base\Model
if
(
$this
->
updateByPk
(
$this
->
getOldPrimaryKey
(),
$values
)
>
0
)
{
$this
->
_pk
=
$this
->
getPrimaryKey
();
return
true
;
}
else
{
}
else
{
return
false
;
}
}
else
{
}
else
{
throw
new
Exception
(
Yii
::
t
(
'yii'
,
'The active record cannot be updated because it is new.'
));
}
}
...
...
@@ -1032,13 +997,11 @@ abstract class ActiveRecord extends \yii\base\Model
$criteria
=
$builder
->
createPkCriteria
(
$table
,
$this
->
getOldPrimaryKey
());
$command
=
$builder
->
createUpdateCounterCommand
(
$this
->
getTableSchema
(),
$counters
,
$criteria
);
if
(
$command
->
execute
())
{
foreach
(
$counters
as
$name
=>
$value
)
{
foreach
(
$counters
as
$name
=>
$value
)
{
$this
->
$name
=
$this
->
$name
+
$value
;
}
return
true
;
}
else
{
}
else
{
return
false
;
}
}
...
...
@@ -1056,12 +1019,10 @@ abstract class ActiveRecord extends \yii\base\Model
$result
=
$this
->
deleteByPk
(
$this
->
getPrimaryKey
())
>
0
;
$this
->
afterDelete
();
return
$result
;
}
else
{
}
else
{
return
false
;
}
}
else
{
}
else
{
throw
new
Exception
(
Yii
::
t
(
'yii'
,
'The active record cannot be deleted because it is new.'
));
}
}
...
...
@@ -1076,19 +1037,15 @@ abstract class ActiveRecord extends \yii\base\Model
if
(
!
$this
->
getIsNewRecord
()
&&
(
$record
=
$this
->
findByPk
(
$this
->
getPrimaryKey
()))
!==
null
)
{
$this
->
_attributes
=
array
();
$this
->
_related
=
array
();
foreach
(
$this
->
getMetaData
()
->
columns
as
$name
=>
$column
)
{
foreach
(
$this
->
getMetaData
()
->
columns
as
$name
=>
$column
)
{
if
(
property_exists
(
$this
,
$name
))
{
$this
->
$name
=
$record
->
$name
;
}
else
{
}
else
{
$this
->
_attributes
[
$name
]
=
$record
->
$name
;
}
}
return
true
;
}
else
{
}
else
{
return
false
;
}
}
...
...
framework/db/ar/JoinElement.php
View file @
c5cdcab6
...
...
@@ -22,13 +22,21 @@ class JoinElement extends \yii\base\Object
*/
public
$relation
;
/**
* @var JoinElement
* @var JoinElement
the parent element that this element needs to join with
*/
public
$parent
;
/**
* @var JoinElement[]
* @var JoinElement[]
the child elements that need to join with this element
*/
public
$children
=
array
();
/**
* @var JoinElement[] the child elements that have relations declared in the AR class of this element
*/
public
$relatedChildren
=
array
();
/**
* @var boolean whether this element is only for join purpose. If true, data will also be populated into the AR of this element.
*/
public
$joinOnly
;
public
$columnAliases
=
array
();
// alias => original name
public
$pkAlias
=
array
();
// original name => alias
...
...
@@ -36,12 +44,13 @@ class JoinElement extends \yii\base\Object
public
$records
;
public
$relatedRecords
;
public
function
__construct
(
$
parent
,
$relation
)
public
function
__construct
(
$
relation
,
$parent
,
$relatedParent
)
{
$this
->
relation
=
$relation
;
if
(
$parent
!==
null
)
{
$this
->
parent
=
$parent
;
$this
->
relation
=
$relation
;
$parent
->
children
[
$relation
->
name
]
=
$this
;
$relatedParent
->
relatedChildren
[
$relation
->
name
]
=
$this
;
}
}
...
...
@@ -68,18 +77,18 @@ class JoinElement extends \yii\base\Object
}
}
$modelClass
=
$this
->
relation
->
modelClass
;
$record
=
$modelClass
::
populate
Record
(
$attributes
);
$record
=
$modelClass
::
populate
Data
(
$attributes
);
foreach
(
$this
->
children
as
$child
)
{
if
(
$child
->
relation
->
select
!==
false
)
{
$record
->
initRelat
ion
(
$child
->
relation
);
$record
->
initRelat
edRecord
(
$child
->
relation
);
}
}
$this
->
records
[
$pk
]
=
$record
;
}
// populate child records
foreach
(
$this
->
c
hildren
as
$child
)
{
if
(
$child
->
relation
->
select
===
false
)
{
foreach
(
$this
->
relatedC
hildren
as
$child
)
{
if
(
$child
->
relation
->
select
===
false
||
$child
->
joinOnly
)
{
continue
;
}
$childRecord
=
$child
->
populateData
(
$row
);
...
...
@@ -102,10 +111,10 @@ class JoinElement extends \yii\base\Object
public
function
buildQuery
(
$query
)
{
$tokens
=
array
(
'@.'
=>
$this
->
relation
->
tableAlias
,
'?.'
=>
$this
->
parent
->
relation
->
tableAlias
,
'@.'
=>
$this
->
relation
->
tableAlias
.
'.'
,
'?.'
=>
$this
->
parent
->
relation
->
tableAlias
.
'.'
,
);
foreach
(
$this
->
buildSelect
()
as
$column
)
{
foreach
(
$this
->
buildSelect
(
$this
->
relation
->
select
)
as
$column
)
{
$query
->
select
[]
=
strtr
(
$column
,
$tokens
);
}
...
...
@@ -117,32 +126,60 @@ class JoinElement extends \yii\base\Object
$query
->
having
[]
=
strtr
(
$this
->
relation
->
having
,
$tokens
);
}
/*
* joinType;
on;
via;
orderby
groupby
join
params
*/
if
(
$this
->
relation
->
via
!==
null
)
{
$query
->
join
[]
=
$this
->
relation
->
via
;
}
$modelClass
=
$this
->
relation
->
modelClass
;
$tableName
=
$modelClass
::
tableName
();
$joinType
=
$this
->
relation
->
joinType
===
null
?
'LEFT JOIN'
:
$this
->
relation
->
joinType
;
$join
=
"
$joinType
$tableName
{
$this
->
relation
->
tableAlias
}
"
;
if
(
$this
->
relation
->
on
!==
null
)
{
$join
.=
' ON '
.
strtr
(
$this
->
relation
->
on
,
$tokens
);
}
$query
->
join
[]
=
$join
;
if
(
$this
->
relation
->
join
!==
null
)
{
$query
->
join
[]
=
strtr
(
$this
->
relation
->
join
,
$tokens
);
}
// todo: convert orderBy to array first
if
(
$this
->
relation
->
orderBy
!==
null
)
{
$query
->
orderBy
[]
=
strtr
(
$this
->
relation
->
orderBy
,
$tokens
);
}
// todo: convert groupBy to array first
if
(
$this
->
relation
->
groupBy
!==
null
)
{
$query
->
groupBy
[]
=
strtr
(
$this
->
relation
->
groupBy
,
$tokens
);
}
if
(
$this
->
relation
->
params
!==
null
)
{
foreach
(
$this
->
relation
->
params
as
$name
=>
$value
)
{
if
(
is_integer
(
$name
))
{
$query
->
params
[]
=
$value
;
}
else
{
$query
->
params
[
$name
]
=
$value
;
}
}
}
foreach
(
$this
->
children
as
$child
)
{
$child
->
buildQuery
(
$query
);
}
}
public
function
buildSelect
()
public
function
buildSelect
(
$select
)
{
$modelClass
=
$this
->
relation
->
modelClass
;
$tableSchema
=
$modelClass
::
getMetaData
()
->
table
;
$select
=
$this
->
relation
->
select
;
$columns
=
array
();
$columnCount
=
0
;
$prefix
=
$this
->
relation
->
tableAlias
;
if
(
empty
(
$select
)
||
$select
===
'*'
)
{
foreach
(
$tableSchema
->
columns
as
$column
)
{
$alias
=
$this
->
tableAlias
.
'_'
.
(
$columnCount
++
);
$columns
[]
=
"
{
$column
->
name
}
AS
$alias
"
;
$alias
=
$this
->
relation
->
tableAlias
.
'_'
.
(
$columnCount
++
);
$columns
[]
=
"
$prefix
.
{
$column
->
name
}
AS
$alias
"
;
$this
->
columnAliases
[
$alias
]
=
$column
->
name
;
if
(
$column
->
isPrimaryKey
)
{
$this
->
pkAlias
[
$column
->
name
]
=
$alias
;
...
...
@@ -153,8 +190,8 @@ class JoinElement extends \yii\base\Object
$select
=
explode
(
','
,
$select
);
}
foreach
(
$tableSchema
->
primaryKey
as
$column
)
{
$alias
=
$this
->
tableAlias
.
'_'
.
(
$columnCount
++
);
$columns
[]
=
"
$column
AS
$alias
"
;
$alias
=
$this
->
relation
->
tableAlias
.
'_'
.
(
$columnCount
++
);
$columns
[]
=
"
$
prefix
.
$
column
AS
$alias
"
;
$this
->
pkAlias
[
$column
]
=
$alias
;
}
foreach
(
$select
as
$column
)
{
...
...
@@ -164,8 +201,8 @@ class JoinElement extends \yii\base\Object
$this
->
columnAliases
[
$matches
[
2
]]
=
$matches
[
2
];
$columns
[]
=
$column
;
}
elseif
(
!
isset
(
$this
->
pkAlias
[
$column
]))
{
$alias
=
$this
->
tableAlias
.
'_'
.
(
$columnCount
++
);
$columns
[]
=
"
$column
AS
$alias
"
;
$alias
=
$this
->
relation
->
tableAlias
.
'_'
.
(
$columnCount
++
);
$columns
[]
=
"
$
prefix
.
$
column
AS
$alias
"
;
$this
->
columnAliases
[
$alias
]
=
$column
;
}
}
...
...
framework/db/dao/QueryBuilder.php
View file @
c5cdcab6
...
...
@@ -656,7 +656,7 @@ class QueryBuilder extends \yii\base\Object
if
(
is_object
(
$column
))
{
$columns
[
$i
]
=
(
string
)
$column
;
}
elseif
(
strpos
(
$column
,
'('
)
===
false
)
{
if
(
preg_match
(
'/^(.*?)(?i:\s+as\s+|\s+)([\w\-
\.]
)$/'
,
$column
,
$matches
))
{
if
(
preg_match
(
'/^(.*?)(?i:\s+as\s+|\s+)([\w\-
_\.]+
)$/'
,
$column
,
$matches
))
{
$columns
[
$i
]
=
$driver
->
quoteColumnName
(
$matches
[
1
])
.
' AS '
.
$driver
->
quoteSimpleColumnName
(
$matches
[
2
]);
}
else
{
$columns
[
$i
]
=
$driver
->
quoteColumnName
(
$column
);
...
...
tests/unit/data/ar/Customer.php
View file @
c5cdcab6
...
...
@@ -8,4 +8,13 @@ class Customer extends ActiveRecord
{
return
'tbl_customer'
;
}
public
static
function
relations
()
{
return
array
(
'orders:Order[]'
=>
array
(
'on'
=>
'@.customer_id = ?.id'
,
),
);
}
}
\ No newline at end of file
tests/unit/data/ar/Order.php
View file @
c5cdcab6
...
...
@@ -8,4 +8,13 @@ class Order extends ActiveRecord
{
return
'tbl_order'
;
}
public
static
function
relations
()
{
return
array
(
'customer:Customer'
=>
array
(
'on'
=>
'@.id = ?.customer_id'
,
),
);
}
}
\ No newline at end of file
tests/unit/data/mysql.sql
View file @
c5cdcab6
...
...
@@ -86,7 +86,7 @@ INSERT INTO tbl_item (name, category_id) VALUES ('Cars', 2);
INSERT
INTO
tbl_order
(
customer_id
,
create_time
,
total
)
VALUES
(
1
,
1325282384
,
110
.
0
);
INSERT
INTO
tbl_order
(
customer_id
,
create_time
,
total
)
VALUES
(
2
,
1325334482
,
33
.
0
);
INSERT
INTO
tbl_order
(
customer_id
,
create_time
,
total
)
VALUES
(
3
,
1325502201
,
40
.
0
);
INSERT
INTO
tbl_order
(
customer_id
,
create_time
,
total
)
VALUES
(
2
,
1325502201
,
40
.
0
);
INSERT
INTO
tbl_order_item
(
order_id
,
item_id
,
quantity
,
subtotal
)
VALUES
(
1
,
1
,
1
,
30
.
0
);
INSERT
INTO
tbl_order_item
(
order_id
,
item_id
,
quantity
,
subtotal
)
VALUES
(
1
,
2
,
2
,
40
.
0
);
...
...
tests/unit/framework/db/ar/ActiveRecordTest.php
View file @
c5cdcab6
...
...
@@ -116,6 +116,18 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
$this
->
assertEquals
(
3
,
$customer
->
id
);
$this
->
assertEquals
(
null
,
$customer
->
name
);
}
public
function
testEagerLoading
()
{
$customers
=
Customer
::
find
()
->
with
(
'orders'
)
->
orderBy
(
't0.id'
)
->
all
();
$this
->
assertEquals
(
3
,
count
(
$customers
));
$this
->
assertEquals
(
1
,
count
(
$customers
[
0
]
->
orders
));
$this
->
assertEquals
(
2
,
count
(
$customers
[
1
]
->
orders
));
$this
->
assertEquals
(
0
,
count
(
$customers
[
2
]
->
orders
));
$customers
=
Customer
::
find
()
->
with
(
'orders.customer'
)
->
orderBy
(
't0.id'
)
->
all
();
}
/*
public function testGetSql()
{
...
...
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