Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


psy last won the day on January 22

psy had the most liked content!

Community Reputation

763 Excellent


About psy

  • Rank
    Hero Member

Contact Methods

  • Website URL

Profile Information

  • Gender
    Not Telling

Recent Profile Visitors

3,984 profile views
  1. @PCuser Glad to help. Suggest editing your original post and inserting [solved] to the start of the title ๐Ÿ˜Š
  2. @PCuser there many ways to sanitise data using $sanitizer, eg pageName, digits, text, camelCase, etc, which is why you need to let $sanitizer know which method to use. They're all listed in the documentation. ๐Ÿ˜Š
  3. @PCuser you need to let Sanitizer know what kind of clean-up to do, eg: $sanitizer->pageName($sportspage->title) will convert the title text to lowercase and replace spaces with hyphens to make it suitable for use in a URL (or HTML id attribute). See what other $sanitizer methods are available at https://processwire.com/api/ref/sanitizer/ PS: Page titles can change and also not be unique. I prefer to use a letter first (HTML ids must start with a letter) then use the page ID, eg s1234. Alternatively, you could use the existing page name rather than the title.
  4. @joe_ma Maybe something like (untested): <?php $content .= '<main class="front">'; // Container for circles $content .= '<ul class="topCircles" role="navigation">'; // nav list // Output of 16 li elements with links at the chosen postions $items = $page->children("limit=16, sort=sort"); // PageArray limited to 16 items. Sorted according to template/page children settings foreach ($items as $item) { if ($item->front_position == $item->index() { $content .= '<a href="' . $item->url . '">' . $item->title . '</a>'; } $content .= '</li>'; } $content .= '</ul> </main>'; // Ende Liste und Container From the PW API Docs: https://processwire.com/api/ref/page/index/
  5. @joe_ma not sure if it's the issue but seems to me you're using a PHP array functions on a ProcessWire PageArray object - different beasts Is not a PHP array. It is a ProcessWire PageArray.
  6. Those subpages are now linked to your home page and you change your home page template to show what fields you want. For example, if your page reference field is called 'featured', in your home page template you can choose what fields you need to show from the subpage. <?php foreach ($page->featured as $apartment) : if ($page->featured->first->id == $apartment->id) : // it's the first one ?> <div class='featured first'> <h2><?=$apartment->title?></h2> <p>Bedrooms: <?=$apartment->bedrooms?></p> <p>Bathrooms: <?=$apartment->bathrooms?></p> <p>Price: <?=$apartment->price?></p> </div> <?php else: // it's not the first one ?> <div class='featured'> <h3><?=$apartment->title?></h3> <p>Bedrooms: <?=$apartment->bedrooms?></p> <p>Bathrooms: <?=$apartment->bathrooms?></p> <p>Price: <?=$apartment->price?></p> </div> <?php endif; endforeach; ?>
  7. Hi Brandy and welcome to ProcessWire There are many ways to achieve what you want. Hardest part is deciding which method works best for you and you client, eg: On your home page template you could have a Page reference field that allows your client to choose the featured projects and make the first the "main" project. For output, loop through the chosen page references and ensure the main project (page reference Project #1), gets different, more prominent styling. Use Tags on Project pages, eg "Home page featured" & "Home page other". Then in your home page template, use a selector to get the featured projects and loop through as above Based on info you supplied, I'd go with option 1 Hope this helps
  8. Just tested and it works a treat ๐Ÿ™‚ When a frontend user enters their event date, in _init.php: <?php if (!empty($input->post->availability)) { $availability = $sanitizer->date($input->post->availability, 'Y-m-d'); $sameDayBookings = $pages->find("template=booking, booking_date=$availability, booking_status!=pending|cancelled",['loadOptions'=>['autojoin' => true, 'joinFields' => ['booking_items']]]); $cache->save('sameDayBookings', $sameDayBookings); } This query takes no time at all. Next, in my custom module: <?php /** * @param Page $item - product page * @return int|void * @throws WireException */ public function itemAvailability(Page $item) { if ($item instanceof NullPage) return; $itemBookingCount = 0; $otherBookings = $this->wire('cache')->get('sameDayBookings'); if ($otherBookings->count > 0) { // there are other booking on the same event date foreach ($otherBookings as $otherBooking) { foreach ($otherBooking->booking_items as $otherBookingItem) { if ($otherBookingItem->booking_item->id == $item->id) { $itemBookingCount = (int)$itemBookingCount + (int)$otherBookingItem->booking_qty; } } } } $itemsAvailable = (int)$item->qty - (int)$itemBookingCount; return $itemsAvailable; } Query times for this function went from an average of 3.5sec to under 0.01 seconds per item and under 1sec to render the page listing multiple items with their availability. Happy dance time! Thank you all!
  9. Grateful for all your suggestions and you gave me an idea. Didn't get a chance to test today but will try tomorrow. It's a conglomeration of your suggestions. in _init.php prepended to all pages (or maybe refined to only the pages on which it's needed ?), collect all bookings for the day, regardless of individual item ids and cache it. Historical bookings won't change and without the repeater stuff, will be quick; instead of going back to the db for all calls, run the individual item queries on the cached page array - at most 20 items Will report back ๐Ÿ™‚
  10. @dragan No question you ask is ever dumb! I should have made it clearer. Each item is a page, a product page. The qty is an integer field and refers to how many units of that product are owned by the client. The $limit is set to that number. The query searches through other bookings for that item on the nominated day, and on each match, subtracts the booking_qty from the item qty, to return how many are left for hire on that date. When all are booked out, the front-end customer cannot add it to their cart to prevent over-booking. A count wont do it as other bookings may have booked 2 or more units of the same item on that day.
  11. @BillH Thanks, I tried RockFinder3 a while ago. It's certainly a great module however I couldn't figure out how to get it working with Repeater fields. It's perfect with direct relation fields, eg PageReference but Repeaters are different beasts. Not sure if RF3 handles '.' separated fields in the selector, eg "booking_items.booking_item.id" either?
  12. I have a $pages selector that works great in giving me the requested info. However it's incredibly slow. Added to this, the request may be called up to 15 times on a particular page for 15 different listed items. <?php // in my custom module... // retrieves qty of items already hired on a particular day to determine availability for new bookings // booking_items is a repeater field and booking_item are repeater pages // I already have the $item and the $eventDate // Query is searching through 5K+ bookings and at least 3x that many booking_item repeater pages $limit = $item->qty; $selector = "template=booking, booking_items.booking_item.id=$item, booking_date=$eventDate, booking_status!=pending|cancelled, limit=$limit"; $pp = $this->wire()->pages; $otherBookings = $pp->find($selector); Each item query can take between 2 to 8 seconds ๐Ÿ˜ฌ What can I do to speed up this query? TIA psy
  13. Had an extreme example to deal with recently. Multiple field replacements for various fieldtypes. May not be the best approach but worked for me. Private function is in a custom module function. <?php /** * Takes a page field, eg 'body' as a template and replaces tags eg {age} with the same field value * from the supplied data page * @param $tplPage * @param $tplField * @param $dataPage * @param string $startTag * @param string $endTag * @param array $other * @return string|string[] * @throws WireException * @throws WirePermissionException */ private function _compileFieldTags ($tplPage, $tplField, $dataPage, $startTag = '{', $endTag = '}', $formatDate = false, $other = []) { $allowedFieldtypes = [ 'FieldtypeText', 'FieldtypeTextarea', 'FieldtypeInteger', 'FieldtypeFloat', 'FieldtypeDatetime', 'FieldtypeToggle', 'FieldtypeCheckbox', 'FieldtypePage' ]; $replacementNames = []; $replacementValues = []; // Sort out what to do with each inputfield type foreach ($dataPage->fieldgroup as $replacement) { if (!in_array($replacement->type, $allowedFieldtypes)) continue; switch ($replacement->type) { case 'FieldtypeDatetime': $fldData = $formatDate == false ? $dataPage->$replacement : $dataPage->getFormatted($replacement); break; case 'FieldtypePage': $fldData = $dataPage->$replacement->title; break; case 'FieldtypeCheckbox': $fldData = $dataPage->$replacement == true ? "Yes" : "No"; break; default: $fldData = $dataPage->$replacement; break; } $replacementNames[] = $replacement->name; $replacementValues[] = $fldData; } // Prepare replacement arrays foreach ($dataPage as $k => $v) { $replacementNames[] = $startTag . $k . $endTag; $replacementValues[] = $v; } $replacementNames['url'] = $startTag . 'url' . $endTag; $replacementValues[] = $dataPage->httpUrl; $result = str_ireplace($replacementNames, $replacementValues, $tplPage->$tplField); return $result; }
  14. Trying to upgrade TD to the latest version and I get this: Fatal Error: Uncaught WireException: No download URL specified in wire/modules/Process/ProcessModule/ProcessModule.module:1072 Happens both on the Modules->New and Settings->Upgrades with the upgrade module. I could upload the zip but that's not the issue. Reason for upgrade was another error message: Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in [no active file]:0 Stack trace: #0 {main} thrown in [no active file] on line 0 which auto-magically began appearing. I'm not serializing any data and the error disappears when I turn off TD. Any ideas on what's happening here?
  15. @Knubbi that's a question for Ryan in the ProDrafts forum ๐Ÿ™‚
  • Create New...