Jump to content
blynx

Custom PHP code selector

Recommended Posts

Hej,

i am trying to build a custom PHP code selector to get all pages using a user template for a site using multiple templates for users.

Here are my two non-working approaches:

/**
 * A
 */
return function() {
$template_ids = implode("|", $config->userTemplateIDs);
return $pages->find("template=$template_ids, include=all");
};


/**
 * B
 */
return $pages->find("template=".implode("|", $config->userTemplateIDs).", include=all");

Maybe I am thinking too complicated and I miss something here - basically I need a Page Field which can select from all users with all the different user templates ...
uhm - has anyone an idea how this might work?

Also in general - has anyone an idea what is actually possible with this custom php code selector? I guess it is somewhat restrained?

Thanks!
Steffen

EDIT:

I guess that I can't access $config?

Share this post


Link to post
Share on other sites

I think that context can't access the $config variable. You could try wire('config')...

What else: I'm not fully 100% sure that "template="..." would work you could also try "template.id="...".

  • Like 1

Share this post


Link to post
Share on other sites

The custom php code is executes as part of InputfieldPage and therefore all api variables are accessable as $this->… . Only $pages as $page are available as local variables.

  • Like 2

Share this post


Link to post
Share on other sites

Yes!

Thanks @LostKobrakai, thats it - should've tried that one too ...
@Martijn Geerts, yep - I also tried wire('config') but that didn't work either – and I was not sure about `template=` vs. `template.id=`, too ... both work though ;)

PS:

Is there actually some kind of summarized documentation of where which variables are scoped and why? Like to get to know some underlying concepts of processwire? Or a forums thread where things like that are explained more thoroughly?

  • Like 1

Share this post


Link to post
Share on other sites

There are basically four different environments to talk about.

  1. TemplateFile
    TemplateFile is core class, which does include your template files, but does also power things like $page->render(), wireRenderFile(), wireIncludeFile() and others. This class will automatically make all API Variables available as local variables. Meaning all those included files can directly use $pages, $page, … . It won't work inside any functions defined in those files, because of the way PHP does scope variables.
  2. Classes extending Wire
    Every class, which is extending the Wire class will have access to API variables via $this->pages, $this->page, if the properties or __get() are not overwritten. Also there's $this->wire('pages'), which is less likely to be overwritten (even some core classes need to use $this->wire()).
  3. Anonymous functions
    There are some methods in the processwire code, which accept anonymous functions as parameters (e.g. WireCache). Those anonymous functions can retrieve api variables as parameters, even though I'm not sure how exactly this is working or if that's often used.
  4. Everywhere else
    Outside of wire classes, template files and special anonymous functions there's the wire() function, which is basically the same as $this->wire() in wire classes, but as a global function, which is accessable anywhere after pw is started.
    With PW 3.0 and multi-instance this is the option to avoid.

Places, which technically are number 2, but it may not be apparent to everybody:

Custom PHP code for fields like FieldtypePage or FieldtypeMarkup:
As those PHP code is evaluated/run inside those (input)field classes there's (besides manually available local api variables) always the option to use $this->pages or $this->wire('pages').

All those template files included by the TemplateFile class:
For the same reason as above there's not only $pages available in those template files, but also $this->pages, $this->wire('pages').

  • Like 10

Share this post


Link to post
Share on other sites
On 11. August 2016 at 8:47 PM, LostKobrakai said:

Everywhere else
[...]

With PW 3.0 and multi-instance this is the option to avoid.

Great overview, Benjamin!

Have you any reference on this or could you explain why we should avoid wire(). What's the best way to go, using $this?

Share this post


Link to post
Share on other sites

It's because all other options are aware of their instance (e.g. a page of instance1 will get the configs of instance1), whereas the global wire function does not have state and therefore does only ever return the "primary" instance, which is simply the first one ever instantiated.

Edit: Maybe 'avoid' it to hard, but one needs to be aware that the function is not aware of additional instances. Especially in hooks or alike, where people are currently often using wire() one should rather use $event->wire() so the hook is not prone to using a different instance than intended.

  • Like 4

Share this post


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

It's because all other options are aware of their instance (e.g. a page of instance1 will get the configs of instance1), whereas the global wire function does not have state and therefore does only ever return the "primary" instance, which is simply the first one ever instantiated.

Thanks for the explanations. Is there an instance-aware way to get API variables in function scope?

Share this post


Link to post
Share on other sites

There isn't one, other than passing the instance into the function as parameter. But really a class is way better in handling this kind of state. 

<?php namespace ProcessWire;

class Helpers extends Wire{
	
	public function getGlobalSeo()
	{
		return $this->wire('pages')->get('/')->seo;
	}
}

In the init.php

$helpers = $this->wire(new Helpers); // Wire the instance into the helpers class
$this->wire('helpers', $helpers); // Add as api variable

In your templates

$seo = $helpers->getGlobalSeo();

 

  • Like 4

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By jds43
      Hello, I have a Page Reference by template radio button field to promote a certain page (only two options), but I'd like to target the page that isn't selected. This would be used dynamically throughout the site.
      Does anyone know how I could accomplish this? Would I use something like remove() or not()?
       
    • By Hubris
      Hi there!
      I'm using some page reference fields to create lists of tags, categories, years, etc.. I'm able to find the pages like so:
      $pages->find("template=project, {$filter}={$page->title}"); Which dynamically does something like: 
      $pages->find("template=project, tags=Experimental"); Only if the value (the page name, like "Experimental") starts with letters. If it starts with numbers, find returns nothing.
      Why is this and how can I fix it?
    • By Elchin
      Hi.
      I want select pages where now between date and end_date or now bigger than date and end_date is empty.
      I have five tried variants:
      $start = strtotime(date('Y-m-d') . " 00:00:00"); $results = $page->children("foo=(date<$start,date_end=''),bar=(date<$start,date_end>=$start),sort=-date,limit=12"); $start = strtotime(date('Y-m-d') . " 00:00:00"); $results = $page->children("date<$start,(date_end='',date_end>=$start),sort=-date,limit=12"); $start = strtotime(date('Y-m-d') . " 00:00:00"); $results = $page->children("date_end=''|date_end>=$start,date<$start,sort=-date,limit=12"); $start = strtotime(date('Y-m-d') . " 00:00:00"); $results = $page->children("!date_end|date_end>=$start,date<$start,sort=-date,limit=12"); $start = strtotime(date('Y-m-d') . " 00:00:00"); $results = $page->children("date_end>=$start|!date_end,date<$start,sort=-date,limit=12"); All this variants not worked for me and returned zero results.
    • By pwFoo
      I played with the Selectors object and would like to use it for a special use case...
      That is a custom Selectors object with dummy data converted to an php array to see the structure (Selectors object is a WireArray with "fields" added)
      Array ( [0] => Array ( [0] => Array ( [field] => seg1 [value] => val1 [not] => [group] => [quote] => [forceMatch] => ) [1] => Array ( [field] => seg2 [value] => val2 [not] => [group] => [quote] => [forceMatch] => ) ) )  
      But instead of "seg1" the field name is "field" with value "seg1" (= my field name).
       
      So I can't search the Selectors WireArray (= custom WireArray with added Selectors objects) with PW "find('seg1=val1')", Is there a way to search with "find()" or build a simple wrapper to make the elements searchable / filterable with find()?
    • By celfred
      Hello,
      I'm facing a weird behavior (to me)... Why are these requests not returning the same values ?

        // Test 01 : not working > returns empty $allPlayers = $pages->find("team=$team"); // Returns the 10 players (1 of them has HP=14, others have HP>15, no players have coma=1) $dangerPlayers = $allPlayers->find("(HP<=15), (coma=1)")->sort("coma, HP"); // Returns nothing ??? // Test 02 : Working as expected $dangerPlayers = $pages->find("parent.name=players, team=$team, (HP<=15), (coma=1)")->sort("coma, HP"); // Returns the low HP player
      If you can explain this to me, I would appreciate because this is causing me a headache right now 🙂 
      Thanks !
×
×
  • Create New...