我可以为Symfony 2/条令结果设置更好的结构吗?

我可以为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(

我正在用Symfony构建一个API,我正在努力使用QueryBuilder为我的json提供的默认格式

在CakePhp中,当我获取数据时,它被放入一个嵌套的数组中,每个模型被分离出来,如下所示

$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存储库