加入 Propel 导致递归警告

Join in Propel causes recursion warning

我们有一个如下所示的数据库模型:

CREATE TABLE `Recipient` (
  `username` VARCHAR(15),
  `full_name` VARCHAR(45) NOT NULL,
  `email` VARCHAR(50) NOT NULL,
  `phone` VARCHAR(20) NOT NULL,
    `status` BIT NOT NULL,
  PRIMARY KEY (`username`)
) DEFAULT CHARSET=utf8;

CREATE TABLE `Printer` (
  `id` INT(6) UNSIGNED AUTO_INCREMENT,
    `arrival_date` DATETIME NOT NULL,
    `archived_date` DATETIME,
    `recipient_id` VARCHAR(15) NOT NULL,
    FOREIGN KEY(`recipient_id`) REFERENCES Recipient(`username`),
    PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8; 

CREATE TABLE `Owner` (
  `id` INT(6) UNSIGNED AUTO_INCREMENT,
  `name` VARCHAR(30) UNIQUE NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8; 

CREATE TABLE `Document` (
  `serial` VARCHAR(50),
  `picture` TEXT,
    `owner_id` int(6) UNSIGNED NOT NULL,
    `printer_id` INT(6) UNSIGNED,
    FOREIGN KEY(`owner_id`) REFERENCES Owner(`id`),
    FOREIGN KEY(`printer_id`) REFERENCES Printer(`id`),
    PRIMARY KEY(`serial`)
) DEFAULT CHARSET=utf8; 

当我们调用我们的方法时 get_printers,它看起来像这样:

public function get_printers(){
    $printers = \PrinterQuery::create()
            ->joinWith("Document")
            ->useDocumentQuery()
            ->joinWith("Owner")
            ->endUse()
            ->joinWith("Recipient")
            ->find();
    return $printers->toJSON();
}

我们得到这个作为回应

{
  "Printers": [
    {
      "Id": 1,
      "ArrivalDate": null,
      "ArchivedDate": null,
      "RecipientId": "myusername",
      "Recipient": {
        "Username": "myusername",
        "FullName": "Sture Testsson",
        "Email": "email@example.com",
        "Phone": "07383918",
        "Status": "\u0001",
        "Printers": [
          "*RECURSION*"
        ]
      },
      "Documents": [
        {
          "Serial": "111",
          "Picture": "url",
          "OwnerId": 1,
          "PrinterId": 1,
          "Printer": "*RECURSION*"
        },
        {
          "Serial": "222",
          "Picture": null,
          "OwnerId": 2,
          "PrinterId": 1,
          "Printer": "*RECURSION*"
        },
        {
          "Serial": "333",
          "Picture": null,
          "OwnerId": 3,
          "PrinterId": 1,
          "Printer": "*RECURSION*"
        }
      ]
    }
  ]
}

问题: 是什么导致 "Printer": "*RECURSION*" 发生,我们如何将其从响应中删除?最好不必 SELECT 除了 "remote" 外键之外的每一列。

所以看起来 toJSON() 创建了 整个 Collection 的 JSON 表示(包括其元数据),其中包含的对象允许在对象层次结构中上下移动,即 Printer 持有对 Document 的引用,后者又持有对其父级的引用 - Printer。一旦掌握了它应该如何完成,这是一个漂亮的小功能。


本例中的解决方案是添加一个Formatter, as suggested here

最终结果如下所示:

$printers = \PrinterQuery::create()
            ->joinWith("Document")
            ->useDocumentQuery()
            ->joinWith("Owner")
            ->endUse()
            ->joinWith("Recipient")
            ->setFormatter('\Propel\Runtime\Formatter\ArrayFormatter')
            ->find();
    return $printers->toJSON();
}