Jump to content

Jan Romero

Members
  • Posts

    612
  • Joined

  • Last visited

  • Days Won

    15

Everything posted by Jan Romero

  1. You can do it from $pages as well, using the has_parent selector. It will match up the whole tree, not just the direct parent. I can't believe I actually didn't know $page->find(). Nice one!
  2. If you want to avoid converting the selector to SQL you can let ProcessWire do it for you as teppo has shown in this post: $selectors = new Selectors("template=blog-post, limit=1000000"); $pagefinder = new PageFinder(); $sql = $pagefinder->getQuery($selectors->getArray(), array())->getQuery(); Then you can modify that or wrap your own select around it: select sum(data) as sum_amount from field_amount where pages_id in ($sql)
  3. $timerkey = Debug::timer(); //do lots of things echo "Lots of things took " . Debug::timer($timerkey) . " seconds to do."; Note Ryan’s benchmarking tips here: https://processwire.com/blog/posts/processwire-3.0.6-brings-pages-upgrades-and-link-abstraction/#how-to-benchmark-pages
  4. Try clearing your browser cache or force-refresh the page using CMD+SHIFT+R (I think).
  5. You don’t actually need to load the page at /url-one/, since you already know its url, and that’s all you need for your switch logic. Also, your variable $styleSwitcher refers to a Page object, but you’re comparing it to a string (the current page’s url). I would suggest simply comparing $page->url to "/url-one/".
  6. Existing pages always take precedence over urlSegments. You have several options: Use urlSegments that don’t exist as children of /site/teachers/, for example by adding a string, or by using 2 urlSegments. E.g. /site/teachers/selection/teacher1/. Use GET parameters instead: /site/teachers/?teacher=teacher1. You could either process the parameter with PHP or catch it with JavaScript and use your existing AJAX solution. Which would probably be the simplest option. Just add one or two lines of JS. Or, if you don't want the actual page under /site/teachers/teacher1/ to be reachable at all, just display /site/teachers/ in that template. Example below: template of /site/teachers/teacher1/: $options['teacher'] = $page; //pass the teacher to the parent page using options array echo $page->parent->render($options); //render the parent page (/site/teachers/) template of /site/teachers/: if(isset($options['teacher'] && $options['teacher'] instanceof Page) { $aside_teacher = $options['teacher']; } //Now render the page as you normally would, and you can use $aside_teacher to put its contents where you need them This also has the added bonus that you can use standard page caching for the child pages.
  7. I'm confused. What @kongondo says is undoubtedly true: a page field will return a Page object, even from within a repeater. I just tested it myself. But knowing that, @joe_ma's code from the OP should have worked: echo "<div class='" . $s->color->title . "'>"; Here, $s is the repeater item, color is its page field, and title is the title property of that page field's page. Seems fine to me? Edit: Oh, I get it. The page field "color" is multi-page, so it returns a PageArray which silently fails to return a title property. @joe_ma, try changing color to a single page field, unless you need to define multiple colors per repeater item. Then your original code should work. It's a good idea to name your fields according to what they return, i.e. this one is called "color" as opposed to "colors", so when you access it, you're likely to expect a single item
  8. Great introduction to urlSegments. This is a textbook use case. However, some pointers for beginners who might want to copy and paste the code. You can probably skip the whole $allowedSegs array, imo. I would sanitize the segment like you did, then cut off the extension afterwards (not sure if anything can go wrong doing that string operation on unsanitized input, but it works the same). Then I’d just get a child page of that name. Most importantly, get the child page using $page->child('name=' . $sanitizedSegment), because with $pages->get() you might get an unexpected page of the same name from a different branch of the page tree. If it returns a NullPage, you can still 404. Also, I would refrain from overwriting $page, just to rule out any potential headaches that might cause
  9. You can set a default template by supplying the GET parameter “template_id”, or the POST parameter “template”: http://example.com/processwire/page/add/?parent_id=1024&template_id=46 I’m not sure about forcing the template. You could probably specify a default name format in order to bypass the page-add screen directly, or hook into ProcessPageAdd to manipulate the form.
  10. This line is executed regardless of whether $item has children: $out .= "<li$class><a href='{$item->url}'><i class='fa fa-file-text-o'></i> {$item->title}</a>\n"; You’re going to want to attach it to the condition if($numChildren) { below, so the link is only appended to your output if it doesn’t have children. Perhaps like so: if(!$numChildren) { //No children, so append the standard top-tier link $out .= "<li$class><a href='{$item->url}'><i class='fa fa-file-text-o'></i> {$item->title}</a>\n"; } else { //We have children here, so append the parent-style link and do the recursion //... }
  11. Next and prev return a single Page, not a PageArray, so you can’t count them. See the docs for $page->next: https://processwire.com/api/variables/page/ »This page's next sibling page, or NullPage if it is the last sibling.« This is the same for all properties and methods that return only a single Page, like $pages->get(), $page->parent, $page->rootParent, etc. If nothing is found, they will give you a NullPage, which always has the id 0. So you can test for it using one of these conditions: if ($page->next->id === 0) { /*$page is the last of its siblings*/ } or if ($page->next instanceof NullPage) { /*same here*/ } Since 0 evaluates to false you can also go if (!$page->next->id) { /*see above*/ } if you’re into the whole brevity thing. Sorry, can’t format on mobile.
  12. I actually think “page” is a stroke of genius. It keeps the learning curve low for beginners by giving them a word they can immediately understand and work with. You can either keep working under the assumption that a page represents an HTML document, or dig deeper little by little. You’ll install a module like Language Support, and notice that – what do you know – languages are pages, until you arrive at “everything is a page”.
  13. Check this out. It tells you exactly what you need to do and shows you what your page will look like on facebook.
  14. In your page field settings go to Input, expand “Custom PHP code to find selectable pages” under “Selectable Pages”. You can fill your input field according to the template of the page being edited, by checking $page->template: if ($page->template->name === 'News') { return $pages->find('parent=/categories/news/'); } else if ($page->template->name === 'Product') { return $pages->find('parent=/categories/products-type/'); } else if ($page->template->name === 'Picture') { return $pages->find('parent=/categories/pictures-type/'); } Make sure to remove all the other options from “Selectable Pages”. Sometimes they don’t get overridden properly.
  15. In the database it’s going to look the same either way: a table with two columns, user id and picture id. But since you probably want to show “this image has been favorited by 43 users”, rather than “this user has favorited 29 pictures”, I’d put it in the picture template. That way you can simply go $page->favs->count(), rather than $users->count("favs={$page->id}"). It would also be easier to select and sort pictures by number of favs. Have you considered storing the time of the favorite? Maybe this module will be of interest: http://modules.processwire.com/modules/fieldtype-page-with-date/
  16. Hi ngrmm, the value of a checkbox is 0 for unchecked and 1 for checked, so to have checked pages at the top, you have to sort in descending order. Simply prepend a - to the field: $articles = $pages->find('template=x|y, sort=-highlight, sort=creation');
  17. You can build your selector string like any normal string before you pass it to the find function. If a field has been left empty, you can simply not include it in the selector. $selector = "template=user, roles={$role}, include=all"; //fixed part of the selector that is always used if ($input->post('country')) { //sanitize etc. $selector .= ", country={$inputcountry}"; } //repeat for other inputs
  18. Might be faster to just do a simple for loop from 2010 (depending on how far back your archive goes) to 2100 (or, say, the current year) and just check the page count for each year. That way you’re not loading any pages at all, and you don’t have to do any date magic. It would also probably result in shorter code. for ($i = 2010; $i <= date('Y'); $i++) { $c = $pages->count("template=artikel, publish_from>={$i}, publish_from<" . ($i+1)); if ($c > 0) $out += "<a href='/{$i}'>{$i}</a>"; } Maybe even throw limit=1 into the selector, or display the count for free.
  19. Since you already have $references_parent in a variable, why not use $references_parent->numChildren(true)? It’ll give you the total number of children including pages that are hidden/unpublished/etc. Set to false to get only visibles. Another idea would be to use $r->sort. Even with manual sorting that should always be the highest number immediately after adding the page. Be aware that both these methods will lead to duplicate numbers if you decide to delete one of the existing pages! You should probably keep a record of the highest number assigned somewhere central, if you need these reference numbers to be unique.
  20. For anyone wanting to getUnformatted regardless, you can do this: $page->getUnformatted('dates_table.begin_date'); /* Returns: * array(8) { * [0]=> int(1430863200) * [1]=> int(1433282400) * [2]=> int(1434837600) * } */ Also: $page->getUnformatted('dates_table.first.begin_date'); // Returns int(1430863200) $page->getUnformatted('dates_table.last.begin_date'); // Returns int(1434837600) So you can have your cake and eat it too without having to parse date strings. E. g. you can directly use the inbuilt templating syntax with formatted values, but if, say, you also need a locale aware day name, you can feed the timestamp to strfrtime().
  21. The method get() returns only one page. Your code is looking for a page with the path /case-references/. If this path doesn’t exist on your site, you will get a NullPage. You can check if you got a NullPage by testing for $references_parent->id === 0 or $references_parent instanceof NullPage. Because you only get a single page from get(), your variable $num will always be 0, as page objects don’t have a count. To find multiple pages, you should use wire('pages')->find(). Unfortunately it is unclear which pages you want exactly. I’m guessing you want all the children of /case-references/. In that case, try wire('pages')->find('parent=/case-references/'). You may also want to specify the template of the pages you’re looking for. Also in your first line you are testing whether $page->id is false AND $page is unpublished. That seems like an unlikely combination, because the NullPage is usually published.
  22. While Praegnanz do use ProcessWire in some of their projects, I doubt Computerbase.de is among them. Here is a German blog post about the project, where they say they were only responsible for the frontend design: http://praegnanz.de/weblog/computerbase-workflow Gerrit van Aaken of Pragenanz is one of the best-known German web developers and he occasionally posts here in the PW forums.
  23. Of course you can totally roll your own table and SQL, but the “ProcessWire way” would be to have a Review template and a separate page for each review. There are a couple of different ways to model the relation between reviews and their pages, the simplest being just making them children. So you’d have --Listing (?? or whatever) ----Review 1 ----Review 2 If you don’t want to pollute your page tree with this, and/or have the convenience of editing reviews directly from the page edit screen, you may use a page field, a page table field, or possibly a repeater field. PageTable would probably provide the nicest UI for editors, if that’s a concern. If you’re interested in accessing the database, these threads about the $db variable may also be of interest: Functions/methods to access the DB? Reading and displaying data from a custom table
  24. Hi mattcohen, since you specifically asked about “more control over the results other than using foreach”, I’d like to add to the responses above that you can absolutely sort, modify, filter the results you get from find()! What ProcessWire’s $pages->find() gives you is a special kind of array object called PageArray. PageArrays have a number of methods detailed in the ProcessWire Cheatsheet. If you need to sort the gyms from your example by location after finding them, you can do this: $gyms->sort('location'); //Sorts ascending. For descending prepend a "-" like so: sort('-location') This may be useful if, for example, you want to output the same list of gyms twice. Once sorted by rating and once by location, perhaps. You can also use find() on an existing PageArray. Maybe you want to show all gyms, but feature the three top rated ones above. You may do something like this: //Find all gyms sorted by location $gyms = $pages->find("parent=/gyms/, sort=location"); //Copy the 3 with the highest rating into $top_three (another PageArray) //No need to go to the database again, because we have $gyms already $top_three = $gyms->find("limit=3, sort=-rating"); foreach ($top_three as $top) { echo "$top->title: $top->rating Stars"; } foreach ($gyms as $gym) { echo "$gym->title in $gym->location"; }
×
×
  • Create New...