-
Posts
6,268 -
Joined
-
Last visited
-
Days Won
314
Everything posted by bernhard
-
I guess nobody wants to hear that, because it seems to be too nerdy to create fields via code, but this is just another example why I love my setup so much. Thank's for reminding me of those days where I was struggling myself with those topics ? For those interested in an advanced approach of organising PW projects and keeping your setup clean I'll try to explain what I do for all my projects now. And that's another benefit: I always do the same. On every project. For every field. So every project works the same and I instantly know what's going on even if I haven't worked on the project for a longer time. For me these two things were crucial: Custom Page Classes (optional) RockMigrations (optional) RockMatrix or RepeaterMatrix If you haven't used custom page classes be sure to check them out: https://processwire.com/blog/posts/pw-3.0.152/#new-ability-to-specify-custom-page-classes That would actually take too long to explain... But I've shown some of the above mentioned techniques that might also be of interest for readers of this topic in the linked issue (https://github.com/processwire/processwire-requests/issues/154) The sort version which might be an idea for you guys having troubles with field names: You could create a custom class that is loaded in _init.php where you define your fieldnames as class constants: <?php // site/_init.php class MyProject { const field_body = 'body'; const field_teaser = 'body1'; const field_summary = 'body1'; const field_cover = 'blog_cover_image'; } Now you can access your fields in your templates like this: <?php // template newsitem echo "<h1>{$page->title}</h1>"; echo "<div>".$page->get(MyProject::field_teaser)."</div>"; <?php // template basic-page echo "<h1>{$page->title}</h1>"; echo "<div>".$page->get(MyProject::field_summary)."</div>"; Note that we are reusing the field "body1" and referring to it as "field_teaser" in newsitem and as "field_summary" in basic-page. Personally I don't do any reusing of fields any more but that's a different topic and relates to RockMatrix + RockMigrations. Hope the ideas where useful for someone nonetheless.
-
How do I make ProcessWire display the 404 "page not found" page?
bernhard replied to ryan's topic in API & Templates
Thanks for making me aware of something that I've done wrong for about 20 years ? -
Ok now we are talking about a totally different topic... But first things first. This is exactly what I'm using SSE for. The user clicks a button, ProcessWire starts doing a long running task (for example trashing lots of pages) and while it does so, the progress is sent to the client so that the client knows what's going on. I'd call that real world ? The reason why I chose SSE over sockets and over not implementing any client feedback is obvious: Having a long running task without a progress bar is just not an option. What if the user trashed several hundreds of pages and didn't know if that takes 5, 10 maybe 120 seconds? Other techniques are much more complicated to setup (for example web sockets). SSE is built in and does just what I needed: Inform the user of the progress of the task without polling. Of course while this task is running the system is blocked for all other requests. As far as I understand that's the nature of how PHP works. We have the same limitation everywhere in PW and everything in PHP... For example if you empty the trash with lots of pages and you try to visit the PW backend in another browser tab you'll also be blocked until the first tab has finished it's job - or am I wrong here? PHP is single threaded so if you wanted to come around this you'd have to do additional things. I've no experience in this territory, but this seems to look like it could be worth a try: https://stackoverflow.com/a/4350418 There's also https://www.php.net/Thread but that is based on a PECL. And so is https://openswoole.com/ which looks like it comes closer to what you are trying to achieve than what is possible with SSE as far as I understand. 1. Of course we are! Why shouldn't we?? The module is just here to have a common foundation to test things out and eliminate confusion about who copied which code snippet to whatever place etc.; You could now test the linked popen() technique and just add that to the module as a PR and everybody could understand and learn. 2+3. We'd need to have a real non-blocking background process for that. But as I said that not a matter of SSE that's a matter of multi threading in PHP. https://www.youtube.com/watch?v=spDpR2qr-Fs&ab_channel=Dr.RobertDimpsey So for my use case SSE seem to be a good option. For updating a website's content based on "real time data" polling might still be the better option as it will not block the user.
-
Well please try the module and see if that works first. Then try a custom approach and see if it breaks. The reason why I created the modules is exactly to avoid hickups when copy/pasting things from this thread or placing things in the wrong spot... So that everybody has a quick test of SSE with a single click (install module) and can proceed from there.
-
Have you tested my module?
-
RockMigrations1 - Easy migrations from dev/staging to live server
bernhard replied to bernhard's topic in Modules/Plugins
The main difference is how migrations are triggered. On the old module I've used the "fireOnRefresh" approach which fired migrations on every modules refresh. On the new version you can add files to a watchlist and migrations will automatically fire if a file changed. That makes a huge difference when working with the module as you'll only need a page reload and the new data will be there ? Also I've improved logging so that it's easier to see what happens and the module handles same cases in the same way (the old one sometimes threw exceptions, sometimes did early exists). Other than that it's quite the same as the old one as I'm really happy with how everything worked there. I've refactored all methods while transferring them from the old version to the new one. -
So what about the error you previously posted?
-
Nice writeup, congratulations ?
-
Anybody?
-
Thx Ryan for pulling my changes and improving them ? I wonder if you have any numbers of how much more efficient it is to use a non-hookable method compared to using a hookable method? I'm usually not thinking too much about this as everything seems to be fast anyhow. But as you have refactored that approach it might be a noticable difference? I'd be very happy about some insights ?
-
https://github.com/baumrock/RockSSE-demo Would be great if many of you could test this on your setups and let me know if it works as expected! In production I have a long running task like trashing lots of pages. The script will finish when all pages have been trashed.
-
It's an URL hook with the code I already posted above: Ok I'm missing an $i++ in the example! So it will run forever... Simply add an $i++ in the loop or do while(++$i) ...
-
You might have a process running then in the background... this is why I added the manual break ($i>30) in my example... This is how a correct SSE implementation looks like: one single request stream of +4s message appear in "EventStream" tab console shows logs (because I'm doing console.log in JS)
-
No, the issue is not the JS, the issue is that the data received is not properly formatted, so the client thinks the request failed and it fires a new request which is the same as if it were ajax polling. If the received data is properly formatted the stream can be read and the connection keeps open. This is my JS: const evtSource = new EventSource(url, { withCredentials: true } ); evtSource.onmessage = function(event) { console.log(event); if(event.data==='DONE') { evtSource.close(); if(modal) modal.hide(); if($button.data('reload')) RockGrid2.getGrid($button).reload(); } else if($progress) { $progress.fadeIn(); $progress.html(event.data); } }
-
Yep, RockToken can help here ? https://github.com/baumrock/RockToken
-
I've had the same problem - the script seemed to work but sent several requests just like ajax polling: But I've managed to get it working correctly and the result is a nice stream of data and updating feedback for the user while bulk-editing of data in RockGrid. There's no reload, no ajax-polling: The key is to echo the correct message. I've built a method for this in my module: /** * Send SSE message to client * @return void */ public function sse($msg) { echo "data: $msg\n\n"; echo str_pad('',8186)."\n"; flush(); } If you do that, you can do something like this: <?php header("Cache-Control: no-cache"); header("Content-Type: text/event-stream"); $i = 0; while(true) { $this->sse("value of i = $i"); if($i>30) return; // manual break after 30s for testing while(ob_get_level() > 0) ob_end_flush(); if(connection_aborted()) break; sleep(1); } Not sure if the ob_get_level and ob_end_flush are necessary...
-
Yes, you can use InputfieldTextTags https://processwire.com/blog/posts/pw-3.0.177/ But it would be a lot easier to use HannaCode or a custom Textformatter module which replaces [file=foo-bar.php] with the content of the file foo-bar.php
-
$item is a Page object. The "Page" class extends the "Wire" class (which all of PW's classes do), so you can access the ProcessWire instance via $item->wire and from there you can access the "Sanitizer" class via ->sanitizer: $item->wire->sanitzer->trunc(...) <?php $list = $pages->get(1234)->children; $toJSON = $list->explode(function($item) { $summary = $item->wire->sanitizer->truncate($item->summary, [ 'type' => 'punctuation', 'maxLength' => 155, 'visible' => true, 'more' => '…', ]); return [ 'title' => $item->title, 'id' => $item->id, 'start' => $summary, ]; }); Most of the time you can even do $item->sanitizer without the ->wire but I'd consider it a best practise to use ->wire because it's slightly more efficient and less error prone.
- 1 reply
-
- 3
-
I've created a PR for this issue https://github.com/processwire/processwire/pull/219
-
Very interesting!! Thx for sharing. https://www.githubunwrapped.com/ is built with it ?
-
@kongondo I don't understand. Is added anything better than saveReady? Wouldn't you have to do a save() or setAndSave() in your example? And isn't the id=0 obsolete (or even wrong) if you are using the added hook?
-
Alternatively to hiding/renaming the publish button you can auto-publish the page when it is created: <?php $wire->addHookAfter("Pages::saveReady(template=xyz,id=0)", function($event) { $page = $event->arguments(0); $page->status = 1; // auto-publish });