首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP ORMs和优化的关系查询

PHP ORMs和优化的关系查询
EN

Stack Overflow用户
提问于 2011-10-28 20:45:31
回答 3查看 487关注 0票数 3

我需要一个PHP ORM来处理好关系。请考虑Zend中的代码:

代码语言:javascript
复制
$persons = new Persons();
$person = $persons->find(5)->current();
echo 'Name: '.$person->fullname;

$phones = $person->findDependentRowset('Phones');
foreach($phones as $phone)
    echo 'Phone: '.$phone->phonenumber; 

或xPDO中下面的代码:

代码语言:javascript
复制
$person = $xpdo->getObject('Persons', 5);
echo 'Name: '.$person->get('fullname');

$phones = $person->getMany('Phones');
foreach($phones as $phone)
    echo 'Phone: '.$phone->get('phonenumber');

在这两个脚本中,ORMs执行两个查询如下:

代码语言:javascript
复制
SELECT * FROM persons WHERE id=5;
SELECT * FROM phones WHERE person=5;

它意味着对主对象的一个查询和对每个关系的一个查询,但是我需要的是对主对象及其关系使用一个查询!xPDO可以这样做:

代码语言:javascript
复制
$person = $xpdo->getObjectGraph('Persons', '{"Phones":{}}', 5);
echo 'Name: '.$person->get('fullname');

foreach($person->Phones as $phone)
    echo 'Phone: '.$phone->get('phonenumber');

它执行以下查询:

代码语言:javascript
复制
SELECT * FROM persons
LEFT JOIN phones ON phones.person=persons.id
WHERE persons.id=5

这是很好的,但它不可能设置字段从表!在本例中,这意味着xPDO使用"SELECT * ",因此如果我得到一个对象及其4个关系,我将得到所有这些表的所有字段!

因此,我需要一个ORM来执行下面的查询,例如:

代码语言:javascript
复制
SELECT persons.fullname , phones.phonenumber FROM persons
LEFT JOIN phones ON phones.person=persons.id
WHERE persons.id=5

原则可以通过DQL来实现,但我认为原则对个人项目没有好处。有什么PHP ORM可以这样做吗?

谢谢AHHP

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-18 23:30:23

xPDO可以做到。你只需要调整你的想法和要求。

请记住,objectGraph使用对象的类名,其中在图形和查询中使用图形中的关系。

代码语言:javascript
复制
 $criteria = $this->xpdo->newQuery('prefixClient');
            if (!empty($limit))
                $criteria->limit($limit);
            $criteria->where(array('Child.planid' => $this->getPrimaryKey(),
                                   'Child.active' => true,
                                   'GrandChild.someAttribute' => true,
                                   'GreatGrandChild.someOtherAttribute' => true,
                                   'suspended' => false
                             ));

            $out = $this->xpdo->getCollectionGraph('prefixClient', '{"Child":{"GrandChild":{"GreatGrandChild":{}}}}', $criteria);

您可以在关系的任何方面设置WHERE,包括当前对象,如挂起的=> false行中所示。

我的书可能会对你建立模式和关系有所帮助。对象在命名上应该总是单数,而它们之间的关系可以是复数(1:M)或单数(1:1)。

票数 3
EN

Stack Overflow用户

发布于 2011-10-29 10:58:01

哦,伙计,

我吃这种狗粮已经两个月了,我很喜欢它。红豆。

http://www.redbeanphp.com/

嵌套bean,这是它们将一个对象作为另一个对象的属性的单词。

豆子

整个文件都很小。使用SQL。我正在一个大型的项目中使用它,并且喜欢我能如此快地完成任务。

约翰。

票数 1
EN

Stack Overflow用户

发布于 2011-10-29 06:40:33

加塞拉可以通过以下几种方法自动获取相关信息:

1)继承关系

在如下示例中:

代码语言:javascript
复制
CREATE TABLE wizards (
    wizardId INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    fname VARCHAR(255) NOT NULL,
    lname VARCHAR(255) NOT NULL,
    ROLE ENUM('teacher', 'student') NULL,
    addressId INT UNSIGNED NULL,
    CONSTRAINT fk_address_wizard
    FOREIGN KEY (addressId)
    REFERENCES addresses(addressId)
    ON DELETE SET NULL
) ENGINE = Innodb;

CREATE TABLE students (
    wizardId INT UNSIGNED NOT NULL PRIMARY KEY,
    houseId INT UNSIGNED NOT NULL,
    isDAMembmer BOOL NOT NULL DEFAULT 0,
    CONSTRAINT fk_wizard_student
    FOREIGN KEY (wizardId)
    REFERENCES wizards(wizardId)
    ON DELETE CASCADE,
    CONSTRAINT fk_house_students
    FOREIGN KEY (houseId)
    REFERENCES houses(houseId)
    ON DELETE RESTRICT
) ENGINE = Innodb;

students表具有与wizards表相同的主键,并且由于外键关系定义,Gacela将检测到students继承了wizards中的所有字段。

2)相依关系

这可能更接近你要找的东西:

代码语言:javascript
复制
CREATE TABLE addresses (
    addressId INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    locationName VARCHAR(255) NOT NULL
) ENGINE = Innodb;

CREATE TABLE wizards (
    wizardId INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    fname VARCHAR(255) NOT NULL,
    lname VARCHAR(255) NOT NULL,
    ROLE ENUM('teacher', 'student') NULL,
    addressId INT UNSIGNED NULL,
    CONSTRAINT fk_address_wizard
        FOREIGN KEY (addressId)
        REFERENCES addresses(addressId)
        ON DELETE SET NULL
) ENGINE = Innodb;

但是,这个示例仍然与示例略有不同,因为addressId位于wizards表中,从而创建了belongsTo关系,而不是您的示例所反映的hasMany。

在Gacela中还有第三种选择,不过,我首先建议您考虑,虽然通常最好是急切地获取数据,但总是抓取而不是延迟加载数据会带来真正的性能影响。正是由于这个原因,Gacela (以及基本上所有其他数据Mapper或ORM)在默认情况下不会急切地从hasMany关系中获取数据。也就是说,您可以编写如下内容:

代码语言:javascript
复制
class Mapper extends \Gacela\Mapper 
{

    public function find($id)
    {
        $query = $this->_source()->query();

        $query->from('persons', array('fullName'))
            ->join('phones', 'phones.person=persons.id', array('phonenumber'), 'left')
            ->where('persons.id = :id', array(':id' => $id);

        $data = $this->_source->query($query);

        return $this->_load($data);
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7934728

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档