Pommbundle 与另一个 table 的关系
Pommbundle Relation with another table
对于我的项目,我将 pommbundle 用于我的 Symfony 项目,我有一个问题:
例如:
TABLE Catalogue:
id = 1
name = test
webinfo = 2
TABLE Info :
id=1
webid = 2
textinfo = OK
textmore = it's test
关系
Catalogue.webinfo = Info.webid
如果我的实体与模式中定义的另一个实体有关系并且我想要一个包含所有信息的对象,如何访问信息因为转储 "Catalogue" returns 只有一个整数 "webinfo".我必须创建自己的方法吗?该包包含一个方法?
是否可以展示一个基本示例,供在 symfony2 中使用?
谢谢
Pomm 不是 ORM,因此不提供自动获取关系的方法。
做出这个选择是因为大多数程序员习惯的一个简单状态:
$blog_posts = $orm->getBlogPosts(); // SELECT * FROM blog.post;
foreach ($blog_posts as $blog_post) {
printf(
"The post titled '%s' has been written by '%s'.\n",
$post->getTitle(),
$post->getAuthor()->getName() // SELECT * FROM blog.author WHERE author_id = $*
);
}
上面的代码在作者 table 中发出的查询与博客 [=47=] 中的查询一样多,这称为嵌套循环查询,这是一个巨大的性能问题,非常烦人,因为隐藏的原因大多数程序员实际上并没有看到它执行了那么多查询。
您可以在 SQL 中执行相同的操作,只需一个查询:
SELECT
title,
published_at,
… -- other fields
a AS author
FROM
blog.post p
LEFT JOIN blog.author a USING (author_id)
这将输出如下行:
title | published_at | … | author
Gone with the wind | 2010-04-04 13:43:02… | … | ("Jules Vernes","jules.vernes@gmail.com", … )
Postgres 可以 return 作者行直接在博客的结果集中 posts,这比以前的解决方案效率高得多,但如果作者,这仍然会导致性能问题记录很大。自愿限制在博客 post 实体中获取的作者字段的数量可能很有趣,也许只是名字就足够了。让我们在博客 post 模型中执行这样的查询:
class PostModel extends Model
{
// …
public function getWithAuthor()
{
// HINT: this is bad practice, read below.
$sql = <<<SQL
select P.post_id, P.title, …, A.name AS author_name
from blog.post P
left join blog.author A using (author_id)
SQL;
return $this->query($sql);
}
在控制器中,获取博客 posts 和额外的作者信息变得很容易:
$blog_posts = $this->get('pomm')['my_session']
->getModel(PostModel::class)
->getWithAuthor();
foreach ($blog_posts as $post) {
printf(
"Post '%s' has been written by '%s'.\n",
$post['title'],
$post['author_name']
);
}
但是这种方法不太适用table,因为每个关系的名称 (table) 都是硬编码的,投影也是如此(SELECT 部分中的字段)。更改数据库结构会破坏此查询。这是一种规避这种情况的方法:
class PostModel extends Model
{
// …
public function getWithAuthor(Where $condition = null)
{
$condition = (new Where)->andWhere($condition); // empty condition and empty condition => true.
$sql = <<<SQL
select {projection}
from {post} P
left join {author} A using (author_id)
where {condition}
SQL;
$projection = $this->createProjection() // use Post fields
->setField('author_name', 'A.name', 'text'); // add a new field with its type
$author_relation = $this->getSession()
->getModel(AuthorModel::class) // get author relation name
->getStructure()
->getRelation();
$sql = strtr( // transform the SQL
$sql,
[
'{projection}' => $projection->formatFieldsWithFieldAlias("P"),
'{post}' => $this->structure->getRelation(),
'{author}' => $author_relation,
'{condition}' => $condition,
]);
return $this->query($sql, $condition->getValues(), $projection);
}
如果我们需要获取自昨天以来所有 post 博客及其作者姓名怎么办?
$blog_posts = $this->get('pomm')['my_session']
->getModel(PostModel::class)
->getWithAuthor(new Where("published_at > $*::timestamptz", [new \DateTime('yesterday')]));
也可以取回整个嵌套的 Author 实例,只需更改方法中的投影:
$projection = $this->createProjection()
->setField('author', 'A', 'blog.author');
注意: 上面字段的类型是行的来源 table。在 Postgres 中创建 table 意味着创建类型。
在控制器中:
foreach ($blog_posts as $post) {
printf(
"Post '%s' has been written by '%s'.\n",
$post['title'],
$post['author']['name']
);
}
Postgres 是 ORM。
谢谢大家,
我的代码中只有第二个错误
更正:
public function findWithJointureAll(Where $condition = null)
{
$famille_model = $this
->getSession()
->getModel('\AppBundle\Entity\MyDb1\PublicSchema\FamilleModel')
;
$condition = (new Where)->andWhere($condition);
$sql ="
select
{projection}
from
{ssfamille} ssf
inner join {famille} fam ON ssf.\"Famille\" = fam.\"ID\" where {condition}";
$projection = $this->createProjection()
->setField('test', 'fam','"Famille"')
;
$sql = strtr(
$sql,
[
'{ssfamille}' => $this->structure->getRelation(),
'{famille}' => $famille_model->getStructure()->getRelation(),
'{projection}' => $projection->formatFieldsWithFieldAlias('ssf'),
'{condition}' => $condition,
]
);
return $this->query($sql,$condition->getValues(),$projection);
}
我只想添加 $projection->formatFieldsWithFieldAlias('ssf') et quote 因为 name base 大写...
谢谢你的捆绑,太完美了!!
对于我的项目,我将 pommbundle 用于我的 Symfony 项目,我有一个问题:
例如:
TABLE Catalogue: id = 1 name = test webinfo = 2
TABLE Info : id=1 webid = 2 textinfo = OK textmore = it's test
关系
Catalogue.webinfo = Info.webid
如果我的实体与模式中定义的另一个实体有关系并且我想要一个包含所有信息的对象,如何访问信息因为转储 "Catalogue" returns 只有一个整数 "webinfo".我必须创建自己的方法吗?该包包含一个方法?
是否可以展示一个基本示例,供在 symfony2 中使用?
谢谢
Pomm 不是 ORM,因此不提供自动获取关系的方法。
做出这个选择是因为大多数程序员习惯的一个简单状态:
$blog_posts = $orm->getBlogPosts(); // SELECT * FROM blog.post;
foreach ($blog_posts as $blog_post) {
printf(
"The post titled '%s' has been written by '%s'.\n",
$post->getTitle(),
$post->getAuthor()->getName() // SELECT * FROM blog.author WHERE author_id = $*
);
}
上面的代码在作者 table 中发出的查询与博客 [=47=] 中的查询一样多,这称为嵌套循环查询,这是一个巨大的性能问题,非常烦人,因为隐藏的原因大多数程序员实际上并没有看到它执行了那么多查询。
您可以在 SQL 中执行相同的操作,只需一个查询:
SELECT
title,
published_at,
… -- other fields
a AS author
FROM
blog.post p
LEFT JOIN blog.author a USING (author_id)
这将输出如下行:
title | published_at | … | author
Gone with the wind | 2010-04-04 13:43:02… | … | ("Jules Vernes","jules.vernes@gmail.com", … )
Postgres 可以 return 作者行直接在博客的结果集中 posts,这比以前的解决方案效率高得多,但如果作者,这仍然会导致性能问题记录很大。自愿限制在博客 post 实体中获取的作者字段的数量可能很有趣,也许只是名字就足够了。让我们在博客 post 模型中执行这样的查询:
class PostModel extends Model
{
// …
public function getWithAuthor()
{
// HINT: this is bad practice, read below.
$sql = <<<SQL
select P.post_id, P.title, …, A.name AS author_name
from blog.post P
left join blog.author A using (author_id)
SQL;
return $this->query($sql);
}
在控制器中,获取博客 posts 和额外的作者信息变得很容易:
$blog_posts = $this->get('pomm')['my_session']
->getModel(PostModel::class)
->getWithAuthor();
foreach ($blog_posts as $post) {
printf(
"Post '%s' has been written by '%s'.\n",
$post['title'],
$post['author_name']
);
}
但是这种方法不太适用table,因为每个关系的名称 (table) 都是硬编码的,投影也是如此(SELECT 部分中的字段)。更改数据库结构会破坏此查询。这是一种规避这种情况的方法:
class PostModel extends Model
{
// …
public function getWithAuthor(Where $condition = null)
{
$condition = (new Where)->andWhere($condition); // empty condition and empty condition => true.
$sql = <<<SQL
select {projection}
from {post} P
left join {author} A using (author_id)
where {condition}
SQL;
$projection = $this->createProjection() // use Post fields
->setField('author_name', 'A.name', 'text'); // add a new field with its type
$author_relation = $this->getSession()
->getModel(AuthorModel::class) // get author relation name
->getStructure()
->getRelation();
$sql = strtr( // transform the SQL
$sql,
[
'{projection}' => $projection->formatFieldsWithFieldAlias("P"),
'{post}' => $this->structure->getRelation(),
'{author}' => $author_relation,
'{condition}' => $condition,
]);
return $this->query($sql, $condition->getValues(), $projection);
}
如果我们需要获取自昨天以来所有 post 博客及其作者姓名怎么办?
$blog_posts = $this->get('pomm')['my_session']
->getModel(PostModel::class)
->getWithAuthor(new Where("published_at > $*::timestamptz", [new \DateTime('yesterday')]));
也可以取回整个嵌套的 Author 实例,只需更改方法中的投影:
$projection = $this->createProjection()
->setField('author', 'A', 'blog.author');
注意: 上面字段的类型是行的来源 table。在 Postgres 中创建 table 意味着创建类型。
在控制器中:
foreach ($blog_posts as $post) {
printf(
"Post '%s' has been written by '%s'.\n",
$post['title'],
$post['author']['name']
);
}
Postgres 是 ORM。
谢谢大家, 我的代码中只有第二个错误 更正:
public function findWithJointureAll(Where $condition = null)
{
$famille_model = $this
->getSession()
->getModel('\AppBundle\Entity\MyDb1\PublicSchema\FamilleModel')
;
$condition = (new Where)->andWhere($condition);
$sql ="
select
{projection}
from
{ssfamille} ssf
inner join {famille} fam ON ssf.\"Famille\" = fam.\"ID\" where {condition}";
$projection = $this->createProjection()
->setField('test', 'fam','"Famille"')
;
$sql = strtr(
$sql,
[
'{ssfamille}' => $this->structure->getRelation(),
'{famille}' => $famille_model->getStructure()->getRelation(),
'{projection}' => $projection->formatFieldsWithFieldAlias('ssf'),
'{condition}' => $condition,
]
);
return $this->query($sql,$condition->getValues(),$projection);
}
我只想添加 $projection->formatFieldsWithFieldAlias('ssf') et quote 因为 name base 大写...
谢谢你的捆绑,太完美了!!