Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 01/21/2015 in all areas

  1. New year, new site online http://schutzbelueftung.de/ This time industry client, they build ventilation systems for diggers, earth movers and stuff like that. Pretty interesting. English version is in the works, should be ready by march. This is the second page featering my pagetable extended module, with which the client can easily build an individual layout out of predefined layout elements. That means: Everything on the site is filled by the client, all images and text. One special thing is the database of their installations: http://schutzbelueftung.de/aufbaubeispiele/ Here you can filter by company, type field of application. This is done by ajax in the background, so easy to build with the PW selectors <3
    8 points
  2. since everyone is trying to make themes based on their own wishes and needs, I tried to have a view from our clients: what do they really need? how often? what should they see and what not...? so I ended up with a really clean theme. the trash page will not be shown in the page tree. I'll move it in the right bottom corner. some footer informations are not necessary to be visible all the time (eg. pw version, copyright). I want to hide them behind a button. I often see people looking for a "back button" because they don't want to use the browser back button (don't know why - maybe just my view?). some ideas for other features (like custom colors)? let me know what you think. thanks
    6 points
  3. -------------------------------------------------------------------------------------------------------------------------------- for PW 3.0+ please follow this link! -------------------------------------------------------------------------------------------------------------------------------- Croppable Image Module for PW >= 2.5.11 and PW <= 2.7.3 Version 0.8.3 alpha Hey, today I can announce an early (alpha) release of CroppableImage, what was forked from Anttis Thumbnails module. Until now there was a lot of work done by owzim, Martijn Geerts and me. We have solved the issues regarding the list from here: The modules are bundled together so that you only can and have to use FieldtypeCroppableImage for install, uninstall & configure. It uses new naming scheme that was introduced with PW 2.5.0 that supports suffixes. The complete image rendering is delegated to the core ImageSizer, or to any optional hooked in rendering engine. Template-settings are now fully supported, including removing variations when settings have changed. It fully respects settings for upscaling. If upscaling is set to false, you cannot select rectangles smaller than the crop setting. We implemented these enhancements: The GridView now is very nice and compact, and also benefits from the lately introduced setting for $config->adminThumbOptions. Permanent storage of the crop coordinates, quality and sharpening settings are now implemented native. No need to use PiM for this anymore. The usage/display of the Quality and Sharpening DropDown-Selects can be globally disabled/allowed in the modules Configpage. (additionally to that a setting on a 'per field base' is planned.) And the most wanted feature by the community: It gives back a pageimage and not the URL-string. This way you can use it like this: // get the first image instance of crop setting 'portrait' $image = $page->images->first()->getCrop('portrait'); You can further use every pageimage property like 'url', 'description', 'width' & 'height' with it: // get the first image instance of crop setting 'portrait' $image = $page->images->first()->getCrop('portrait'); echo "<img src='{$image->url}' alt='{$image->description}' />"; And you can proceed further image rendering with it: // get the first image instance of crop setting 'portrait' and proceed a resize with imagesizer $image = $page->images->first()->getCrop('portrait'); $thumb = $image->width(200); // or like this: $thumb = $page->images->first()->getCrop('portrait')->width(200); // and if you have installed Pia, you can use it here too: $thumb = $page->images->first()->getCrop('portrait')->crop("square=120"); The only downside with this is that when you (as the site developer) have enabled the usage of DropDown-Selects in the images editor, you do not know the values the editors have chosen for the images. As a workaround for this you can use the getCrop() method with a second param. This is a PW selector string. It can contain as many of the known pageimage options like 'quality', 'sharpening', 'cropping', etc, as you need, but none of them is required. But required is at least one setting for 'width' or 'height': $image = $page->images->first()->getCrop('portrait', "width=200"); $image = $page->images->first()->getCrop('portrait', "width=200, height=200, quality=80"); $image = $page->images->first()->getCrop('portrait', "height=400, sharpening=medium, quality=75"); . . You can get the module from GitHub: https://github.com/horst-n/CroppableImage (Better Docs are coming soon) Screenshots Related Infos A good setting in site/config.php for the AdminThumbs are: (height=>200 and scale=>0.5 !) $config->adminThumbOptions = array( 'width' => 0, 'height' => 200, 'scale' => 0.5, 'imageSizer' => array( 'upscaling' => false, 'cropping' => true, 'autoRotation' => true, 'sharpening' => 'soft', 'quality' => 90, 'suffix' => array(), ) );
    4 points
  4. Hi, Another way to do this is to use subselectors, which were introduced in Processwire 2.5. The code would then be: $pages->find("parent.id=[pagefield1.pagefield2.field=value]"); I love subselectors...
    4 points
  5. Okay, so I've actually decided to rename the module to ProcessJumplinks. I prefer it. https://github.com/mike-anthony/ProcessJumplinks Hit counter is done. Still need to work on importing from Redirects module - I'll do that tomorrow as I'm super-tired now. I don't think I'm going to make this compatible with the current stable (2.5.3). If you really want me to, please let me know. Will also work on docs soon - though my intro post covers a lot. Nice to have docs, however.
    3 points
  6. I see. Yes that's somewhat different to what WireArray does, but you're way is fine then. You can add your own method to PageArray using hook then instead of a new class. wire()->addHook("WireArray::addUnique", null, function($event){ $item = $event->arguments(0); if($item instanceof WireArray){ foreach($item as $p){ if(!$event->object->has($p)) $event->object->add($p); } } else { if(!$event->object->has($item)) $event->object->add($p); } }); $pa = new PageArray(); $pa->add($pages->find("template=basic-page")); $pa->addUnique($pages->get("/about/")->children); $content .= $pa;
    3 points
  7. @ESRCH That login code will throw error if you login 3 times with wrong credentials... I already tried to put a note in those various (dozens already and lost track of) threads that use this "exact" frontend login code, which works but has one flaw. Problem is that once the login throttle kicks in you're left with a exception error. It's not obvious and I think posting that code in the forum over and over just creates problems in the long run for everyone copy paste such code. Funny thing is that the code originally is from Ryan himself. Either Ryan should change the behaviour of the throttle code or you need to use this code instead with a try catch to catch the login throttle error: if ($user->isLoggedin()) { $session->redirect($pages->get('/')->url); } if ($input->post->user && $input->post->pass) { $username = $sanitizer->username($input->post->user); $password = $input->post->pass; try{ $u = $session->login($username, $password); if ($u) { if ($redirectUrl = $session->get('redirect')){ $session->remove('redirect'); $session->redirect($redirectUrl); } else { $session->redirect($pages->get('/')->url); } } else { $error = "Wrong username or password. Login failed."; } } catch(Exception $e){ $error = $e->getMessage(); } }
    3 points
  8. One last attempt to suggest using the api, then I'm gone Instead of changing your source data, you can let the API create the pages for you when needed. So for a (simplified) table like this: Bibliography Type Document Title ----------------- ---------------------- Book Interesting Book 1 Book Interesting Book 2 Magazine Fascinating Magazine 1 .... you could use the following code, which automatically creates the pages for you function getBibliographyType($name) { $template = 'bibliography-type'; $parent = $pages->get('/bibliography-types/'); static $bibliographyTypes = array(); if (isset($bibliographyTypes[$name])) { return $bibliographyTypes[$name]; } else { // Create the bibliography-type page $p = new Page(); $p->template = $template; $p->parent = $parent; $p->name = wire('sanitizer')->pageName($name); $p->title = wire('sanitizer')->text($name); $p->save(); // Save bibliography type id for future calls, avoiding calls to the database $bibliographyTypes[$name] = $p; return $p; } } $f = $page->import_file->filename; $csvDelimiter = ','; $csvEnclosure = '"'; $templateName = 'Document'; $parent = $pages->get('/documents/'); while (($data = fgetcsv($f, 0, $csvDelimiter, $csvEnclosure)) !== false) { $bibliographyType = getBibliographyType($data[0]); $title = $data[1]; $p = new Page(); $p->template = $templateName; $p->parent = $parent; $p->name = $sanitizer->pageName($title); $p->title = $sanitizer->text($title); $p->bibliography_type = $bibliographyType; $p->save(); }
    3 points
  9. Your method seems secure enough. You are after all not sending a 404, so your user already knows that the url that they originally requested exists. Another method is to use the session to store the redirect url. So in the restricted page you would do: if (!$user->isLoggedin()) { // Store requested url in the session, then redirect $session->set('redirect', $page->url); $session->redirect($pages->get('template=login')->url); } and on the login page you could have // Edit: This code is not correct as-is, please note Soma's post below including the try-catch block around the login code! <?php if ($user->isLoggedin()) { $session->redirect($pages->get('/')->url); } if ($input->post->user && $input->post->pass) { $username = $sanitizer->username($input->post->user); $password = $input->post->pass; if ($session->login($username, $password)) { if ($redirectUrl = $session->get('redirect')){ $session->remove('redirect'); $session->redirect($redirectUrl); } else { $session->redirect($pages->get('/')->url); } } else { $error = "Wrong username or password. Login failed."; } }
    3 points
  10. Check your image's fields Input Tab and tick checkbox at 'Overwrite existing files?' Since version 2.5.1
    2 points
  11. Peter, I've added a lot of custom fields to my blog-post template, so my template file for the blog post itself is going to have a lot of calls to the fields listed for the template so that I can't rely on the module to output everything I want in the way that I want. It should be totally possible, and the module has a lot of other features that make it worth my while (multiple authors, the dashboard, etc). Unless you're stripping even more off the blog than just the template output for the individual posts, I think I'd stick with using it. My 2¢!
    2 points
  12. @Peter Knight I can confirm that Kongondo's example gist works no problem. Can easily add mark up to the necessary parts of the function. In my case I've added divs to suit bootstrap. No problem. And if you wanted to create separate markup for a single post you could either do it with a separate function or with a conditional statement within the renderPosts() function.
    2 points
  13. I find it easier to manage these things in a module like this. Also you need to use a before hook, as saving the page with the new title after saving would trigger an infinite loop. See next posts <?php /** * ProcessWire 'Hello world' demonstration module * * ProcessWire 2.x * Copyright (C) 2014 by Ryan Cramer * Licensed under GNU/GPL v2, see LICENSE.TXT * * http://processwire.com * */ class PutYourNameHere extends WireData implements Module { /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * * @return array * */ public static function getModuleInfo() { return array( 'title' => '', 'version' => 1, 'summary' => '', 'singular' => true, 'autoload' => true, ); } public function init() { $this->addHookAfter('Pages::saveReady', $this, 'doStuffOnPage'); } public function doStuffOnPage($event) { $page = $event->arguments[0]; if($page->template->name === "blog_page" && $page->blog_categories == "Swatch"){ // Do your thing } } }
    2 points
  14. There's a really great and simple example given by ryan here that can help you understand. In your case, you should be able to do the following (not tested): $pages->addHook('saveReady', function($event) { $sanitizer = wire('sanitizer'); $pages = $event->object; $page = $event->arguments(0); if($page->template == 'blog_page' && $page->blog_categories == 'Swatch') { // You can build the string as you wish, here is an example $concatenatedName = $page->blog_date; $concatenatedName .= '-' . $page->createdUser; $concatenatedName .= '-' . $page->blog_brand; $concatenatedName .= '-' . $page->blog_name; $page->title = $concatenatedName; $page->name = $sanitizer->pageName($concatenatedName); } });
    2 points
  15. I’m not exactly sure if that’s what you want, but if you just want to generate a bunch of nested <ul>s, you should recursively travel around the page tree. Something like: function siteMap(Page $root) { $out = "<li>{$root->title}"; if ($root->hasChildren) { $out .= '<ul>'; foreach($root->children() as $child) { $out .= siteMap($child); } $out .= '</ul>'; } $out .= '</li>'; return $out; } Uuuuh… at least I think that should work. Untested It should give you the complete branch starting at whatever you plug into $root. edit: Actually. Something is bound to be wrong with this. And you need to supply the outer <ul> yourself. edit: Tested it. Fixed it because it was stupid.
    2 points
  16. Nice idea, but I would personally go for a dedicated table for this. Perhaps you could steal some ideas from teppo's ChangeLog module: http://modules.processwire.com/modules/process-changelog/
    2 points
  17. In the "Extra Allowed Content" section on the Input tab of your field's settings, add the following: span{!color} That will allow span tags so long as the color style attribute is set. You can get more details here: http://docs.ckeditor.com/#!/guide/dev_allowed_content_rules-section-2 If you want to allow span tags no matter what attributes they have, then use this: span[*]{*}(*)
    2 points
  18. Hello, all! Sorry if this should be in another forum, but I didn't see one for general introductions, testimonials, and the like. I actually don't need help yet (the documentation and existing forum threads have already been immensely helpful), but I am just finishing up my first project using ProcessWire and felt the need to come here and say thanks. I've been designing/developing websites for several years now, and this is by far the most intuitive CMS I've used...from both a development and end-user standpoint. I just showed my most recent client the backend a couple of days ago and he was amazed at how easy it was for him to update content. So, thank you!
    2 points
  19. Welcome chadamas, I've been using PW since late 2011, and I don't think about CMS's anymore. I suspect you will never look back.
    2 points
  20. Haha, sorry about that. I knew that title was misleading, but used it anyway! Wordpress more than anything else, but I've tried several over the years. Drupal and Joomla (of course), CMS Made Simple, Textpattern, a couple of flat-file systems...for two projects I even built a basic CMS on top of forum software (SMF and MyBB). I think my search might be over, though. Thank you all for the warm welcome!
    2 points
  21. Inputfield Page Source Display a string with the rendered output of the Page (per it's Template) in an Inputfield. The markup could be copied with a button click (flash enabled browsers) and/or copied manually from the Inputfield. The rendered output is a runtime only value which is not stored in the database. Potential Use Provide an easy way for editors to copy the sourcecode of the page for the use in newsletter services and such. Note ! This Inputfield should not be used in the page template directly. (could give some “funky” results ) Download on GitHub
    1 point
  22. this is a work in progress... needs testing. in this module the edit links are added to the green boxes using 2 methods: jquery for the page list select and page auto complete, and the native asm select feature for asmSelects (thanks to Soma). Since the PageAutoComplete and PageListSelect are using the hover and icon from asmSelect, the asmSelect assets need to be loaded now on every page edit, in order to make the links look right. if you downloaded this before, please replace with the latest version, as there have been many changes, corrections/bugfixes and improvements. Please report any issues. Updated 12/6/14 at 10PM - please delete earlier versions due to issue with links being added on template editor. Updated 5/7/15: Module removed in anticipation of new official version release: https://processwire.com/talk/topic/9857-module-page-field-edit-links/?p=94599
    1 point
  23. What I do often is taking the hooked method name and put before or after before that name. This way I don't have to think about a name (laziness) and I can see when or if the method derived from a hook. In this case I would have chosen afterSaveReady.
    1 point
  24. Installing the module seems obvious, but some CMSs automatically load modules if they are placed in a certain folder, so one never knows... Anyway, I'm glad to read that it works now
    1 point
  25. If you would like to add this to the modules directory I can add your Module Developer badge over at the dev directory.
    1 point
  26. You should maybe echo something, just to check whether the function gets called at all. Also a dumb question, but have you installed the module that you are developing?
    1 point
  27. This is fantastic Martijn, thanks so much for creating it. Just set it up for exactly the purpose you mention - creating an html email based on content coming from PW. Well done!
    1 point
  28. Damn you guys, I don't answer anything anymore.....
    1 point
  29. You need to add the hook in the init function as you can see it done in my first post here. The thing you're writing there is a class, these can only hold properties and functions and not raw code, like you did. It's only there to provide functionality, which can be called later. The init function of a module is always called on loading the module.
    1 point
  30. For my simple primary navigation, I use this: $root = $pages->get("/"); $children = $root->children(); $children->prepend($root); foreach($children as $child) { echo "<li><a href='{$child->url}'>{$child->title}</a></li>\n"; } It outputs an unordered list horizontally at the top of my page. Wonderful. Some of my pages have children: About > About Our Company About > About Me Contact > Contact Me Contact > Contact The Other Guy Contact > Contact The Girl Browse > By Price Browse > By Size Browse > By Artist I thought I should use something like the above code but change where it gets root. So, instead of get site root, make it get root of about, or root of contact, root browse. But I'm sure it can be better written. $page=$page->name; if ($page=="browse") { $root = $pages->get("/browse"); $children = $root->children(); foreach($children as $child) { echo "<li><a href='{$child->url}'>{$child->title}</a></li>\n"; } }elseif ($page=="about") { $root = $pages->get("/about"); $children = $root->children(); foreach($children as $child) { echo "<li><a href='{$child->url}'>{$child->title}</a></li>\n"; } } What if I add more root pages that have children? I shouldn't have to hard code it, but I just haven't figured that out. What if later the client wants to add a summary or change something above the UL?
    1 point
  31. Could be slow if you have a lot of pages, but for a reasonable number this might work. foreach($pageArray2 as $p){ if ($pageArray1->has($p)) continue; $pageArray1->append($p); } *untested and written in the browser.
    1 point
  32. after years working on PW it's always a bit difficult get in mind all the new stuff inside new versions, but it's a pleasure of course
    1 point
  33. $pa = new PageArray(); $pa->add($pages->find("template=basic-page")); // 1001 at the first pos $pa->append($pages->get("/about/")); // 1001 at the last position now (unique) echo $pa;
    1 point
  34. Thank you Horst! Your way of getting a page by id is much simpler than mine and adding to my code your check for the lenght of the array, made me realize the actual mistake! I was loading my page looking for the wrong page id !! Such a silly mistake. Thanks a lot!
    1 point
  35. Look at my selector, my selector is amazing ( ): $favorites = $user->favorites->find("sort=title, private=0, start=".$start.", limit=".$limit); Favorites is Page field with settings: Multiple pages (PageArray). Private is an checkbox on every page which are listed on favorites. My test user has two(2) favorite pages. One public and one private. And it works great! Thanks bye! Wait.. I had a problem with this code: $favorites->getTotal(); I'm in the belief that this should return the amount of pages based on the selector excluding limit-selector. So the result should be one(1). But I'm getting two(2). Am I missing something or is this a bug? Even this one gives me two: $favorites = $user->favorites->find("sort=title, private=0"); echo $favorites->getTotal(); # 2 What I want is the total number of favorite pages. This of course works: $user->favorites->find('sort=title, private=0')->count(); But I would like to avoid making several finds if I could use ->getTotal. And why I can't do this? Because I'm using start/limit for pagination..
    1 point
  36. Maybe it is this: http://processwire.com/api/arrays/page/
    1 point
  37. Nice! The dev branch commit that adrian linked to above will make importing Page fields easier because it will allow the title string to be used instead of the page ID, but your code for creating new select options is a real bonus. Thanks!
    1 point
  38. Might not be as comfortable as similar solutions mentioned here (the generated subdomain URLs are pretty long and clumsy to type on mobile devices), but http://localtunnel.me is another node.js thingy to forward your local dev server.
    1 point
  39. I've run into long waits for thumbnails too on a site where some frontend pages have up to a couple hundred thumbnails from rather large source files. I'm also using tiny thumbs in the backend page lists. In normal operation with template caching and routine editing it's fine but during setup it was insane. I wrote a script which uses the API to see which variations are not made yet and make them. Before turning it loose you can use assess method to just get a report. Returns a handy array to use in other processing scripts. It's alpha, not gift wrapped and polished, but I can make it available somewhere if anybody wants it. Example of usage below. This puzzles me: While my script is building images all other PW activity pretty much grinds to a halt (that's not the puzzling part) but other pages on the site using PHP/MySQL independent of PW continue to work just fine. They use a different database so maybe some db lock/transaction thing is holding things up? $fab = new imagePrefab(); $fab->background = 1; //don't make browser wait $fab->verbose = 1; //Yes we want some feedback... $fab->setLog(); //...in a log file $ok = $fab->setBuilderCallback('buildImageMyWay'); //optional callback function if(!$ok)die(" Callback function not found at ".__LINE__); $data = $fab->build('my-template', 'image', array(array(48,48),array(110,110),array(800,0)));
    1 point
  40. I added two config options: Including not only visible pages: optional, include all hidden and unpublished pages and pages that user doesn't have access to view Multiple Output: optional, multiple selection (using ASMSelect) Field settings: Select Lists: (settings above -> first one)
    1 point
  41. Hi adrianmak, This seems to be a bug, I submitted a pull request to correct this. The problem is that when logging out, the user is changed to guest, and the language is set back to default. Interestingly, the $user variable still points to the logged out user (adrian in your case), while wire('user'), which is used by the __() translation function, points to guest. While waiting for the correction to the core, you can solve this issue by adding the following line after $session->logout(): wire('user')->language = $user->language; This will set the language back to what it was before logging out, and the correct translation will be shown.
    1 point
  42. You could use the wonderful Page Select Field Creator. In that module there is a textarea that takes CSV text.
    1 point
  43. Thanks for the replies. Issue 1 is now solved - I tried playing around with some of the options for the field I'm using as my select and setting "Deference in API as" to "Single page (Page) or empty page (NullPage) when none selected" allowed me to use $page->bibliography_type->title This setting isn't mentioned in the Wiki article (whoops, it is ), and I think it would be useful to have some documentation for the Page fieldtype in the API seeing as the ProcessWire method for creating common controls like select and select multiple is a bit unorthodox (although powerful). Any advice for issue 2? I'm going to need to import a large number of pages from CSV (using the ImportPagesCSV module I expect) and if that's going to be problematic to do in conjuction with using the Page fieldtype I had better rethink how I set up the fields.
    1 point
  44. Hi Cerulean, echo "<p>{$page->bibliography_type->title}</p>"; Should do the trick. The number you were getting it the page ID of the selected item. This should give you the title. Can you attach more of your code so we can have a closer look? Maybe there's a typo somewhere?
    1 point
  45. Hi @Cerulean, and welcome! I had the same trouble recently. The number string is good, it means you're nearly successful! I don't know very much (especially compared to others on this forum) but I will answer you best i know how... Start here on another thread to follow how I converted the number string to the correct display. The solution that worked for me was to call the pages before trying to output them. Here is some untested code for you to try: $bib = $pages->find("parent=/enter/path/to/your/bibliography/type/pages/here"); // calling the bibliography type pages // the path will be short, something like /tools/bibliography_type <- find it in your page tree echo "<p>{$bib->title}</p>"; More experienced users, please correct my suggestion if it is bad!
    1 point
  46. Had to do this yesterday. But this works only on the newest dev version of processwire, because Ryan just implemented the removeTab() method. Older versions will still show the tab, but no actual form to delete something. <?php /** * ProcessWire 'Hello world' demonstration module * * ProcessWire 2.x * Copyright (C) 2014 by Ryan Cramer * Licensed under GNU/GPL v2, see LICENSE.TXT * * http://processwire.com * */ class RemoveDeleteTab extends WireData implements Module { /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * * @return array * */ public static function getModuleInfo() { return array( 'title' => 'RemoveDeleteTab', 'version' => 1, 'summary' => '…', 'singular' => true, 'autoload' => true, ); } public function init() { // Remove Settings Tab in Global settings for non superadmins $this->addHookAfter('ProcessPageEdit::buildForm', $this, "removeDeleteTab"); } public function removeDeleteTab(HookEvent $event){ // check what role the user has, if superuser do nothing if($this->user->isSuperuser()) return; $page = $event->object->getPage(); if($page->template->name === "settings"){ $form = $event->return; $fieldset = $form->find("id=ProcessPageEditDelete")->first(); $form->remove($fieldset); $event->object->removeTab("ProcessPageEditDelete"); $event->return = $form; } } }
    1 point
  47. I've seen usefinch.com before. However, they limit you to only 2 hours of usage per month. Ngrok is free unlimited (pay what you want) and also has subdomain, password protection, etc. ability. Another tunneling service I was quite found of is https://forwardhq.com/. Their minimum pay plan is only $5 a month and what sets them apart is the ability to have a custom page your clients see when the tunnel is offline. Wow. That's some terrible speed However, I wouldn't think it would affect you since the only time it sends data is when being accessed. You could have it tunnel all day long without any data being sent. It only sends when the client accesses.
    1 point
  48. Here's how it worked for me in CKEditor (in case you persist on this route - but I would go for Hanna Code as Adrian suggested. As usual, the "culprit" is our friend HTML Purifier (read from here up to and including Ryan's comment here about its pros and cons before deciding whether to implement #5 below!) For iframes, the Extra allowed content seems to have no effect - btw, the correct syntax here is for example, div(*) not div[*] Add 'Iframe' (note the spelling) to your CKEditor Toolbar Leave ACF on No need to switch the field's "Content Type" from "Markup/HTML" to "Unknown" Turn HTML Purifier off (gasp! ) Enjoy your embedded video
    1 point
  49. Kyle, If an AD can only belong to one City and one Category, then I would probably do it like below (almost similar to what you have...). Cities would be parents of ADs. Categories would be children of Category... City 1 AD 1 - C1 AD 2 - C1 City 2 AD 1 - C2 AD 2 - C2 AD 3 - C2 AD 4 - C2 City 3 AD 1 - C3 AD 2 - C3 Category Electronics Furniture Books This will keep my setup DRY. I do not have to repeat categories like you have in your example. ADs will have Single Page Reference Fields. I would restrict selection in this field to just children of Category (electronics, etc.). Cities will have a "cities" template with minimal fields. ADs an "ads" template with all the necessary AD fields + a Single Page Reference Field to select one category. Categories would have "categories" template probably with just a title. Searching: Written quickly, there could be errors, etc //find all ads of a city. 1007 is the ID of the city; you can use path or name of the city as well $ads = $pages->get(1007)->children("sort=title, limit=50"); //find all ads of a city that belong to electronics category. "category" is the name of the single page reference field. "electronics" is the name (title works as well I think?) of the category page $elecronicAds = $pages->get(1007)->children("sort=title, limit=50, category=electronics"); //find all ads belonging to electronics irrespective of city $elecronicAds = $pages->find("category=electronics, limit=50"); //find all ads and sort them by city, then category $allAds = $pages->find("template=ads, sort=parent, sort=category, limit=50"); There's probably better ways of doing this + you have other selectors at your disposal, but this should give you an idea
    1 point
×
×
  • Create New...