Jump to content
Manuel

Fatal error when outputting multiple page_reference fields

Recommended Posts

Hi everybody!

I'm new to PW and just did the beginner-tutorial “Hello Worlds”, a beginning ProcessWire tutorial --> Link
After extending the template from the original tutorial with a page_reference-Field (Page-Field value type is configured as single page),
PW throws a fatal error when i try to output multiple pages:

$planets = $pages->find("template=planet, sort=-title");

foreach($planets as $planet) {
	echo $planet->title;
	echo $planet->planet_reference->title;  
}

Should return three Pages, but throws the following error:

Quote

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes) in /Applications/MAMP/htdocs/extranet/wire/core/Page.php on line 1651
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes) in Unknown on line 0

When i try to output the field with a single page, everything just works fine:

$planet = $pages->get(1018);

echo $planet->title;
echo $planet->planet_reference->title;

I've tried to solve the problem with myself (and google), but i can't fix the error.
Thanks a lot!

My enviroment:
OSX Mojave / MAMP (PHP 7.2), PW v 3.0.123

Share this post


Link to post
Share on other sites

Hi @Manuel and welcome to PW and the forum 🙂 

I don't see anything strange here. Could you paste the whole code? Are you sure you don't have any endless loop somewhere?

I'd also recommend that you install TracyDebugger - you can try snippets like the one posted above easily in the console: https://adrianbj.github.io/TracyDebugger/#/debug-bar?id=console

  • Like 1

Share this post


Link to post
Share on other sites

Hi @bernhard - and greetings from Tirol 😉
Yes I've allready installed Tracy-Debugger and get the same error.
It can't be an endless loop, because, even if I enter the code directly into the tracy debugger console, the same error happens.
Two outputs work fine, after a third one a error occurs...

screenshot_1.png.7c58c48778494a6ccee068fbdbc27b6e.png
screenshot_2.png.77367c90b7ab4f42cc0c13629ce7c833.png

Thanks for your help!

Manuel

Edited by Manuel

Share this post


Link to post
Share on other sites

Is planet_reference of page 1018 pointing to itself?

BTW: Use dump() or the shorthand d() better than echo in the console 😉 

  • Like 1

Share this post


Link to post
Share on other sites
7 minutes ago, bernhard said:

Is planet_reference of page 1018 pointing to itself?

 

If that's indeed the case: To avoid this, in your pageref field definition, use "selectable pages" > "selector string" and then insert this condition: id!=page.id to avoid references to itself.

  • Like 1

Share this post


Link to post
Share on other sites

I think even if that was the case it should not end in such an error, but I don't have time to test it right now and maybe others will have better ideas 🙂 

Share this post


Link to post
Share on other sites
15 hours ago, bernhard said:

Is planet_reference of page 1018 pointing to itself?

BTW: Use dump() or the shorthand d() better than echo in the console 😉 

Thank you for the hints! Unfortunately the error occures on every page, also on the backend (TracyDebugger Console).

Share this post


Link to post
Share on other sites

Here's a way to find all self-referencing page fields. Open your MySQL interface (MySQL Workbench, phpMyAdmin, adminer, whatever...) and execute the following query:

SET @oldgcmaxlen = @@group_concat_max_len;
SET SESSION group_concat_max_len = 32768;

SELECT GROUP_CONCAT(querystring SEPARATOR 'UNION\n') as sqlstring
FROM (
	SELECT 1 as something,
	CONCAT(
		'SELECT x.pages_id as id, y.name, z.data as title, \'',
        a.name,
        '\' as fieldname\n',
        'FROM field_',
		a.name,
		' x\n',
        'JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data\n'
	) as querystring
	FROM fields a
	WHERE a.type = 'FieldtypePage'
) as inmemtbl
GROUP BY something
;

SET SESSION group_concat_max_len = @oldgcmaxlen;

The result will be a UNION query that checks all your page fields for direct recursions. Here's an example:

SELECT x.pages_id as id, y.name, z.data as title, 'permissions' as fieldname
FROM field_permissions x
JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data
UNION
SELECT x.pages_id as id, y.name, z.data as title, 'roles' as fieldname
FROM field_roles x
JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data
UNION
SELECT x.pages_id as id, y.name, z.data as title, 'language' as fieldname
FROM field_language x
JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data
UNION
SELECT x.pages_id as id, y.name, z.data as title, 'pagesel' as fieldname
FROM field_pagesel x
JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data

Copy that query into the SQL editor and execute it. If there are any recursions, you will see them listed with the page id, page name, page title and field name.

recursionexample.png.2f5bf2d48d661c51942543e065e3152a.png

  • Like 6

Share this post


Link to post
Share on other sites
1 hour ago, Manuel said:

Thank you for the hints! Unfortunately the error occures on every page, also on the backend (TracyDebugger Console).

This statement seems like you didn't get what I tried to say.

17 hours ago, dragan said:

Is planet_reference of page 1018 pointing to itself?

Means that you have maybe selected page 1018 in the page-reference-field "planet_reference" of page 1018. That means the planet_reference of 1018 points to page 1018 (itself) and could maybe end in an endless loop?

No idea if that is possible and it would throw such an error. I think PW should be clever enough to prevent such errors. If not, that would be worth an issue report!

  • Like 1

Share this post


Link to post
Share on other sites

@bernhard now i know what you mean.
No - there is another id selected (1017).
PW even doesn't offer a self-refference in the selectbox.

Share this post


Link to post
Share on other sites
5 minutes ago, Manuel said:

PW even doesn't offer a self-refference in the selectbox.

OK great for PW, bad for solving your problem 🙂 Then I'm out of ideas, sorry 😐 

Share this post


Link to post
Share on other sites

No problem and thanks for your advise! I'll try to solve the issue and will report the solution in this thread - hopefully 😉

Share this post


Link to post
Share on other sites
47 minutes ago, Manuel said:

No - there is another id selected (1017).

And page 1017 references page 1018, right? It's a circular reference issue that seems to happen when two pages that reference each other are both loaded into memory. Probably connected to this issue: https://github.com/processwire/processwire-issues/issues/572

 

  • Like 1

Share this post


Link to post
Share on other sites
17 minutes ago, Robin S said:

And page 1017 references page 1018, right? It's a circular reference issue that seems to happen when two pages that reference each other are both loaded into memory. Probably connected to this issue: https://github.com/processwire/processwire-issues/issues/572

 

Hi @Robin S,

that would make sense. But after checking the references (only 4 pages), I can tell you they don't reference each other. Here's another screenshot.
The references are as follows:

earth (1016) --> mars (1017)
mars(1017) --> jupiter (1018)
jupiter(1018) --> merkur (1045)
merkur(1045) --> earth(1016)
screenshot.png.e0aa515e08cec5faf06647e921e839b1.png

After removing one of the d() functions as shown above, the fatal error doesn't occure.
The problem is, I want to get all pages with there references, not only n-1 😉

Share this post


Link to post
Share on other sites
29 minutes ago, Manuel said:

But after checking the references (only 4 pages), I can tell you they don't reference each other.

But they do. Not as directly as I first suggested, but there is a kind of circularity within the pages you are loading...

2019-04-18_002135.png.8dd43c264f6be780b30842eae4c45344.png

As soon as your loaded pages form a circularity the out of memory occurs. This kind of problem seems to happen particularly when a "single page" value type is defined in the field settings. I expect that if you change the field setting to "multiple pages" then the error won't occur.

2019-04-18_003019.png.f8f3ce7652f120af609bf01721f528ef.png

To be clear, I think that it ought to be possible to load pages like this using a single page field without any error occurring. I encourage you to make a report in the PW issues repo: https://github.com/processwire/processwire-issues/issues  add a comment to the existing issue: https://github.com/processwire/processwire-issues/issues/572

  • Like 2

Share this post


Link to post
Share on other sites
2 minutes ago, Robin S said:

I think that it ought to be possible to load pages like this using a singe page field without any error occurring

Wouldn't that be fixed too with the correction in the linked issue? The cited error (Wire.php line 1069) points to setTrackChanges.

  • Like 1

Share this post


Link to post
Share on other sites
2 minutes ago, BitPoet said:

Wouldn't that be fixed too with the correction in the linked issue? The cited error (Wire.php line 1069) points to setTrackChanges.

Ah, yes, you're right. So no need for a new issue, but maybe @Manuel might like to add a link to this topic in the issue discussion to hopefully bring the issue back to Ryan's attention. 🙂

Share this post


Link to post
Share on other sites

@Manuel, could you try commenting out the setTrackChanges method in core/Wire.php and replacing it with the following code?

	protected static $resetTrackChangesItems = array();

	public function resetTrackChanges($trackChanges = true) {
		$isRoot = count(self::$resetTrackChangesItems) == 0;
		
		self::$resetTrackChangesItems[$this->id] = true;
		
		parent::resetTrackChanges($trackChanges);
		foreach($this->data as $key => $value) {
			if(is_object($value) && $value instanceof Wire && $value !== $this) {
				if($value instanceof Page && isset(self::$resetTrackChangesItems[$value->id])) continue;
				$value->resetTrackChanges($trackChanges);
			}
		}
		
		if($isRoot) self::$resetTrackChangesItems = array();
		
		return $this; 
	}

 

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, Robin S said:

2019-04-18_003019.png.f8f3ce7652f120af609bf01721f528ef.png

Switching the field to Multiple Pages works fine, but for now the user is able to assign multiple planets instead of just one 🙂

Share this post


Link to post
Share on other sites
7 hours ago, Manuel said:

Switching the field to Multiple Pages works fine, but for now the user is able to assign multiple planets instead of just one

The single/multiple value type determines the type of value returned by the field. The number of pages the user can assign in Page Edit is determined by the input field type. So it's possible to use a single page selection input type (e.g. select) with a multiple page value type. But regardless we all agree that the issue should be fixed for the single page value type.

Share this post


Link to post
Share on other sites
11 hours ago, Robin S said:

The single/multiple value type determines the type of value returned by the field. The number of pages the user can assign in Page Edit is determined by the input field type. So it's possible to use a single page selection input type (e.g. select) with a multiple page value type. But regardless we all agree that the issue should be fixed for the single page value type.

You're right, a select-input would be a neat workaround to prevent a user to assign multiple pages. I agree, issue should be fixed. As a newbie tat behaviour was a bit confusing to me. Thanks to everybodies help: @Robin S @adrian @BitPoet @bernhard 🙂

  • Like 1

Share this post


Link to post
Share on other sites

My final solution to output all fields as a JSON-Object:

 

<?php

$planets = $pages->find("template=planet, sort=-title");
$planets_array = array();

foreach($planets as $planet) {
    
	$moon_array = array();
	$moons = $planet->planet_moons;
	
	foreach($moons as $moon)
	{
		$moon_array[] = $moon->title;
	}
	
    $planets_array[] = array(
        'title' => $planet->title,
		'created' => date("H:i:s d.m.Y", $planet->created),
		'modified' => date("H:i:s d.m.Y", $planet->modified),
		'type' => $planet->planet_type,
        'age' => $planet->planet_age,
		'color' => ucfirst($planet->planet_color->title),
		'moons' => $moon_array,
		'summary' => $planet->planet_summary,
		'foto' => $_SERVER['SERVER_NAME'] . $planet->planet_foto->url,
		'planet-reference' => $planet->planet_reference[0]->title
    );
}

$planets_json = json_encode($planets_array, true);
echo $planets_json;

?>

Output (JSON):

[{
	"title": "Merkur",
	"created": "20:25:29 16.04.2019",
	"modified": "14:06:19 17.04.2019",
	"type": "W\u00fcstenplanet",
	"age": "800.812",
	"color": "Brown",
	"moons": ["Merkur Mond 1", "Merkur Mond 2"],
	"summary": "Beschreibung gibt es noch erst eine sehr kurze. hier gibt es noch nicht viel zu lesen...",
	"foto": "extranet\/site\/assets\/files\/1045\/merkur.jpg",
	"planet-reference": "Earth"
}, {
	"title": "Mars",
	"created": "17:54:58 07.04.2019",
	"modified": "14:06:08 17.04.2019",
	"type": "Terrestrial moon",
	"age": "4.500.000.712",
	"color": "Red",
	"moons": ["Phobos", "Deimos"],
	"summary": "Mars is the fourth round planet from the Sun...",
	"foto": "extranet\/site\/assets\/files\/1018\/mars.jpg",
	"planet-reference": "Merkur"
}, {
	"title": "Jupiter",
	"created": "17:28:14 07.04.2019",
	"modified": "14:05:52 17.04.2019",
	"type": "Great Gas Giant",
	"age": "4,5 Billion",
	"color": "Yellow",
	"moons": ["Io", "Europa", "Kallisto", "Ganymed", "Amalthea", "Himalia", "Elara"],
	"summary": "Jupiter is the fifth planet...",
	"foto": "extranet\/site\/assets\/files\/1017\/jupiter.jpg",
	"planet-reference": "Mars"
}, {
	"title": "Earth",
	"created": "17:13:23 07.04.2019",
	"modified": "14:05:40 17.04.2019",
	"type": "Terrestrial Planet",
	"age": "15.56 Billion",
	"color": "Purple",
	"moons": ["Moon"],
	"summary": "Earth (or the Earth) is the third planet from the Sun...",
	"foto": "extranet\/site\/assets\/files\/1016\/earth-1.jpg",
	"planet-reference": "Jupiter"
}]

 

  • Like 1

Share this post


Link to post
Share on other sites

Nice! 🙂

On mobile, but you can even make it simpler by using 

1 hour ago, Manuel said:

'moons' => $moon_array,

'moons' => $planet->planet_moons->each('title')

See the API docs for WireArray. It has some nice features 🙂

Share this post


Link to post
Share on other sites

Thank you @bernhard

7 minutes ago, bernhard said:

'moons' => $planet->planet_moons->each('title')

I knew there would be a faster way to get the job done. PW is geeting better and better to me 🙂

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Guy Incognito
      I seem to be running into a repeated fatal error in a fresh PW install version 3.0.148. I can't quite put my finger on the pattern but it seems to be around deleting image fields or removing images from certain image fields.
      This is the trace from the log generated by trying to save a page and delete an image from an image field:
      Fatal Error: Uncaught Error: Cannot access protected property Pageimage::$original in /wire/core/PageimageVariations.php:256 Stack trace: 1. /wire/core/Pageimage.php(1327): PageimageVariations->getInfo() 2. /wire/core/Wire.php(386): Pageimage->___isVariation() 3. /wire/core/WireHooks.php(823): Wire->_callMethod() 4. /wire/core/Wire.php(450): WireHooks->runHooks() 5. /wire/core/Pageimage.php(1369): Wire->__call() 6. /wire/core/Pageimage.php(399): Pageimage->getOriginal() 7. /wire/core/WireData.php(333): Pageimage->get() 8. /wire/core/PageimageVariations.php(256): Pro Line 256 of /wire/core/PageimageVariations.php Earlier in the day I was experimenting with custom fields for images for the first time and kept running into this error, thinking it was me using this feature wrong and not having time to read up I deleted the custom image fields template and went about my business. So now I don't know if I triggered an issue or whether it was never related to the custom image fields in the first place?
      Any ideas?
    • By jonatan
      Hi! 😄
      SITE SETUP / DESCRIPTION:
      What? Online art magazine with an "All featured works" and also an "All featured artists" index page, and also individual "Work" and "Artists" pages, and data relations between the different artists and their artworks.
      So, I have two different page reference fields, connected by @Robin S's awesome Connect Page Fields module (though that has nothing to do with the issue in fact, Robin's plugin works great! and the issue is the same with or without it).
      The two Page Reference type fields are called "works" and "artists". They are meant to simply connect different artists to different artworks.
      Fx:
      Work 1  (page)  –> artists (Page Reference field) : Artist A (page)           --->>> (automatically connected)         Artist A (page)  –> works (Page Reference field) : Work 1 (page)
      Work 2  (page) –> artists (Page Reference field) : Artist B  (page)           --->>> (automatically connected)         Artist B (page)  –> works (Page Reference field) : Work 2 (page)
      ISSUE:
      On both Page Reference fields, both on "artists" and on "works" this option "Allow unpublished pages" is activated:

      As it says in the option description, supposedly, unpublished pages should be selectable in the page reference field, but they should not be visible, they shouldn't appear, on the front-end...
      Frontend:
      To show all works related to the artist on the artist individual page I'm doing this:
      <?php foreach($page->works as $item) { echo "<img src='{$item->image->first->width(200)->url}' class='pr-2'><a class='pr-4' href='$item->url'>$item->title</a>"; } The problem is now, unexpectedly, if some work is set to "Unpublished", it shows up anyways!
      WORKAROUND:
      So to get around this I figured out that I can do this:
      <?php foreach($page->works as $item) { if($item->is(Page::statusUnpublished)) { return; }; echo "<img src='{$item->image->first->width(200)->url}' class='pr-2'><a class='pr-4' href='$item->url'>$item->title</a>"; } But ofc this is a rather inelegant "solution" which shouldn't really be necessary, right? 
      I might be missing something basic here, but really can't figure out what it is... I hope one of you awesome guys can help me out 😊
      Thanks a lot in advance!
      All the best,
      Jonatan
    • By t0b1
      Hello there, and thanks for ProcessWire!
      I'm getting to know ProcessWire while doing my first project using it and I really like it so far.
      The challenge I'm facing right now is the following:
      I have a One-Pager using fullpage.js, realized as a single PW-Page containing a Repeater Field where each Repeater Item is one Section.
      Some Sections are supposed to have a little menu at the Top which references/links to different Sections of the Website, so I wanted to use a Checkbox Field "Top Menu" to decide if a Section gets a Menu and a Page Reference Field to choose the different Sections (Repeater Items) it should contain.
      I've already accomplished this by pasting the following code into /site/ready.php:
       
      $wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) { if($event->object->hasField == 'top_menu_entries') { $page = $event->arguments('page'); if($page instanceof RepeaterPage) $page = $page->getForPage(); $event->return = $page->; } });  
      The only problem that still remains is that when I select the Entry of the Repeater Item itself it doesnt save the selection, meaning after I saved it's unselected again.
      On some Sections I do want a Menu-Entry for the Section itself though (which would be styled differently and not link anywhere) for Continuity-Reasons, any ideas on how to achieve that?
    • By wesp
      Hello everyone,
      Is there a way to access the key number of an item in a page reference field and then output it as a value?
      So for example I want to automatically output the number 1 if the referenced page is the first in the list and have it be updated when the list is reordered via drag and drop.
      Thanks in advance!
    • By cosmicsafari
      Hi all,
      Starting work for a new client, so pulled down a copy of their existing PW site.
      All looks normal in terms of the codebase structure, set it up as I would normally for any PW site yet I everytime I attempt to view a page I get:
      From what I can gather its running PW version 2.8.
      On the live environment where I copied it from and its working fine, they are apparently running PHP 7.1 whereas I am running PHP 7.3 locally, just incase that may be a cause for the issue.
      Any ideas as nothing seems obvious to me at this point.
       
       
×
×
  • Create New...