Skip to content

Joining a PageTable field results in an empty value when the field has exactly one page #1988

@tuomassalo

Description

@tuomassalo

Short description of the issue

When a page has a PageTable field and it's joined with e.g. $p = $pages->get('id=42, field=my_pagetable_field'), the resulting $p->my_pagetable_field is empty when the field contains exactly one page.

Expected behavior

Adding field=... should not affect the result, only performance.

Actual behavior

The only subpage is not fetched.

Screenshots/Links that demonstrate the issue

Possible cause: when the database query returns exactly one subpage, is_array returns false here:
https://github.com/processwire/processwire/blob/master/wire/modules/Fieldtype/FieldtypePageTable.module#L452

Steps to reproduce the issue

The script below creates a parent and child template, p and c, and a field c_ref in the p template. Then it adds these pages:

Parent: parent-a
  Child: child-a1
  Child: child-a2
Parent: parent-b
  Child: child-b1

If run without GET params, it fetches all the pages and prints the above output. If run with ?join, the lone child child-b1 is not printed.

Setup/Environment

  • ProcessWire version: latest dev
  • (Optional) PHP version: 8.2
  • (Optional) MySQL version: MariaDB 10.5.26

The script:

<?php

$processwirePath = '/var/www/html/';
include($processwirePath . 'index.php');
header('Content-Type: text/plain');

////// Install fixture templates, field and pages.
////// First, clean up previous run (if any).

// Remove pages with template 'p' or 'c'.
$pagesToRemove = $pages->find("template=p|c");
foreach ($pagesToRemove as $page) $pages->delete($page, true);

// Remove templates 'p' and 'c'.
$pTemplate = $templates->get('p');
if ($pTemplate) $templates->delete($pTemplate);

$cTemplate = $templates->get('c');
if ($cTemplate) $templates->delete($cTemplate);

// Remove field 'c_ref' if it exists.
$field = $fields->get('c_ref');
if ($field) $fields->delete($field);

// Create templates and field.

$pTemplate = $templates->add('p');
$pTemplate->save();

$cTemplate = $templates->add('c');
$cTemplate->save();

$field = $fields->makeItem();
$field->name = 'c_ref';
$field->type = 'PageTable';
$field->label = "c_ref";
$field->template_id = [$cTemplate->id];
$field->inputfield = "InputfieldPageTable";
$field->parent_id = 1;
$field->save();
$pTemplate->fields->add($field);
$pTemplate->save();

// Create pages.
$parent_a = $pages->add('p', '/', 'parent-a');

$child_a1 = $pages->add('c', '/', 'child-a1');
$parent_a->c_ref->add($child_a1);
$parent_a->save();

$child_a2 = $pages->add('c', '/', 'child-a2');
$parent_a->c_ref->add($child_a2);
$parent_a->save();

$parent_b = $pages->add('p', '/', 'parent-b');

$child_b1 = $pages->add('c', '/', 'child-b1');
$parent_b->c_ref->add($child_b1);
$parent_b->save();

//////// Now everything is set up.

$selectorSuffix = isset($_GET['join']) ? ', field=c_ref' : '';    

foreach (['parent-a', 'parent-b'] as $parentName) {
    $parent = $wire->pages->get("name=$parentName" . $selectorSuffix);
    echo "Parent: $parentName\n";

    foreach ($parent->c_ref as $child) {
        echo "  Child: " . $child->name . "\n";
    }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions