Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by ErikMH

  1. Well, I’ve revisited all the modules and made sure that even the core modules’ settings are all identical. And I’ve made the config.php file essentially the same. But I cannot reproduce the problem in the purpose-built “Nori” test environment. So to reiterate briefly in one place: on my development server, in page-class files in /classes/ in 3.0.191, $this->parent() properly points to $this’s parent page, and the parent property of $this also properly points to its parent page; upgrading to 3.0.192 causes no problems, except that in page-class files in /classes/, $this->parent() is a NullPage, and the parent property of $this is empty. I have found an inefficient but effective workaround, however — and given that no one else is seeing this problem and that I’ve easily spent 40 hours trying fruitlessly to track it down, I think I’ll just need to say “good enough” and move on: Awkward work-around Rather than refer to $this->parent(), I’ll instead use $this->wire('pages')->findOne("child=$this"). This works just fine, and @ryan’s code is so efficient that I see no appreciable difference in speed. Sometimes you just have to move on....
  2. Thanks for your interest, @kongondo! In fact, I was able right from the get-go to pin it down to the difference between 3.0.191 and 3.0.192; I mentioned 3.0.184 recently, though, because that’s the last master release before things break for me. Here are the 3.0.192 commits on GitHub, which I linked to above. @bernhard, I decided to go all in on your suggestion of a new project: I created a new server (“Ori”) running 3.0.191. There, I created two templates (“Parent” and “Child”), and set them up in their family tabs so that only “Child” could be the child of “Parent” and only “Parent” could be the parent of “Child.” I turned on page classes, and created ParentPage.php and ChildPage.php files in the site/classes/ directory, setting each up as a subclass of Page. I created a public function in each (identify()) which returns a small definition list that includes the template and the ID of $this. I then created a page of template type Parent, and gave it a child of template type Child; in each case, the template calls the page’s identify() function and echoes it into the HTML, and it checks whether its parent record has an identify() function and echoes its results out, too. As expected, when I load the parent page on the front-end, I see that its template is Parent and its ID is 43 — and no information is provided about its parent (which would be the home page, which doesn’t have an identify() function). Also as expected, when I load the child page on the front-end, I see that its template is Child and its ID is 44, and that its parent template is Parent with an ID of 43. So much for the “control” — it worked as expected. So then I cloned that entire “Ori” set-up as “Nori,” which I then upgraded (3.0.191 → 3.0.192), and loaded the same two pages. I had expected to see the same result for the Parent page, but only the Child information for the Child. Unfortunately for me (but probably fortunately for @ryan!), nothing broke in 3.0.192 on Nori: the Child page also (properly!) showed its parent’s information. So then I began installing each of the modules that I’m using one by one on Nori, and testing the results (still in 3.0.192). I have more modules than I thought! But none of them caused my 3.0.192 test to break the way it does to my system IRL. I guess my next step at this point would be to gradually change the config.php file to match my system, with tests after each change. And then, gosh, I guess gradually re-create the whole system until something breaks. I think I‘ll take this evening off before embarking on that tomorrow. I have no idea how I could create a gist to show this, but I‘d be very happy to give any of you access to a copy of my development system where everything works perfectly in 3.0.191 but not in 3.0.192. Please PM me if you‘d be willing; I‘ll treat you to a couple of beers if you can help me make headway on this!
  3. Thank you for replying, @bernhard! I do always run Tracy Debugger [on my development server], though tbh I really haven’t figured out how to use it other than to be aware of the helpful execution time figure which helps me keep my code comparatively lean. This is not called from a hook; rather, it’s a function in a class definition in the /classes/ directory. $this itself as a variable is working fine — referring to the instance of the subclass, which is of course a page. I added the bd commands you listed into one of the class functions attempting to find $parent, and discovered the little orange shopping-cart icon. (This is how Tracy denotes dumps? Interesting.) When loading my site’s home page in 3.0.184 I see 16 dumps, which makes perfect sense: I had added those bd commands to the “Post” page class, and currently eight posts are among the items listed on the home page. So each post dump is followed immediately by a dump of its parent. Though I’ve never seen this layout or used this portion of the tool, it all makes perfect sense and is exactly what I’d expect to see. Now, if I upgrade to 3.0.196 and reload the same page, I again see 16 dumps. Eight of these are the same eight posts — and they look exactly the same. Their parents, however, all look like this: ProcessWire\NullPage #??? id: 0 name: '' parent: '' template: '' where ??? is different in all eight parent records. This number is not the record’s ID — I really don’t know what it represents. It is not the same number that Tracy Debugger reports along with the good-looking parent data in 3.0.184. If I click on the disclosure triangle, there is lots more data — but almost everything is blank or 0 or null. I’m thrilled that I now know a little more about running Tracy Debugger — thank you for that! But I don’t think it’s telling me anything new: $this->parent() is null (or empty or something) instead of $this’s parent. Is there more sleuthing I can do?
  4. I’ve adjusted my code, hoping to find that $person = $this->wire('page')->parent(); would work better than $person = $this->parent(); — but the result is (unsurprisingly) identical: both of these work perfectly in all cases in 3.0.191, but consistently return an empty page whose id = 0 in 3.0.192 and later, no matter what $this’s page class is and no matter what $this->parent()’s page class is.
  5. OK, I’ve returned from business trips and have finally had some time to pursue this further. I made a slight error in my last post here. As of 3.0.192 (and all subsequent versions through 3.0.196, at least), $this->parent() (in the context of page-class PHP files in the “Classes” directory) isn’t actually null; rather, it’s always empty, with an ID of 0. It doesn’t matter what the class of $this is, and it doesn’t matter what class its parent really is within the system. $this->parent() always gives me an empty page with no template and an ID of zero. Somehow, getting $this->parent() was broken with 3.0.192. I can build lots of checks into my code so that I can render a page without errors (and I am, in fact, doing that) — but I still need the original functionality restored. Is there some alternative way I should be referring to the instance’s parent? Or is there some way we can restore the functionality that we had up through 3.0.191? I’d be very happy to help, but I’m utterly unable to pursue this any further alone.
  6. Well, I have some answers, @ryan, though I do not understand them. home.php In my home.php file, I create a selector that looks for the most recent pages of any of a half-dozen different templates. It sorts first by date, and then by template. I then, of course, cycle through the resulting pages and create HTML for each. I have now added checks for null (via the ID shortcut — thank you!) for each of the returned pages: no errors were reported. In each case, I refer to the item’s parent. I have now also added checks for null for each of these parents: no errors were reported. IssuePage.php custom class It happens that the first item’s template is “issue,” so I began with IssuePage.php. I added a check to make sure that $this itself was not null, just to be thorough: no errors were reported. Again, one of the first things I do then is find the page’s parent and set it to $parent. I’d already changed this logic a couple of days ago to do it properly as a method call: $parent = $this->parent(); I then added a check to $parent to make sure it’s not null. First, I loaded the home page in 3.0.184. $parent was not null, and the relevant information from the parent record was generated and displayed properly in the HTML. Then, I loaded the home page in 3.0.192. $parent was null. $parent should definitely not be null. Here is an image from the back side, showing the “February, 2022” issue whose parent is Beyond Bree. And here is another image, showing the issue as one of Beyond Bree’s children from the editing panel: There is nothing unusual about these records. If I delete them, I get the same null-parent-result on a PostPage class page whose parent is a BlogPage. So, in short — there’s something about 3.0.192 that causes $this->parent() consistently to return NullPage instead of $this’s parent. Thank you so much for walking me through the proper way to debug this! Is there anything else you’d like me to do?
  7. Thank you so much, @ryan! I’ll methodically add these today and see if I can’t pin this down....
  8. Thank you for pursing this with me, @ryan! I was swept away by various events today and wasn’t able to to add more details until now. All of my custom classes are subclasses of a class I call vsPage, which itself extends Page. I make sure to add stub methods to vsPage such that, if I inadvertently call an undefined method, it’s dealt with gracefully. In the case of getTitle(), I’m actually intentionally using the method inherited from vsPage: getTitle() gets the page’s title, falls back to its name if title is empty, and adds some punctuation and a subtitle field, too, if it exists and is populated. The page’s parent uses a different template (not home!), which is also a subclass of vsPage. I’ve double-checked home.php, and getTitle() is never called on anything there. I’ve double-checked every custom class PHP file, and everything is either directly or indirectly inherited from vsPage, where getTitle() is defined. I’ve changed the line so that it calls getTitle() only on the page itself, rather than on its parent, but I still get the same error. I then reversed course and changed the line so that it calls getTitle() only on its parent, and not on the page itself, but I still get the same error. I’ve commented out the line altogether in IssuePage, but the equivalent line in PostPage (see below) causes the same problems. And once I’ve commented out all calls everywhere to getTitle(), I begin hitting the equivalent error with another method, markupALikeness().... Essentially, I seem to be unable to call custom class methods at all. getTitle() works exactly as I mean it to (through 3.0.191) for every template class that I throw at it. No errors are reported in 3.0.191, AFAICT, even with debug mode and Tracy Debugger on. You can see the live site (running 3.0.184) at https://tolkienists.org/. The title of each entry is formed via getTitle(). For the next twelve hours or so, the first three entries will be: Beyond Bree, February, 2022 — a journal issue (IssuePage extending vsJournal extending vsPage extending Page) № 196: Chad Bornholdt — a blog post (PostPage extending EntryPage extending vsPage extending Page) The Great Books № 214: The Hobbit by J.R.R. Tolkien — another blog post; this one shows the subtitle that gets added to the title via getTitle(), in fact. This same page running 3.0.191 on my test machine looks exactly the same. Since I use this method in constructing entries on basically every page on the site, I haven’t yet seen a single page generated in 3.0.192 or 3.0.193. Instead, I get this: Call Stack # Time Memory Function Location 1 0.0001 377648 {main}( ) .../index.php:0 2 0.1780 7369472 trigger_error( $message = 'Exception: Method NullPage::getTitle does not exist or is not callable in this context (in /home/716930.cloudwaysapps.com/aqewnfhddd/public_html/tolkienists-org/public/wire/core/Wire.php line 564)\n\n#0 /home/716930.cloudwaysapps.com/aqewnfhddd/public_html/tolkienists-org/public/wire/core/Page.php(1809): ProcessWire\\Wire->___callUnknown()\n#1 /home/716930.cloudwaysapps.com/aqewnfhddd/public_html/tolkienists-org/public/wire/core/Wire.php(420): ProcessWire\\Page->___callUnknown()\n#2 /home/716930.cloudwaysap', $error_level = 256 ) .../index.php:64 Well well… Error: Exception: Method NullPage::getTitle does not exist or is not callable in this context (in wire/core/Wire.php line 564) #0 wire/core/Page.php (1809): Wire->___callUnknown()#1 wire/core/Wire.php (420): Page->___callUnknown()#2 wire/core/WireHooks.php (951): Wire->_callMethod()#3 wire/core/Wire.php (485): WireHooks->runHooks()#4 wire/core/Wire.php (488): Wire->__call()#5 site/classes/IssuePage.php (43): Wire->__call()#6 site/templates/home.php (95): IssuePage->getEntry()#7 wire/core/TemplateFile.php (327): require('/home/716930.cl...')#8 wire/core/Wire.php (414): TemplateFile->___render()#9 wire/core/WireHooks.php (951): Wire->_callMethod()#10 wire/core/Wire.php (485): WireHooks->runHooks()#11 wire/modules/PageRender.module (571): Wire->__call()#12 wire/core/Wire.php (417): PageRender->___renderPage()#13 wire/core/WireHooks.php (951): Wire->_callMethod()#14 wire/core/Wire.php (485): WireHooks->runHooks()#15 wire/core/WireHooks.php (1059): Wire->__call()#16 wire/core/Wire.php (485): WireHooks->runHooks()#17 wire/modules/Process/ProcessPageView.module (183): Wire->__call()#18 wire/modules/Process/ProcessPageView.module (114): ProcessPageView->renderPage()#19 wire/core/Wire.php (417): ProcessPageView->___execute()#20 wire/core/WireHooks.php (951): Wire->_callMethod()#21 wire/core/Wire.php (485): WireHooks->runHooks()#22 index.php (55): Wire->__call()#23 {main} I do understand that we’re not paying you big bucks to troubleshoot our code — but I’m at a complete loss as to why the changes included in 3.0.192 are causing these problems for (apparently!) only my site. Of course, there probably aren’t a lot of us using custom classes, but still.... Please let me know if there’s any further information I can provide or if you have any more ideas. I’d hate to be stuck forever at 3.0.191! Many thanks!
  9. First, thank you very much, @ryan, for your code pointers. I’m not sure how I’d fallen into the habit of $me = wired($this);, but my custom-class code was riddled with it. I removed it all, and changed all references to ->parent properties to ->parent() method calls. On 3.0.184, this sped up most page loading by about 10% (hooray!), but had no other discernible effect. It’s a testament to ProcessWire’s efficiency that I haven’t ever felt the urge to go hunting for speed improvements.... Anyway, I then attempted to upgrade to 3.0.193 — and immediately was presented with NullPage errors. So I tried 3.0.189, which ran fine. So too did 3.0.191. I was becoming pretty sure the problem was going to be introduced with 3.0.193, but I tried 3.0.192 — and boom! So, this is code that I’ve been running in production without incident since last June, but 3.0.192 is causing major difficulties, which continue with 3.0.193. I don’t see anything wrong with my code (but, then again, I’m the guy who put $me = wired($this) into all his custom classes). I’ve looked at the descriptions of everything between 3.0.191 and 3.0.192 on GitHub, but nothing stands out as related. It’s late here now, so I’ll write up a summary of the logic that’s causing the problem tomorrow morning, but essentially a custom class method is called, correctly, and it’s now failing to run — giving an error that the method isn’t callable because the object is null. But it’s not null — and I get exactly the (non-null) results I expect up through 3.0.191. Here’s a link to 3.0.192 on GitHub. I’d be very grateful if anyone can give me further guidance (or figure out which bit of 3.0.192 is responsible). I’ll post more details in about 12 hours. [administrivia: Clearly, therefore, this problem doesn’t belong in this thread; I’d be happy if someone could split it out and put it somewhere appropriate.]
  10. I’ve been running 3.0.184 for a while now, so it’s possible that new errors that I’m seeing are due to an intervening change, but with 3.0.193 I’m getting lots of NullPage errors when dealing with parent pages (and, I’m guessing, other related pages) in methods defined in custom page classes. For example, this code worked perfectly in 3.0.184: public function getEntry() { $me = wire($this); $parent = $me->parent; $theHTML = "<h3>{$parent->getTitle(true)}, <span class='small'>{$me->getTitle(true, false)}</span></h3>"; ... In 3.0.193, the $parent->getTitle(true) causes Exception: Method NullPage::getTitle does not exist or is not callable in this context I cannot seem to create a parent object at all. Is this faulty coding on my part? Or an as-yet-unsupported part of 3.0.193 lazy loading? Thanks!
  11. Well, it looks like I should do something with `tabs_tab` — but I’m really not sure what. Is this something I can change in site->config.php? I don’t see how....
  12. I’ve just set up searching with SearchEngine with basically all of the default options, and I’m really impressed! I‘ve turned on group-by-template, and it’s almost exactly what I want! The template-named filtering buttons are terrific and intuitive.... I find that I’d like to render them as *plurals*, though, where the template names are *singular*. For example, I have a template *Person* that I would like to see as *People*, and another template *Journal* that I’d like to see as *Journals*. Is there a built-in way to do this? If not, does anyone have any suggestions as to how I might go about implementing this.... Just guidance as to where I might put a switch/case statement would be acceptable, though I wouldn’t be surprised if there was a more elegant solution. Thanks!
  13. Wow — not what I see at all. Thanks for testing, @Robin S! I’ll look further into this and report back. I’m using PHP 7.4, btw.
  14. This textformatter seems to work for really simple Markdown things like emphasis and headers. But I get Trying to access array offset on value of type null errors if I do any of the following: create an unordered list by beginning successive lines with `- ` feed it text that contains a bracket character (`[`) that’s not being used as part of a link put a short string of `-` characters on a line of its own to generate a horizontal rule Interestingly, if I try to create an unordered list by beginning successive lines with `• ` instead of `- ` (both are acceptable Markdown syntaxes), the attempt is just ignored: no formatting is done and no error occurs. Also interestingly, ordered lists work as expected! Are others encountering these problems? I really want to be able to parse Markdown. I’d love for extended things like footnotes and tables to be supported, but I’d settle for Gruber’s original bare-bone syntax.
  15. Quick report: wire works splendidly: <?php function myFunction() { $session = wire('session'); echo $session->future; }; ?> Thanks again, @kongondo, for the pointer!
  16. Thanks for your response, @kongondo! To answer your second point, I had indeed thought that ProcessWire variables were global — but since neither the $config nor the $session variable actually were accessible in my function (see the errors), I researched and found that: — https://www.w3schools.com/PHP/php_variables_scope.asp That source then went on to explain that that’s what the “global” statement is for. And in fact, adding “global $config” to the function solved the problem for $config. But when “global $session” did not solve the problem for $session, I posted here looking for guidance. Thank you for the pointer to wire, which I’ve never heard of and which didn’t come up in the entire day that I spent searching the PW docs, blogs, tutorials, and forum. I’ll experiment with wire('session') and see whether that solves my problem. I’m loving ProcessWire itself, but the layers upon layers of documentation and forum posts and blog articles that you have to wade through in hopes that someone has been kind enough to provide a link to the information that you really need is very frustrating.
  17. So, if I do this right at the top of a template PHP file: <?php namespace ProcessWire; function myFunction() { global $config; echo $config->dateFormat; }; ?> I, predictably, get this in my front end (once I figured out about the necessary global $config; line): Y-m-d H:i:s Happy camper. But if I try to access $session variables in the same way: <?php namespace ProcessWire; function myFunction() { global $session; echo $session->future; }; ?> I’m told there is no $session object; it responds exactly as if I hadn’t included the global $session statement: PHP Notice: Trying to get property 'future' of non-object in .../public/site/templates/home.php:5 I thought the problem might conceivably have to do with my private variables, so I tried the provided hasCookie() method: <?php namespace ProcessWire; function myFunction() { global $session; print_r($session->hasCookie()); }; ?> With essentially the same result: Error Call to a member function hasCookie() on null $session variables and methods are fully accessible and work exactly as expected if placed immediately outside of myFunction(). I am rapidly running out of hair. Is this intentional? Or a bug? Can anyone confirm that they see this behavior? Can anyone think of a workaround? Thanks! ProcessWire: 3.0.179 PHP: 7.4.19
  18. @elabx and @netcarver, thank you both so much for your detailed and well-reasoned responses. These were just what I was hoping for! As I said at the outset, I do appreciate PW’s flexibility — but it does mean there’s a lot to process mentally before really getting going on one’s first project. Of the four strategies you mentioned (a repeater, a table, child pages, and a repeater matrix), I think I’d have to agree with Netcarver that a table or a repeater matrix sound like the best match for my needs. Child pages (though a fascinating approach that I hadn’t thought of) won’t work because I do have another need for the page hierarchy. And repeaters just don’t “feel” right somehow. So while I mull that over, does anyone have much experience with ProFields TextAreas? I stumbled across these yesterday, and have experimentally set one up to hold a batch of “note”-type TextArea fields — very similar to Ryan’s example — and it’s working really well with my half-dozen test pages. Again, it “feels” like this might also be an excellent match for my needs with Text fields, but I’m curious as to why you didn’t suggest it. (Simply not having thought of it is a perfectly acceptable answer, of course: So.Many.Options!) Thanks!
  19. ProcessWire is unopinionated. I get that. It’s a good thing. And yet, this lack of proscription can be bewildering to newbies like me who struggle to figure out how best to accomplish something — even a simple something. Case in point: I’ve created an “organizations” template, and have added a couple of obvious fields to it (sortTitle (fieldText), address (fieldStreetAddress), etc.). Now I realize that I have a bunch of similar-but-distinct bits of information that I’d like to store for each organization — basically, various competing “unique identifiers” such as PURLs, DOIs, ORCids, that kind of thing. Each organization will have 0–n of these, and I’m sure that over the years, more such IDs will crop up, and I’ll want to easily add new ones. So, I could define lots of different FieldTexts (one for each type: ORCid, DOI, etc.), most of which would be empty for most organizations. And then I could continue adding new ones over the years. This seems less than graceful. Or I could (I think) define a repeating field — though I’m pretty sure that would allow me to collect values of such IDs, without saying what kind of ID each was (am I right?), so that wouldn’t be a good plan. Or I could define a FieldSet, which might be more efficient (since it’s just one field), but would have the same long-term drawbacks that using lots of FieldTexts would have. Or I could use a ProField Table … I think. (I’ve purchased ProFields for other reasons, so I’ve no reluctance to go this route if it makes sense.) Or I could create a “Unique Identifier Code (UIC)” template with N FieldTexts defined on it, and could create a new UIC page for each organization that had any kind of UIC. I’m sure there are more options, too — possibly including the best choice. I’ve read (and done!) many of the tutorials, dozens of full forum threads, all of the relevent official documentation, and many module descriptions … and I feel like I know less than I did when I started. So my questions are two: What would you do — and why? Is there somewhere where the community has assembled a list of broadly-agreed-upon best practices for ProcessWire development? Something along the lines of Ryan’s PHP Coding Style Guide? Thanks in advance for all constructive suggestions. I’ve now read a lot of threads in this forum, and I have to say that I’m very impressed with the friendliness of the community, and with the exceptionally high signal-to-noise ratio here. I’ll try not to add too much noise!
  20. Thank you so much for your quick response, @Mike Rockett! Long-time developer here, but very very new to ProcessWire. I’d suspected I was calling the module in the wrong way — and clearly I was right! So, thank you for adding the new method, but in fact I’ll look into configuring the field to use it as a formatter; I’ll bet that’ll be more efficient in terms of caching (and using a reference!) than what I was trying to do! I’m loving ProcessWire, but there’s a lot to learn....
  21. @Mike Rockett (& others), I think I must be missing something obvious here. Using the standard modules installer, I’ve installed Typographer 1.0.0 into my PW 3.0.179 installation (PHP 7.4.19), and configured many of its options. Two examples: smart quotes and smart ordinals. Following the example of TextformatterMarkdownExtra (which I have working), I “get” the module: $typ = $modules->get('TextformatterTypographer'); I then want Typographer to process the contents of a field “vsDetails” (in $item): $details = $item->vsDetails; $typ->format($details); echo "<p class='news'>$details</p>"; All this seems to work without error, but $details is echoed unmodified: foot symbols used as apostrophes remain “'” and “2nd” remains unchanged (the “nd” is not superscripted). The whole site is in debug mode; Tracy is installed (but I don’t really know how to use it yet). If I make other changes to the page, they’re immediately apparent, so I’m pretty sure caching isn’t an issue. (And just to be sure, I deleted the contents of /site/assets/cache/ ) I see that it’s possible to turn Typographer off for certain elements and classes; the text I’m feeding it is not from any of those, but I’m really not sure how it would know one way or the other. I’m taking this as another sign that I’m missing an important concept. FWIW, I can run the TextformatterMarkdownExtra module on the same text in the same way, and it works perfectly. Thanks for any help or pointers you can give!
  22. As things stand, is it possible to get the same sort of functionality for auto-compiling .less files for front-end CSS — like, put the .less files into the right place and add a line to config.php? If not, I see hints of how I might begin to script that sort of thing in @ryan’s post, but I’m sure I wouldn’t be able to figure out the fancy timestamp checking, &c. (Old-school applications programmer/systems analyst here, but still pretty new at PHP, Unix, &c.) I’m game to experiment, if someone could point me in the right direction. Thanks!
  23. I’m a nearly brand-new ProcessWire user, and I’ve got to say I’m really impressed — not just with this functionality, but with how easy @ryan and @bernhard have made everything. I installed the new version of PW on my cloud server, installed the Less module, updated config.php and put a few Less statements into admin.less — and had it all working perfectly within about 15 minutes. Nicely done!
  24. Ooh, thank you for this pointer, @wbmnfktr. I’ve done just what you suggested!
  25. Excellent, @elabx — thank you again. It turns out it was the fingerprinting (not the sessionChallenge) — and I’m guessing it’s because I’m using Cloudflare’s WARP for my local connection. I’ve removed the sessionChallenge override, and moved the sessionFingerprint line down in site/config.php to the spot that would correspond to where it is in wire/config.php. Everything’s still working, so I’m happy and I’ve learned something. Thanks! Onwards, through the fog!
  • Create New...