Is there a way to make a widget call itself recursively? I am trying to build something similar to the native menus of WordPress, but I cant seem to get it done.
This is the code of what I have tried:
class SCTSubsections extends SiteOrigin_Widget { function __construct() { parent::__construct( 'sct-subsections', __('Subsections', 'sct-subsections-text-domain'), [ 'description' => __('Subsections', 'sct-subsections-text-domain'), 'panels_title' => false, 'panels_groups' => ['dummy-widgets'], ], [], [ 'title' => [ 'type' => 'text', 'label' => __('title', 'sct-subsections-text-domain'), 'default' => '' ], 'sections' => array( 'type' => 'repeater', 'label' => __( 'Sections.' , 'sct-subsections-text-domain' ), 'item_name' => __( 'Section', 'siteorigin-widgets' ), 'item_label' => array( 'selector' => "[id*='repeat_text']", 'update_event' => 'change', 'value_method' => 'val' ), 'fields' => array( 'section' => [ 'type' => 'widget', 'label' => __( 'Subsections.', 'sct-subsections-text-domain' ), 'class' => 'SCTSubsections', ], ) ), ], plugin_dir_path(__FILE__) ); } } siteorigin_widget_register('sct-subsections', __FILE__, 'SCTSubsections');
But this do not seem to be working. When this code is present, WordPress just returns me a blank screen. Am I going about this the wrong way?
Hi Enrique,
The provided PHP is likely resulting in an infinite loop – the widget is infinitely loading and embedding a new instance of itself. It is possible to make a widget load itself again but you need to add something in place to prevent this from happening infinitely. What that something could be I’m not too sure. Can you please elaborate on what you’re specifically trying to do? Can you partially offload this into two widgets (one of which doesn’t load itself again)?
Well, it is only an infinite loop in the repeater has more than 0 elements, no? If the repeater is empty, there should be no infinite loop.
It is kinda like recursion, where you have a “base case” that stops the loop.
About the “separate in 2 widgets” technique: I had already thought of that and the outcome is exactly the same.
What I am trying to build is a menu, like the ones that WordPress uses. It is really an index for a document, where each index may (or may not) have subsections. I am going to use it to set links to different pages inside a PDF file.
Hi Enrique,
In theory, yes. However, we need to generate the repeater template when the widget form options are loaded and that will result in the repeater repeatability loading the same widget over and over again.
Can you please provide me with a copy of the second widget code so I can check over that? Ideally, if possible, can you please provide me with a copy of your entre plugin? This will allow me to test using your copy and rule out any structural differences caused by the (potentially) different method of adding the widget(s) code.
This is what I have tried to do, with the “separate in 2 widgets” strategy:
Hi Enrique,
Thanks. I can confirm an infinite loop is occurring with the provided widgets file:
This infinite loop is caused when the widgets loading itself for templating purposes and due to the widget infinitely loading itself, it’ll hit the maximum function nesting limit. To avoid this, it’s recommended you create a dedicated widget that handles creating sections and then insert that widget into another widget rather than having that widget load itself.
You mean like a “Sections wrapper”?
Hi Enrique,
Yes. The problem with your code is that the widget is embedding itself and that results in the infinite loop. You need to either embed another widget that doesn’t embed itself (or the parent widget), or add the fields directly to the widget rather than embedding any widget.
Do you mean something like this?
Because this doesnt work neither
Hi Enrique,
The provided widgets will result in the same infinite loop due to the widgets embedding each other an infinite number of times – a always loads b, b always a, and the cycle always repeats. If you add a widget to a widget, that same widget cannot load itself (ie. SCTSection cannot load SCTSection) or the parent (SCTSection cannot load SCTListOfSections as SCTListOfSections will load SCTSection which in turn will load SCTListOfSections, etc) or an infinite loop will occur.
SCTListOfSectionsWrapper should load SCTListOfSections. SCTListOfSectionsWrapper doesn’t load SCTListOfSectionsWrapper or that would result in an infinite loop.
SCTListOfSections should load SCTSection. It doesn’t load SCTListOfSectionsWrapper, or itself as that would result in an infinite loop.
SCTSection doesn’t load SCTListOfSectionsWrapper, SCTListOfSections, or itself as that would result in an infinite loop.
Kind regards,
Alex
> SCTSection doesn’t load SCTListOfSectionsWrapper, SCTListOfSections, or itself as that would result in an infinite loop.
If `SCTSection` cannot load any of the 3 classes, how am I supposed to make it recursive? What should SCTSection load then?
Hi Enrique,
The SCTSection should contain the desired fields and then you can repeat wrapping it inside of a the repeater form field – the widget itself shouldn’t embed itself as that will result in an infinite loop.