Jump to content

Module: Create a Pages->find(query) as a field


alevine
 Share

Recommended Posts

All:

  If you saw some of my recent postings where I was trying to solve the problem of running a query as a field, I have solved it.

I started with Hanna text, but that didn't quite get me all the way.  Then I tried just a Concat field, and that didn't get me all the way.

I modified the Concat fieldtype for my solution.  I had a need to dynamically pull Pages that were cross-referenced back:

   Product as a Page

   Photo Pages with a  multi-Page Select field that referenced Product (A photo could represent 1+ Products)

I wanted a ->photos field from Product that was updated dynamically according to what Photo entries were currently in place, and I didn't want copy/pasted code, and I wanted the selectors to be easily modifiable from the admin screens.

Usage is faily simple:

1:  Install as a normal module

2:  Create a field as a PagesSelectorQuery type

3: On the field details, enter your selector string, ie: template=my_template,select_page_field=$page

4: Add your field to whichever templates.

5: Access the PageArray results like you would any other $page->field

I hope you find it useful, at the very least as an exercise in my madness.  :)

Thanks again for all the help this community has provided.

EDIT:  Added to GitHub:  https://github.com/alevinetx/processwire-modules/blob/master/FieldtypePagesSelectorQuery.module

And Module's page:  http://modules.processwire.com/modules/fieldtype-pages-selector-query/

FieldtypePagesSelectorQuery.module

  • Like 2
Link to comment
Share on other sites

Trying to figure out pros and cons of using this module because I'm doing something where I have a selector saved in a Page's text field and then do the find at render time. The module would have done that find, giving me a PageArray to use in the render. But I see that the find is done by runSelectorQuery() which is called by the wakeValue, sleepValue, loadPageField hooks. I'm new to a lot of this fieldType/hook stuff but isn't it redundant to do the find in the sleepValue hook?

Link to comment
Share on other sites

Trying to figure out pros and cons of using this module because I'm doing something where I have a selector saved in a Page's text field and then do the find at render time. The module would have done that find, giving me a PageArray to use in the render. But I see that the find is done by runSelectorQuery() which is called by the wakeValue, sleepValue, loadPageField hooks. I'm new to a lot of this fieldType/hook stuff but isn't it redundant to do the find in the sleepValue hook?

I think you see the pros.  As for the cons, I'm still new to PW, but the others haven't offered any comments about this being a bad thing. 

As for when the query is run, I honestly don't know either.  I pretty much did a blind copy from the Concat field, which is also a run-time/invocation-time process.  Hopefully Ryan and the others can provide some insight as to whether it should be called on all the hooks, or just some.

Link to comment
Share on other sites

Trying to figure out pros and cons of using this module because I'm doing something where I have a selector saved in a Page's text field and then do the find at render time. The module would have done that find, giving me a PageArray to use in the render. But I see that the find is done by runSelectorQuery() which is called by the wakeValue, sleepValue, loadPageField hooks. I'm new to a lot of this fieldType/hook stuff but isn't it redundant to do the find in the sleepValue hook?

The loadPageField() method is what loads the raw value from the database and returns it as an array. Most Fieldtypes just inherit the base Fieldtype method of doing this. But in this class, it has to be implemented since it doesn't actually load anything from the DB. 

The wakeupValue() method is what gets called to convert a raw value (typically an array) to an object, if required by the fieldtype. For instance, the Page reference Fieldtype converts it from an array of page IDs (numbers) to a PageArray of Page objects. If the raw value doesn't need any conversion to something else, then the function can just return the raw value. wakeupValue is typically dealing with values loaded from the database (via the loadPageField method). But wakeupValue can't assume that, it doesn't know where the value came from... it could have come from some other web service, data source or import function. That's why loadPageField and wakeupValue are separate things, and both necessary. 

The sleepValue() method is the opposite of wakeupValue(). It converts the value from a runtime representation back to a raw representation, suitable for storage in a DB or web service feed, etc. For instance, in the Page reference field type, it converts the value from a PageArray back to a regular PHP array of page IDs. 

If the page is being saved, the savePageField() receives the value generated from sleepValue() and saves it to the DB. It expects that value to either be a raw value: array of [column => value], string or integer. Like with loadPageField, most Fieldtypes inherit this from the base Fieldtype class. 

Lastly is the formatValue() function, which is what is used to provide any additional front-end, runtime formatting for a value where necessary. For example, text-based Fieldtypes use this to run formatters like Markdown or HTML entities. The formatValue function is only called if the "output formatting" mode for the page is ON. The formatValue() function is called on every access to $page->your_field_name, so the unformatted value is always still retained with the page. 

Given the above, there are a few different ways you could approach implementation of these functions. For instance: 

  • Make loadPageField return the result of runSelectorQuery
  • Make wakeupValue return the value it's given, assuming it's a PageArray. If it's a regularly array, assume it's page IDs and convert to a PageArray.
  • Make sleepValue convert the $value (PageArray) it's given to an array of Page IDs and return that. 

Another possible approach:

  • Make loadPageField return the selector string
  • Make wakeupValue convert the selector string to a PageArray (calling your runSelectorQuery)
  • Make sleepValue return the selector string

In this case of this Fieldtype, you'd basically just have to think about how you'd want the value represented externally in a CSV file or web service (for instance). Would that be an array of Page IDs or the selector string the generated them? The selector string may be more portable in that context. 

Link to comment
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
 Share

×
×
  • Create New...