Jump to content

millipedia

Members
  • Posts

    105
  • Joined

  • Last visited

  • Days Won

    4

Everything posted by millipedia

  1. Just in case you ever need some ammo in persuading a client that WordPress is probably not the way to go these days: https://webdesignerdepot.com/the-slow-implosion-of-wordpress-2025-and-the-cms-thats-losing-its-soul/
  2. Well it's not really a bug since your code does exactly what is intended. If you want to avoid user getting the 404 on misconfigured servers then you could try inspecting using the whole uri rather than the GET parameter. Just trying: // if (!str_ends_with((string)@$_GET['it'], 'rockdevtools-livereload')) return; if (!str_ends_with((string)@$_SERVER['REQUEST_URI'], 'rockdevtools-livereload')) return; in the couple of places you have it works fine for me even if I use the wrong rewrite rule. I think REQUEST_URI should be fine to use these days....
  3. XCloud was one of the services I tried, and it was top of our list for a while until we tried to change the default rewrite rule... Whilst xcloud lets you change quite a lot of nginx conf settings you can't change the default rewrite: // PW rewrite rule should be try_files $uri $uri/ /index.php?it=$uri&$args; // but xcloud won't let you change it from try_files $uri $uri/ /index.php?$args; PW has a fallback so that the second rule generally works, so we didn't notice for a week (and after I'd spent a lot of time in xcloud ...). It was only because we came accross an issue with Bernhards live reload that I realised something wasn't right. xcloud support were good, and honestly in most cases I don't think it will matter, but because they weren't able to change it I decided it was probably the sensible move to cross xcloud off of my list. I don't think that the rewrite to 'it=' gets used much and it might be worth asking @ryan to consider defaulting to the other rewrite url which I assume is what WordPress uses and hence the default for a lot of hosts.
  4. Slightly ninja'd there. But we haven't had any issues with using nginx so far. There is a big discussion on it in this forum already. When I was researching different hosting providers it was interesting how many did just provide nginx and not Apache ( Runcloud / Ploi / XCloud etc ). I think that PW probably needs to make sure it's compatible with other servers and not just rely on Apache (and nope, I've not tried LightSpeed yet).
  5. I've just spent the last week phaffing around with different hosting providers and we've ended up going with Ploi with servers from Hetzner (largely due to recommendations in this forum). This was partly a cost saving exercise (although it's taken a week of my time...) and because we wanted to shift some sites back into the EU. Ploi do only have nginx and not Apache. That's not been an issue for any of our PW sites so far, but if you do have something that relies on fancy rewrite rules or something Apache specific then that would be something to consider. Also - if you're only spinning up a single site then it's probably not going to be as good value as if you have lots of sites. Their Pro tier is the same price for 1-10 servers. We also use Krystal for general cPanel hosting. They've been really good, are UK based, B-Corp and green. When I've needed to use their support it was great. The sites we're moving to Ploi are currently on Cloudways. They've also been good - just more expensive for us than we think Ploi will be. We'll definitely keep some sites with them though. They do have Apache on their servers if you need, and I love just being able to duplicate sites with a click. Lastly we have a couple of sites on the bog standard Hetzner hosting. The control panel is archaic but they are updating it. We'll probably move these sites over to Ploi as well just to keep things neat, but if you just have a single site to deal with then it's probably a cheap option.
  6. Just came across the same 404 error that @rastographics was having. In my case it was because I was using a default nginx config that had a default rewrite rule of: try_files $uri $uri/ /index.php?$args; rather than rewriting to ?it= try_files $uri $uri/ /index.php?it=$uri&$args; Turns out that PW PagesRequest has a fallback so that using the different rewrite url mostly just worked (I've been using it for weeks and hadn't noticed anything), but @bernhard is explicitly looking in $_GET['it'] to see if livereload needs to be returned. Updating the rule as above fixed things. It might have been a completely different reason for @rastographics of course, but just in case someone else has the same issue that's what did it for me.
  7. @bernhard Absolutely no problem! I do really appreciate all the work you do already. I did try building my own module to do the same kind of thing ... but it just wasn't as good as yours 🙂
  8. This one's been a long time coming, but this week we launched a site for the UK charity INQUEST who provide support for families involved in state related deaths. This was part of their 40th Anniversary and the site showcases significant milestones and events from their archive over the last 40 years. There's an interactive timeline, case studies and oral histories. Even given the difficult subject matter we're really pleased with the result: Behind the scenes, the modules we used were mostly the usual suspects, Tracy Debugger, ProCache etc. Also RockFrontend specifically for the ajax routing (would love that as a separate module @bernhard ) which we used with HMTX in various places. Not sure we really needed to use HTMX on this one but hey, it is very handy. One module we made use of which we hadn't used before was @Richard Jedlička's PDF fieldtype so that we could generate thumbnails of PDF documents. There are a lot of historical documents on the site and having the thumbnails generated automatically was really handy. The site seems to have gone down really well. And we actually had a launch party - it's been years since that happened... https://history.inquest.org.uk/ Oh, and it does very nicely in Lighthouse and gets A+ in Observatory as well 🙂
  9. @Robin S - you are great. That's fantasticially helpful. I don't think I've used findRaw before but it worked a treat. According to Profiler rebuilding the markers has gone from 31 seconds to 0.3 secs: It took me a couple of goes to convince myself it was actually rebuilding the markers and not pulling from cache - but it is!
  10. So. I have a lovely map (really must write up that site one of these days), that pulls address data for each marker from a repeater field. Each shop can have multiple addresses with a lat lng and a few other fields. The marker data is cached as geojson so it doesn't get generated each visit, and I refresh that cache every so often when new locations have been added. That's all good, but rebuilding the geojson is beginning to take too long. At the moment I have a page selector for all the shops which then loops through all the addresses and then pulls out the location. I thought I'd try just building a query in SQL to see if I could pull out the locations directly, but I'm struggling to get the relation of the address repeater page to the shop efficiently. The relation seems to be that the parent of the address repeater has the name 'for-page-' + the page id of the shop page. The kind of thing I'm after in psuedocode is: Select all the adresses (template 'repeater_addresses') Left join those addresses on their parents ( address.parent_id = pages.id) And then join those to the relevant shop page ( 'for-page-' + shop.id = address_parent.name ) reading that makes me think it'll have to be more that one query (and maybe I have it backwards and need to start with shops), but hey, I thought I'd see if anyone smarter than me had done this already or had any good suggestions In PageFinder.php Ryan does something fancy with names and aliases but I haven't really got a handle on what he's doing. This is really not an important thing at all, but I'm always keen to learn new ways to break things. s.
  11. One fairly simple thing to do (if you have access to the domain name) would be to use Cloudflare to proxy the site. The free tier includes their CDN which is going to help enormously and means you don't have to worry about integrating a CDN with your website. You should also make sure that the images that are getting requested have been suitably resized. You don't want to be serving large images to users checking their email on a phone. Also - your webserver should be able to handle 450K requests anyway. Especially given that Gmail etc will cache your newsletter images, and that many email clients won't even load remote images, I'd check that that the problem really is too many requests coming in and not something else. If it is a problem with the server being overloaded then you should probably look at different hosting.
  12. millipedia

    PHP Hosting

    We've been using Cloudways for a while now and they've been good for us. Not as cheap as Hetzner but they include some useful hosting management ( git deployment, staging environments, Let's Encrypt etc). And just being to duplicate sites at the click of a button is frankly great. Shout out to Krystal as well if you want a more traditional cPanel setup with email. I'm sure someone in this forum put me on to them - they've worked well for us as well.
  13. I'm with Jan here. I have a local copy of the files I'm working on (templates, modules, assets etc) and then ftp them from VSCode using the SFTP extension. I don't have the files upload automatically when they're saved but my muscle memory for uploading a file on save is good. I've tried using Remote Host in VSCode and occasionally use continuous integration with GitHub but for most of my projects that's overkill.
  14. Just reminding myself of what else we did, and there's also some form obfuscation going on. I'm rot13ing the comments form markup (with the injected field above) and then when the user clicks the comment button I'm unobfuscating it and getting Cloudflare to fire it's challenge. I just thought that not having the form visible without some user inaction might fool a couple of bots. Of course now my secret is out ....
  15. Well it's been trundling along for the last year on the British Record Shop Archive using the above method. We've had a couple of thousand comments ... and I honestly don't remember having a single bit of spam (famous last words there) so I'd say it's been pretty successful. I'm planning to redo the comments forms on the BRSA to allow users to submit images, so I'm probably going to end up with a custom form rather than the above, but it's worked so far.
  16. KDE Plama user here and very happy with it (currently KDE Neon but sometimes Kubuntu). I do also own a Mac becasue we sometimes build apps which needs me to use XCode, and I have a laptop that I can dual boot into Windows but I can't even remember the last time I had to do that and most of my day is spent in Linux. I'd agree that the main drawback is the gap in graphics software. I use Affinity Designer on the Mac which is great, but whilst it nearly runs in Wine it's not quite there yet. Apart from that my development stack on Maxc and Linux is pretty much identical so it's dead easy to swap between them. The designers I work with nearly all use Figma these days so it's been a while since I was given a PSD anyway (which Affinity Desginer deals with very well). You should definitely give Plasma a go if you want to be able to tweak your desktop .... although I warn you will spend a lot of time tweaking your desktop ....
  17. I had to do this just the other week. We had an old CMSMS site that we'd moved to PW. We had a db table with the old user names and passwords in which we stuck on the new site, and then just created our own login page which first checked to see if we had the user in PW already. If the user isn't already in PW then check the password against the old table; If it matches then use that information to add a new user to PW. The users don't really notice that anything has changed. Here's the code I used for that - you'll have to adapt to your circumstances of course but it worked well for our move. if ($input->post('ml_name')) { // when processing form (POST request), check to see if token is present // (we have a CSRF field on our login form) if ($session->CSRF->hasValidToken()) { // form submission is valid // okay to process } else { // form submission is NOT valid throw new WireException('CSRF check failed!'); } $ml_name = $sanitizer->name($input->post('ml_name')); $ml_pass = $input->post('ml_pass'); // dont allow the guest username if ($ml_name === 'guest') { throw new WireException('Invalid username'); }; // do we have this user in PW already? $u_exists = $users->get("$ml_name"); if ($u_exists->id) { // user exists // lets try and log them in try { if ($session->login($ml_name, $ml_pass)) { $session->redirect('/'); } else { $ml_feedback = 'Unknown details.'; } } catch (WireException $e) { // show some error messages: // $e->getMessage(); } } else { // ok - well do we have this user in the old CMS table? $query = $this->database->prepare("SELECT * FROM `cms_module_feusers_users` WHERE username = :login_name LIMIT 1;"); try { $query->execute(['login_name' => $ml_name]); } catch (PDOException $e) { die ('Error querying table : ' . $e->getMessage()); } // we've got a user from the old table if($query && $row=$query->fetch()) { $ml_feedback='Is in old table'; $hash=$row['password']; // handily the old auth just uses password_verify if(password_verify($ml_pass, $hash)){ // Add this user to the PW users $new_user=$users->add($ml_name); if($new_user){ $new_user->pass=$ml_pass; $new_user->addRole('members'); $new_user->save(); $log->save("new_members_site", $ml_name . " added as user"); $u = $session->login($ml_name, $ml_pass); if($u) { $session->redirect('/'); } else { die("Error in logging in. Please contact admin."); } $ml_feedback='new user added to PW'; }else{ $ml_feedback='Unable to add new user. Please let admin know'; } }else{ $ml_feedback='No matching records found.'; } }else{ $ml_feedback='No record found.'; } } } and this is the login form that the we had on our new login page - this and the above was all in a single template. <form id="ml_login_form" class="ml_login_form" method="POST"> <?php echo $session->CSRF->renderInput(); ?> <label for="ml_name">Username</label> <input id="ml_name" name="ml_name" type="text" value="<?= $ml_name ?>" required> <label for="ml_pass">Password</label> <input id="ml_pass" name="ml_pass" type="password" value="<?= $ml_pass ?>" required> <div style="display: none;"> <label for="ml_pass_bear">Password</label> <input id="ml_pass_bear" name="ml_pass_bear" type="text" value=""> </div> <button type="submit" name="ml_submit" class="butt">Submit</button> <div class="ml_feedback"><?= $ml_feedback ?></div> </form>
  18. Depending on your requirements, the Stripe payment processor for FormBuilder might be worth investigating. You can set Paypal to be a payment option in Stripe so that users can pay using PayPal but you can keep all your transactions on the same plaform. Out of the box FormBuilder might not do everything you need (if you need a basket etc) but it is possible to hook into the module to update line items / prices etc. We recently built a basket system for a site that we'd wired directly into Stripe but then shifted over to hook into Formbuilder instead because it already did a lot of the heavy lifting in using the Stripe API.
  19. So, today I learned that you can use a config-dev.php file which takes precedence over the normal config.php file if it's present. ... unfortunately I discovered this by accidentally uploading a config-dev file to a live site. I'd got two config files for live and staging in my project folder and just renamed them when I wanted to update a setting - I'd coincidently named the file for the staging details as config-dev.php and accidently uploaded it to production. Luckily this just meant that the content from the staging site got displayed which wasn't too out of date so hopefully no one noticed.... Now I look into it, I can see that's it been around for ever and there's been lots of chat about it, but hey, I didn't know about it, so thought I'd stick it in this thread just in case anyone else was a daft as me.
  20. Obviously you should try and educate your client into the advantages of building in PW (and in the difficulties of designing a pixel perfect site that works across all browser and devices) but if they really insist on being able to fiddle then WebFlow is probably the kind of thing they want. Not a PW solution, but it does work well once you get the hang of it. We lost a client of 20 years to it last year ?
  21. Bernhard's AdminRockStyle is probably the easiest way to go, but there's a blog post from Ryan which covers how to customise the admin theme using Less. We keep a slightly more accessible colour scheme in our skeleton project as a starting base for new sites for example, and it would be easy enough to add a larger font size in there.
  22. One thing that has improved the speed at which I can mark up a design from Figma is the VS Code extension. I can open a design in a VS Code tab, and then not only see the the properties for an element but also have them appear as auto-complete suggestions as I type. Given that mostly I'm just grabbing one or two properties for an element that's really useful. The same goes for assets; I can copy SVG elements directly to paste into my markup or export them straight into my project folder. If you use Figma and VS Code then it's definitely worth checking out.
  23. Great - that's really useful. I didn't know about the 'always' condition in .htaccess (even though it's all over the place in the usual .htaccess file ....). I think a combination of that and catching my errors earlier should do me. Thanks for your help.
  24. We're building a Capacitor app that grabs data from the OpenAI API via ProcessWire (it's a fun project - I'll write it up once it's done). For successful requests we're adding a CORS header: header('Access-Control-Allow-Origin: *'); header('Content-Type: application/json'); and that's all good. Occasionally though we'll get a timeout form OpenAI (or I've done something daft in the code) and PW will throw a 500 error. Because that response doesn't have the correct headers then I can't catch the error in the app. I've tired adding the header into wire()->addHookBefore('Page::errorPage', function($event) { but I'm not convinced that 500 errors even get there. Suggestions as to how I can a header gratefully received....
×
×
  • Create New...