Leaderboard
Popular Content
Showing content with the highest reputation on 07/13/2012 in all areas
-
I've been diving into the core of PW trying to understand performance problems when there are lots of pages, especially ones with repeater fields in their templates. The problem is that creating a page takes seconds (rather than milliseconds) when certain conditions are met. Setup #1 one container page, say /countries/ hundreds of subpages with children, /countries/<country>[/<state>]/<city>/<data> for example create a new page, parent being /countries/ Setup #2 a large page hierarchy with not that many pages directly under one parent, but hundreds of pages with template(s) that each have the same repeater field structure becomes flat again as repeaters use internally page hierarchy of this kind: /processwire/repeaters/for-field-123/for-page-456/1234567890-1234-1 (--> .../for-page-nnn/... are all siblings even when the actual pages are not) create a page with a repeater field used all over the site, parent is irrelevant And of course I've got both of these on one site . Now, what I don't quite understand is what the Pages class method ___save() does just before calling some hooks in the end (from: wire/core/Pages.php): if(($isNew && $page->parent->id) || ($page->parentPrevious && !$page->parent->numChildren)) { $page = $page->parent; // new page or one that's moved, lets focus on it's parent $isNew = true; // use isNew even if page was moved, because it's the first page in it's new parent } if($page->numChildren || $isNew) { // check if entries aren't already present perhaps due to outside manipulation or an older version $n = 0; if(!$isNew) { $result = $this->db->query("SELECT COUNT(*) FROM pages_parents WHERE parents_id={$page->id}"); list($n) = $result->fetch_array(); $result->free(); } // if entries aren't present, if the parent has changed, or if it's been forced in the API, proceed if($n == 0 || $page->parentPrevious || $page->forceSaveParents === true) { $this->saveParents($page->id, $page->numChildren + ($isNew ? 1 : 0)); } } So, for new (and moved) pages it always ends up calling saveParents() for the parent page of the page being saved. saveParents() then works recursively deeper into the tree calling itself for every child page with children of its own. Given the setup #1 this means going through every .../<country>/ and .../<state> and .../<city> page there is. On the other hand, with setup #2 every single repeater instance (.../<for-page-nnn>/) with data inside will be handled. It doesn't really surprise me anymore this takes a while: saveParents() is deleting rows and inserting new ones into pages_parents for thousands of pages, unnecessarily if I'm right. It does seem necessary to call saveParents() for the parent page if the page being saved is its first child (pages_parents has a row for each ancestor of the parent page, but not for the page or parent page itself), but the recursion goes all over the place. I think it should be somehow restricted to the new/moved page and its children (and so on) only. Also, the second argument to saveParents() gets a wrong value when $page refers to the parent page as numChildren has already been incremented for the parent page (though this doesn't actually break anything). As long as new pages can't have children when they're saved for the first time, saveParents() shouldn't be called at all when saving a new page. If child pages may exist, it isn't of course that straightforward but still the saveParents() recursion should be restricted as stated above. I hope my explanation makes sense to you. It's quite possible there is something laying under the hood that I just can't see now having studied this thing for a while (well, hours). But it sure seems like a bug to me .7 points
-
- Not sure where to post this- I just made a country list and i thought it might be useful to someone so i put it on github. You could use this for example with the importpagescsv module to easily create country pages for use in your site, forms etc. For now it's English only ( i could add other languages if someone needed it) README.md About This is a complete ISO 3166-1 encoding list. It is listed in alphabetical order by the English short country name used by the ISO 3166/MA. There are currently 249 ISO 3166-1 countries. England, Northern-Ireland, Scotland and Wales are added to that because they are used by FIFA. It also contains the corresponding IOC and FIFA three letter codes and the filenames of the country flag image(s). Total countries: 253 Fileformat: txt file separated bij tabs Data is taken from: http://en.wikipedia....wiki/ISO_3166-1 and http://en.wikipedia....6_country_codes Flag icons I included the flag icons from http://icondrawer.com/free.php See the link for details and terms of use. You can also get the flags in a wide range of sizes and flavors from this awesome project: https://github.com/koppi/iso-country-flags-svg-collection For the least amount of hassle: https://github.com/koppi/iso-country-flags-svg-collection#download-the-icon-sets4 points
-
Finally I managed to rework my personal portfolio page with processwire and bootstrap. Nothing special, just some references and contact info. Maybe a blog will follow some day, atm I don't have the time to write blog entries even if I like to. Fully responsive, so you can check it out on your mobile too. Any feedback appreciated www.about-orkan.de (ah it's in german only, so you probably will get a error-500-face ^^)2 points
-
https://www.mlcu.org ...conversion away from a larger CMS. Staff seem to like it so far; it's a migration from a bulkier CMS. Note that this is just the banking service portal and not the actual online banking software...2 points
-
The problem lays in the if( $newsChildPage == $newsChildrenArray->first() ) { Comparing object shoudl be done using "===" Not sure why the error, but with "===" it works. However I cleaned up a little your code, using heredoc (<<<_END) which can be handy to generate output code so the indentation stays. foreach( $newsChildrenArray as $newsChildPage ) { $newsImg = ''; //Test for an image on the current page if( count($newsChildPage->images) ) { //If this is the first article, make a larger image if( $newsChildPage === $newsChildrenArray->first() ) { $newsImg = $newsChildPage->images->first()->size(157,151); } else { $newsImg = $newsChildPage->images->first()->size(77,71); } } $class = ''; $imgstr = ''; if( $newsChildPage === $newsChildrenArray->last() ) $class = ' class="last"'; if( $newsImg ) { $imgstr = "<img src='{$newsImg->url}' alt='$newsImg->description'/>"; } $out = <<<_END <a href="{$newsChildPage->url}"> <li$class>$imgstr <p> <span class="preview-title">{$newsChildPage->title}</span> • <span class="preview-date">{$newsChildPage->date}</span><br /> {$newsChildPage->summary} <a href="{$newsChildPage->url}" class="read-more">Read More...</a> </p> </li> </a> _END; echo $out; } Also changed some things to avoid further problems. Using ->eq(0) for example to check if there's an image is wrong. It won't work if there no image. Use count(); Also the check if($newsImg) will fail if there's no image as the variable won't exists. So you need to set it before.2 points
-
Looking in to PW as an alternative to Drupal. Just wondering if there is any way to define the template file on render. I read in another post about setting a variable before render and checking for that in the template. ($useThumb, was the example to render a thumbnail) But I wanted to keep my templates clean and create, for example a teaser.php template file. Inside of that I would use something like a switch($page->template) statement on $page->template to write out the html for the corresponding type. For example, say I have a video, blog and image type. I could simply have them all use the teaser template file on the homepage. So the real question is, can I switch the page template dynamically and will I be able to access the "original" template in the new template. Here is a code sample to demonstrate: // home.php $videos = $pages->find("parent=/video, featured=1, limit=3, sort=-date"); echo "<h2>Featured Videos</h2>"; foreach($videos as $video) { //set teaser template $video->render();/* Want to render using the teaser.php template */ } // REPEAT for blog and image, all use sample template // teaser.php switch($page->template) { case "video": echo '<div class="teaser video"><div class="field-video">{$page->video}</div></div>'; case "blog": echo ' <div class="teaser-blog"> <div class="title">{$page->title}</div> <div class="date">{$page->date}</div> <div class="summary">{$page->summary}</div> </div> '; break; }1 point
-
I think it might be a little better to use a counter just because that is native PHP with no function call (i.e. always faster/more efficient). And you should be able to get that counter right out of the foreach(). foreach($newsChildrenArray as $cnt => $newsChildPage) { $newsImg = $newsChildPage->images->first(); if($cnt == 0 && $newsImg) { $newsImg = $newsImg->size(157,151); // big } else if($newsImg) { $newsImg = $newsImg->size(77,71); // small } // the rest… }1 point
-
If I understand correctly, you want to change the rendering context at runtime if certain conditions are met. You have a few options. 1. You could set your $video to have a different template file before calling $video->render(); /site/templates/home.php $video->template->filename = 'teaser.php'; echo $video->render(); 2. Or you could throw up a flag that your video.php template file knows to look for: /site/templates/home.php $input->whitelist('teaser', 1); echo $video->render(); …and in your video.php: /site/templates/video.php if($input->whitelist('teaser')) { include('teaser.php'); } else { // render full video page } The advantage here is that all your video rendering code is together in one file. 3. Or you could include your teaser.php from home.php manually: /site/templates/home.php $_page = $page; $page = $video; // substitute $page before including teaser.php include('./teaser.php'); $page = $_page; // return $page to it's original state 4. Or you could isolate the teaser rendering to a function (perhaps included from another file): /site/templates/functions.inc function renderTeaser($page) { return "<p><a href='{$page->url}'>{$page->title</a><br />{$page->summary}</p>"; } /site/templates/home.php include('./functions.inc'); echo renderTeaser($video); This last option is the one I'd be most likely to take as I think it's probably one of the lowest overhead, it's easily reusable across different templates, and requires very little consideration wherever you use it. Here's another way you can do the same thing, by actually adding a renderTeaser() function to the Page class at runtime: /site/templates/functions.inc function renderTeaser(HookEvent $event) { $page = $event->object; $event->return = "<p><a href='{$page->url}'>{$page->title</a><br />{$page->summary}</p>"; } $this->addHook('Page::renderTeaser', null, 'renderTeaser'); And now you can do this: echo $video->renderTeaser(); Btw that line that has $this->addHook(); has null as the 2nd argument because the function is outside of a class. Some people create auto-loading modules to contain rendering functions, in which case that 2nd argument is the module's object instance.1 point
-
That makes sense as to why Page::render is getting called twice, and your hook is getting called twice. It seems to all be the proper behavior. So like you found, you just need to avoid adding your script twice. I think the way you are doing it is good. Though here's another alternative that might be slightly faster: public function addScripts(HookEvent $event) { static $completed = false; if($completed) return; // ... code to add stuff to the rendered output $completed = true; }1 point
-
1 point
-
I just discovered the Template of selectable page(s) option in the Selectable Pages section, which allows me to use a different template for the categories within /work/. Brilliant!1 point
-
I'll add one more to that list, and that would be Zend Framework: http://framework.zen...rvices/overview. ZF being backed by Zend Technologies itself is one of the reasons why it's so popular. Short quote from a 2009 blog post by Jim Plush titled "Why I chose Zend Framework for Enterprise" where he explains why they decided to use ZF at Panasonic: "After a few weeks of evaluations I settled on Zend for a few reasons. #1 It has a company behind it. It means a lot to me to be able to pay out some budget money to get proper training for developers or have people on the ready for support issues." -- http://www.litfuel.n...ush/?postid=177 That's right; there being a company with paid services behind ZF was their number one reason. Just saying. Healthy community is a must for any proper open source project and community support is enough for most small to medium companies - especially if they have enough technical expertise available in-house - but when it comes to enterprise level applications you really need to know that if you're in trouble, there's someone who can help you right there and then (and even when your own CMS guru happens to be on a long vacation at Tahiti.)1 point
-
Hello Ryan, thanks for the quick reply. That's pretty much what I did (I have a module pulling JSON data of the video server). My error was, that 'video_image' was a text field and not an image field! Thanks for the great work, thomas1 point