Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


BillH last won the day on April 21 2022

BillH had the most liked content!

About BillH

  • Birthday 03/06/1962

Contact Methods

  • Website URL

Profile Information

  • Gender
  • Location
    London, UK

Recent Profile Visitors

1,786 profile views

BillH's Achievements

Sr. Member

Sr. Member (5/6)



  1. I'd suggest you use the core Lazy Cron module to trigger loading the JSON. Note that, as described on https://processwire.com/docs/more/lazy-cron/, Lazy Cron hooks into ProcessPageView::finished() to avoid slow page loads.
  2. My guess would be that it's the line getting a value for $event where things start to go wrong. I'm wondering in particular where you're getting the value of $id from, and whether it's valid? You might want to try var_dump() to check whether $event actually is an object (and if so, if it looks as if it might be a repeater item): var_dump($event);
  3. Using findRaw() you get a normal PHP array (not a PW page array). And the value for select_countries is itself an array. So you can do this: foreach($items as $item) { foreach($item['select_countries'] as $country) { echo $country['title']; } } I'm not sure what findRaw() returns if your page selector field is set to a single page, but you may need to simply use $item['select_countries']['title'] rather than the inner foreach.
  4. It seems that, as @kongondo notes, there's an issue with the findRaw() syntax, at least with the array-type syntax and page-reference fields. However, the dot syntax seems to work. So I think the following will give you what you need: $items = $pages->findRaw("template=template-news, select_region=austria, limit=2, objects=1", ["select_countries.id", "select_countries.title"]); Or slightly simpler, as the keys of the returned array of page references are the page ids: $items = $pages->findRaw("template=template-news, select_region=austria, limit=2, objects=1", ["select_countries.title"]); I've submitted an issue regarding the other syntax: https://github.com/processwire/processwire-issues/issues/1563
  5. If a find() is too slow, use findMany() with a suitable selector: https://processwire.com/api/ref/pages/find-many/. Or if that's still too slow, or if you find them preferable for some other reason, use findJoin() or findRaw(), as described in the blog post at https://processwire.com/blog/posts/find-faster-and-more-efficiently/. Another option would be to try RockFinder3: https://processwire.com/modules/rock-finder3/.
  6. If you want to do something if the page has not yet been created: if(!$page->id) { // Do something here }
  7. I haven't tried, but you may be able to do it by hooking on ProcessPageList::find, as discussed here: Note that the pages would have to be loaded and the sort codes calculated each time the page tree was displayed, so I think the approach I have suggested would be more efficient – something that is discussed in the thread too.
  8. The way I've done things like this is to create a text field, use a hook to add a sort code to that field, then set each relevant parent template to sort its children using that field. The sort code would be whatever you'd normally sort by, but with a prefix that depends on whether the page has children or not. So, I'd use something like the following (not tested) in ready.php, here assuming you'd basically sort on title: $this->addHookAfter('Pages::saveReady', function($event) { $page = $event->arguments[0]; if(in_array($page->template, array('template1', 'template2', 'template3'))) { $page->of(false); if($page->numChildren() > 0) { $sortcode = "A-" . $page->title; ) else { $sortcode = "B-" . $page->title; } $page->set('sortcode', $sortcode); } }); Of course, you could use a hook in a module instead. And you can use the same basic technique to get just about any kind of sort order you want.
  9. Perhaps the easiest thing to do would be to make the fields of the user-facing form required, perhaps using JavaScript, or adding the required attribute: <input type="text" id="role" name="role" required> If you want to hook into the module, take a look at https://github.com/ryancramerdesign/LoginRegister. If all else fails, hooking before Inputfield::render (see the example on the page just mentioned) and then replacing strings in the form HTML is an option.
  10. Yes, I noticed that too in the post https://processwire.com/talk/topic/26947-craft-cms-and-processwire-– a-comparison/?do=findComment&comment=222902 (I assume this is the one you mean), although the exact statement is "borderline deprecated". I too was going to comment because language alternate fields are really useful and I make good use them. It's not just image fields, but other non-text field types. For example, there might be a checkbox that can take values specific to each language, or a localized URL for each language, or different attached files (e.g. PDFs in each language). In general, language-alternative fields become really valuable when producing different versions of output for each language, rather than simply having translations of text. Another purpose for which language-alternate fields can be better, even for text fields, is when building interfaces and outputs for translators - for example, if in the admin one needs to display versions of text in different languages side by side, or grouped in fieldsets by language. So from me it's a big vote for keeping language-alternative fields undeprecated!
  11. It occurs to me that with SQL you could write a user-defined function for comparing sets of tags, but this still might run into problems with execution time. I suspect @Robin S's idea is a much better approach!
  12. I could be wrong, but I don't think findRaw(), RockFinder or SQL have any way of returning a result that depends on how many items records have in common. And anyway, to make comparisons between every pair among 20k projects, you'd be looking about 400 million comparisons – which is going to take a while! So, it seems to me that either: you need to think of an algorithm that doesn't involve comparing each project with every other; or you'll need to use a different metric of similarity between projects – or even rank by something other than similarity. Considering the algorithm, I'm wondering if there's an approach that would run in a time dependent on projects * tags (rather than projects * projects), though I don't know if this is possible - and I suspect it'd be really difficult to come up with something. Using a different way of ranking the projects might be much easier, and perhaps equally meaningful - indeed, now that I think about it, I wonder how useful ranking by degree of similarity would be. An alternative, just for example, might be something like ranking the tags by popularity (number of projects they appear in), then give each project a score depending on the ranks of its tags (the mean, or median, or sum of the top three, or something like that).
  13. An interesting problem, but I'm fairly sure there's no solution using PW selectors. As far as I can see you'd need to compare the tags for each project to those every other project, keep track of the results, and then sort by those results. You could get the data you need into an array quickly by using something like: $tagsForAllProjects = $pages->findRaw("template=project", "tags"); However, as you've probably realised, if you have many projects, it could take a long time to work though making the comparisons. Even though you only need to compare each pair of array items once (perhaps using array_intersect()), if I've got this right (which I might not have done!) it'd take n(n-1)/2 operations – so for 100 projects about 50,000 and for 1,000 the best part of half a million. But perhaps someone knows a better way.
  14. Some of your questions will be answered by reading through the articles listed at https://processwire.com/docs/modules/, particularly the first three. Also really helpful are the Hello World example modules described in the blog post https://processwire.com/blog/posts/pw-3.0.181-hello/. And another excellent post is https://processwire.com/blog/posts/building-custom-admin-pages-with-process-modules/. These will probably give you enough to start building useful modules. And I'd suggest that building a module or two (especially by following examples) would be the best way to get started, working things out as needed.
  15. PDFObject is useful for making the most of browsers' PDF capabilities and for setting up fallbacks – particularly for mobile browsers.
  • Create New...