You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Behaviour of $page->pagetable_field->add() depends on whether a temporary variable is used:
if(isset($_GET['tmp'])) {
// this succeeds$tmp = addPage('c');
$p->ptfield->add($tmp);
} else {
// this fails!$p->ptfield->add(addPage('c'));
}
Expected behavior
See test script below: ProcessWire would behave identically with or without ?tmp query string variable.
Actual behavior
With ?tmp, the script correctly returns 1. Without it, the add() fails and the script returns 0.
Optional: Suggestion for a possible fix
I have no idea. I'm not a PHP expert but I'm surprised this is even possible, without some very specific introspection hacks. Maybe the problem is related to the lifespan of objects, but I failed to create a minimal reproducible example without using ProcessWire.
Steps to reproduce the issue
Save this script to /test.php and run it with and without ?tmp.
<?phpuseProcessWire\Page;
require('index.php');
header('Content-Type: text/plain');
////// Install fixture templates, field and pages.////// First, clean up previous run (if any).$pages = $wire->wire('pages');
$templates = $wire->wire('templates');
$fields = $wire->wire('fields');
// Remove pages with template 'p' or 'c'.$pagesToRemove = $pages->find("template=p|c");
foreach ($pagesToRemoveas$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 fields 'ptfield' if it exists.$field = $fields->get('ptfield');
if ($field) $fields->delete($field);
// Create templates and fields.$pTemplate = $templates->add('p');
$pTemplate->save();
$cTemplate = $templates->add('c');
$cTemplate->save();
$field = $fields->makeItem();
$field->name = 'ptfield';
$field->label = 'ptfield';
$field->type = 'PageTable';
$field->template_id = [$cTemplate->id];
$field->parent_id = 1;
$field->inputfield = 'InputfieldPageTable';
$field->save();
$pTemplate->fields->add($field);
$pTemplate->save();
functionaddPage(string$template)
{
global$wire;
$page = newPage();
$page->template = $template;
$page->parent = '/';
$page->save();
// NB: removing this line will make the test work$page = $wire->wire('pages')->get($page->id);
return$page;
}
$p = addPage('p');
if(isset($_GET['tmp'])) {
// this succeeds$tmp = addPage('c');
$p->ptfield->add($tmp);
} else {
// this fails!$p->ptfield->add(addPage('c'));
}
$p->save();
$p = $wire->wire('pages')->get($p->id);
echo$p->ptfield->count;
Setup/Environment
ProcessWire version: latest dev
(Optional) PHP version: 8.1 (I suspect this might be relevant!)
(Optional) MySQL version: Mariadb 10.6
Additional observation: if I add more lines to the else block, like this:
// ...
} else {
$p->ptfield->add(addPage('c')); // this fails!$p->ptfield->add(addPage('c')); // this fails!$p->ptfield->add(addPage('c')); // this fails!
}
// ...
... the first one fails, but the others succeed. (I confirmed this by adding a title parameter to addPage.)
The text was updated successfully, but these errors were encountered:
@tuomassalo That's a strange behavior, but from our standpoint there's no difference between add(addPage)) and add($tmp), so we might be looking at an odd PHP behavior or bug. If the add() method was forcing a pass-by-reference then we'd want to use a variable rather than a return value from another function, but that method does not use a reference argument. So I don't think that part is the source of anything on the PW side, since the two are equivalent from our interface to PHP. But we should look at the parts we do have sway over. And I am particularly curious about the line below though and how it changes the behavior. What is the purpose of it since you already have the $page?
// NB: removing this line will make the test work$page = $wire->wire('pages')->get($page->id);
For another experiment, try changing your page save call to this:
I agree, it looks like a very odd PHP (compiler?) bug. Or maybe some intended PHP corner case peculiarity, since I've confirmed this bug on a wide range of PHP versions: 7.4, 8.1 and 8.4.2.
Short description of the issue
Behaviour of
$page->pagetable_field->add()
depends on whether a temporary variable is used:Expected behavior
See test script below: ProcessWire would behave identically with or without
?tmp
query string variable.Actual behavior
With
?tmp
, the script correctly returns1
. Without it, theadd()
fails and the script returns0
.Optional: Suggestion for a possible fix
I have no idea. I'm not a PHP expert but I'm surprised this is even possible, without some very specific introspection hacks. Maybe the problem is related to the lifespan of objects, but I failed to create a minimal reproducible example without using ProcessWire.
Steps to reproduce the issue
Save this script to
/test.php
and run it with and without?tmp
.Setup/Environment
Additional observation: if I add more lines to the
else
block, like this:... the first one fails, but the others succeed. (I confirmed this by adding a
title
parameter toaddPage
.)The text was updated successfully, but these errors were encountered: