Search code examples
phpmysqlrecursionpropel

Join in Propel causes recursion warning


We have a database model that looks like this:

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; 

When we call our method get_printers, which looks like this:

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

we get this as response

{
  "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*"
        }
      ]
    }
  ]
}

Question: What causes the "Printer": "*RECURSION*" to happen, and how can we remove it from the response? Preferably without having to SELECT each and every column except the "remote" foreign keys.


Solution

  • So it seems like toJSON() creates a JSON representation of the whole Collection (including its metadata), which contain objects that allows for moving both up and down in the object hierarchy, i.e Printer holds a reference to Document which in turn holds a reference back to its parent - Printer. A nifty little feature once you get a hold of how it should be done.


    The solution in this case was to add a Formatter, as suggested here.

    The end result looks like this:

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