我可以为Symfony 2/条令结果设置更好的结构吗?
我正在用Symfony构建一个API,我正在努力使用QueryBuilder为我的json提供的默认格式 在CakePhp中,当我获取数据时,它被放入一个嵌套的数组中,每个模型被分离出来,如下所示我可以为Symfony 2/条令结果设置更好的结构吗?,symfony,cakephp,doctrine-orm,Symfony,Cakephp,Doctrine Orm,我正在用Symfony构建一个API,我正在努力使用QueryBuilder为我的json提供的默认格式 在CakePhp中,当我获取数据时,它被放入一个嵌套的数组中,每个模型被分离出来,如下所示 $this->Person->find( 'first', array( 'conditions' => array( 'Person.id' => $personId ), 'contain' => array(
$this->Person->find( 'first', array(
'conditions' => array(
'Person.id' => $personId
),
'contain' => array(
'Address' => array(
'fields' => array( 'Address.town' )
)
),
'fields' => array( 'Person.id', 'Person.name' )
) );
array(2) [
'Person' => array(2) [
'id' => string (3) "596"
'name' => string (13) "Michael Bates"
]
'Address' => array(1) [
array(3) [
'id' => string (3) "125"
'town' => string (8) "New York"
'AddressesPerson' => array(4) [
'id' => string (4) "4270"
'address_id' => string (3) "125"
'person_id' => string (3) "596"
]
]
]
]
array(1) {
["result"]=> array(1) {
[0]=> array(4) {
["person_id"]=> string(3) "596"
["name"]=> string (13) "Michael Bates"
["address_id"]=> string(3) "125"
["town"]=> string (8) "New York"
}
}
}
Object (Acme\FooBundle\Entity\Person) {
[id] => 596
[name] => "Michael Bates"
[foo] => "bar"
[address] => Object (Acme\FooBundle\Entity\Address) {
[id] => 125
[town] => "New York"
[country] => "USA"
}
}
$serializer = $this->get('jms_serializer.serializer');
$results = $this->getDoctrine()->getRepository('AcmeFoo:Person')->findById($id);
return new Response(
$serializer->serialize($results, 'json'),
200,
[ 'Content-Type' => 'application/json' ]
);
给我一个这样的结果
$this->Person->find( 'first', array(
'conditions' => array(
'Person.id' => $personId
),
'contain' => array(
'Address' => array(
'fields' => array( 'Address.town' )
)
),
'fields' => array( 'Person.id', 'Person.name' )
) );
array(2) [
'Person' => array(2) [
'id' => string (3) "596"
'name' => string (13) "Michael Bates"
]
'Address' => array(1) [
array(3) [
'id' => string (3) "125"
'town' => string (8) "New York"
'AddressesPerson' => array(4) [
'id' => string (4) "4270"
'address_id' => string (3) "125"
'person_id' => string (3) "596"
]
]
]
]
array(1) {
["result"]=> array(1) {
[0]=> array(4) {
["person_id"]=> string(3) "596"
["name"]=> string (13) "Michael Bates"
["address_id"]=> string(3) "125"
["town"]=> string (8) "New York"
}
}
}
Object (Acme\FooBundle\Entity\Person) {
[id] => 596
[name] => "Michael Bates"
[foo] => "bar"
[address] => Object (Acme\FooBundle\Entity\Address) {
[id] => 125
[town] => "New York"
[country] => "USA"
}
}
$serializer = $this->get('jms_serializer.serializer');
$results = $this->getDoctrine()->getRepository('AcmeFoo:Person')->findById($id);
return new Response(
$serializer->serialize($results, 'json'),
200,
[ 'Content-Type' => 'application/json' ]
);
这里的人和地址是分开的
在Symfony/Doctrine中,我不知道如何在结果中获得相同的结构。当我有这个
$queryBuilder = $this->createQueryBuilder('person')
->select('person.id as person_id, person.name')
->addSelect('address.id as address_id, address.town')
->leftJoin('person.address', 'address')
->where('person.id = :person_id')
->setParameter('person_id', $id);
return $queryBuilder->getQuery()->getResult();
我在同一个数组中获取person和address数据,如下所示
$this->Person->find( 'first', array(
'conditions' => array(
'Person.id' => $personId
),
'contain' => array(
'Address' => array(
'fields' => array( 'Address.town' )
)
),
'fields' => array( 'Person.id', 'Person.name' )
) );
array(2) [
'Person' => array(2) [
'id' => string (3) "596"
'name' => string (13) "Michael Bates"
]
'Address' => array(1) [
array(3) [
'id' => string (3) "125"
'town' => string (8) "New York"
'AddressesPerson' => array(4) [
'id' => string (4) "4270"
'address_id' => string (3) "125"
'person_id' => string (3) "596"
]
]
]
]
array(1) {
["result"]=> array(1) {
[0]=> array(4) {
["person_id"]=> string(3) "596"
["name"]=> string (13) "Michael Bates"
["address_id"]=> string(3) "125"
["town"]=> string (8) "New York"
}
}
}
Object (Acme\FooBundle\Entity\Person) {
[id] => 596
[name] => "Michael Bates"
[foo] => "bar"
[address] => Object (Acme\FooBundle\Entity\Address) {
[id] => 125
[town] => "New York"
[country] => "USA"
}
}
$serializer = $this->get('jms_serializer.serializer');
$results = $this->getDoctrine()->getRepository('AcmeFoo:Person')->findById($id);
return new Response(
$serializer->serialize($results, 'json'),
200,
[ 'Content-Type' => 'application/json' ]
);
这对于复杂的结果集来说是非常可怕的,这意味着我必须遍历并为所有名称冲突的字段(上面的person.id和address.id)提供一个别名
这些模型能否以类似于CakePhp的方式在Symfony/Doctrine中进行拆分
或者,在我从控制器返回结果之前,我必须自己这样做吗?我不认为有一种方法可以在条令中的一个查询中包含两个“拆分”的结果集,但这又有什么关系呢?在一个查询中有两个不同的实体结果是不对的 你想达到什么目标 看来你没有运用教义的力量。你似乎有实体,为什么不给它们补水呢
$qb = $this->createQueryBuilder('p')
->addSelect('a')
->leftJoin('p.address', 'a')
->where('p.id', ':id')
->setParameter(':id', $id)
;
return $qb->getQuery()->getResult();
这将为您提供一个Person
实体数组,这些实体与getAddress()
链接到Address
实体,如下所示
$this->Person->find( 'first', array(
'conditions' => array(
'Person.id' => $personId
),
'contain' => array(
'Address' => array(
'fields' => array( 'Address.town' )
)
),
'fields' => array( 'Person.id', 'Person.name' )
) );
array(2) [
'Person' => array(2) [
'id' => string (3) "596"
'name' => string (13) "Michael Bates"
]
'Address' => array(1) [
array(3) [
'id' => string (3) "125"
'town' => string (8) "New York"
'AddressesPerson' => array(4) [
'id' => string (4) "4270"
'address_id' => string (3) "125"
'person_id' => string (3) "596"
]
]
]
]
array(1) {
["result"]=> array(1) {
[0]=> array(4) {
["person_id"]=> string(3) "596"
["name"]=> string (13) "Michael Bates"
["address_id"]=> string(3) "125"
["town"]=> string (8) "New York"
}
}
}
Object (Acme\FooBundle\Entity\Person) {
[id] => 596
[name] => "Michael Bates"
[foo] => "bar"
[address] => Object (Acme\FooBundle\Entity\Address) {
[id] => 125
[town] => "New York"
[country] => "USA"
}
}
$serializer = $this->get('jms_serializer.serializer');
$results = $this->getDoctrine()->getRepository('AcmeFoo:Person')->findById($id);
return new Response(
$serializer->serialize($results, 'json'),
200,
[ 'Content-Type' => 'application/json' ]
);
你将拥有所有你需要的数据。如果您想序列化它(将其转换为json),您可能需要使用(或其)来处理这项艰巨的工作。在控制器级别,这看起来是这样的
$this->Person->find( 'first', array(
'conditions' => array(
'Person.id' => $personId
),
'contain' => array(
'Address' => array(
'fields' => array( 'Address.town' )
)
),
'fields' => array( 'Person.id', 'Person.name' )
) );
array(2) [
'Person' => array(2) [
'id' => string (3) "596"
'name' => string (13) "Michael Bates"
]
'Address' => array(1) [
array(3) [
'id' => string (3) "125"
'town' => string (8) "New York"
'AddressesPerson' => array(4) [
'id' => string (4) "4270"
'address_id' => string (3) "125"
'person_id' => string (3) "596"
]
]
]
]
array(1) {
["result"]=> array(1) {
[0]=> array(4) {
["person_id"]=> string(3) "596"
["name"]=> string (13) "Michael Bates"
["address_id"]=> string(3) "125"
["town"]=> string (8) "New York"
}
}
}
Object (Acme\FooBundle\Entity\Person) {
[id] => 596
[name] => "Michael Bates"
[foo] => "bar"
[address] => Object (Acme\FooBundle\Entity\Address) {
[id] => 125
[town] => "New York"
[country] => "USA"
}
}
$serializer = $this->get('jms_serializer.serializer');
$results = $this->getDoctrine()->getRepository('AcmeFoo:Person')->findById($id);
return new Response(
$serializer->serialize($results, 'json'),
200,
[ 'Content-Type' => 'application/json' ]
);
这将产生
[
{
"id": 596,
"name": "Michael Bates",
"address": {
"id": 125,
"town": "New York"
}
}
]
如果需要地址数组,可能需要在AddressRepository
public function findByPersonId($id)
{
$qb = $this->createQueryBuilder('a')
->leftJoin('a.person', 'p')
->where('p.id', ':id')
->setParameter(':id', $id)
;
return $qb->getQuery()->getResult();
}
它将返回一个与Person
id匹配的Address
数组。您可以将两者结合起来,以实现最初尝试的目标
$doctrine = $this->getDoctrine();
$persons = $doctrine->getRepository('AcmeFoo:Person')->findById($id);
$addresses = $doctrine->getRepository('AcmeFoo:Address')->findByPersonId($id);
$data = [
'Person' => $persons,
'Address' => $addresses
];
但是,如果您使用此方法,请注意忽略(在注释中)或删除join-in-Person存储库我不认为有一种方法可以在doctrine中的单个查询中包含两个“拆分”的结果集,但这又有什么关系呢?在一个查询中有两个不同的实体结果是不对的 你想达到什么目标 看来你没有运用教义的力量。你似乎有实体,为什么不给它们补水呢
$qb = $this->createQueryBuilder('p')
->addSelect('a')
->leftJoin('p.address', 'a')
->where('p.id', ':id')
->setParameter(':id', $id)
;
return $qb->getQuery()->getResult();
这将为您提供一个Person
实体数组,这些实体与getAddress()
链接到Address
实体,如下所示
$this->Person->find( 'first', array(
'conditions' => array(
'Person.id' => $personId
),
'contain' => array(
'Address' => array(
'fields' => array( 'Address.town' )
)
),
'fields' => array( 'Person.id', 'Person.name' )
) );
array(2) [
'Person' => array(2) [
'id' => string (3) "596"
'name' => string (13) "Michael Bates"
]
'Address' => array(1) [
array(3) [
'id' => string (3) "125"
'town' => string (8) "New York"
'AddressesPerson' => array(4) [
'id' => string (4) "4270"
'address_id' => string (3) "125"
'person_id' => string (3) "596"
]
]
]
]
array(1) {
["result"]=> array(1) {
[0]=> array(4) {
["person_id"]=> string(3) "596"
["name"]=> string (13) "Michael Bates"
["address_id"]=> string(3) "125"
["town"]=> string (8) "New York"
}
}
}
Object (Acme\FooBundle\Entity\Person) {
[id] => 596
[name] => "Michael Bates"
[foo] => "bar"
[address] => Object (Acme\FooBundle\Entity\Address) {
[id] => 125
[town] => "New York"
[country] => "USA"
}
}
$serializer = $this->get('jms_serializer.serializer');
$results = $this->getDoctrine()->getRepository('AcmeFoo:Person')->findById($id);
return new Response(
$serializer->serialize($results, 'json'),
200,
[ 'Content-Type' => 'application/json' ]
);
你将拥有所有你需要的数据。如果您想序列化它(将其转换为json),您可能需要使用(或其)来处理这项艰巨的工作。在控制器级别,这看起来是这样的
$this->Person->find( 'first', array(
'conditions' => array(
'Person.id' => $personId
),
'contain' => array(
'Address' => array(
'fields' => array( 'Address.town' )
)
),
'fields' => array( 'Person.id', 'Person.name' )
) );
array(2) [
'Person' => array(2) [
'id' => string (3) "596"
'name' => string (13) "Michael Bates"
]
'Address' => array(1) [
array(3) [
'id' => string (3) "125"
'town' => string (8) "New York"
'AddressesPerson' => array(4) [
'id' => string (4) "4270"
'address_id' => string (3) "125"
'person_id' => string (3) "596"
]
]
]
]
array(1) {
["result"]=> array(1) {
[0]=> array(4) {
["person_id"]=> string(3) "596"
["name"]=> string (13) "Michael Bates"
["address_id"]=> string(3) "125"
["town"]=> string (8) "New York"
}
}
}
Object (Acme\FooBundle\Entity\Person) {
[id] => 596
[name] => "Michael Bates"
[foo] => "bar"
[address] => Object (Acme\FooBundle\Entity\Address) {
[id] => 125
[town] => "New York"
[country] => "USA"
}
}
$serializer = $this->get('jms_serializer.serializer');
$results = $this->getDoctrine()->getRepository('AcmeFoo:Person')->findById($id);
return new Response(
$serializer->serialize($results, 'json'),
200,
[ 'Content-Type' => 'application/json' ]
);
这将产生
[
{
"id": 596,
"name": "Michael Bates",
"address": {
"id": 125,
"town": "New York"
}
}
]
如果需要地址数组,可能需要在AddressRepository
public function findByPersonId($id)
{
$qb = $this->createQueryBuilder('a')
->leftJoin('a.person', 'p')
->where('p.id', ':id')
->setParameter(':id', $id)
;
return $qb->getQuery()->getResult();
}
它将返回一个与Person
id匹配的Address
数组。您可以将两者结合起来,以实现最初尝试的目标
$doctrine = $this->getDoctrine();
$persons = $doctrine->getRepository('AcmeFoo:Person')->findById($id);
$addresses = $doctrine->getRepository('AcmeFoo:Address')->findByPersonId($id);
$data = [
'Person' => $persons,
'Address' => $addresses
];
但是,如果使用此方法,请注意忽略(在注释中)或删除join-in-Person存储库