Jump to content

Jonathan Lahijani

Members
  • Posts

    629
  • Joined

  • Last visited

  • Days Won

    23

Posts posted by Jonathan Lahijani

  1. I wanted to share the way I enable Tracy Debugger for myself (a superuser) and myself only, only when logged in.  This is useful if there are other superusers that are not developers and you don't want them to see the Tracy Debugger bar.

    There's a variety of settings and methods related to this, but I wanted to distill it into a few short steps:

    • create a permission called 'tracy-debugger' (note: Tracy Debugger doesn't create this permission for you during installation)
    • create a role called 'developer' (sounds like the right name to me)
    • assuming you're a superuser, edit your account and assign the 'developer' role; if there are multiple developers on the project, consider assigning them this role as well
    • in Tracy Debugger's settings do the following:
      • Main Setup → Output Mode → DEVELOPMENT
      • Access Permission → Restrict Superusers → checked
  2. I'm putting this here in case anyone finds this useful (or I google this myself in a few years)...

    Let's say you have the following in config.php:

    // config.php
    $config->myArray = [
      'foo' => [
        'k1' => 'v1',
    	'k2' => 'v2'
      ],
      'bar' => 'some string',
      'baz' => ['some', 'other', 'array']
    ];

    Now you want to want to add an item to the 'foo' array somewhere else in your codebase (template file, a module's init method, etc.).  This won't work (overloaded notice will occur):

    $config->myArray['foo']['k3'] = 'v3';

    Correct way to do it:

    $config->myArray = array_merge(
      $config->myArray,
      [
        'foo' =>
          // existing
          $config->myArray['foo'] +
          // new
          [
            'k3' => 'v3'
          ]
      ]
    );

     

    • Like 2
  3. I have a URL hook like this which acts as an API endpoint:

    wire()->addHook('/foo/', function(HookEvent $event) {
      bd($event);
    }); 

    That endpoint will be hit from somewhere with some post data, outside of ProcessWire.  As you can see, I have a bardump to log $event, but I won't be able to see that output because it's coming from some outside request.  How do I actually log it and store it (without using ProcessWire's own $log capabilities)?

  4. I'm developing a very advanced ecommerce site with ProcessWire and an order needs to have various related pieces of data.  To keep it simple for this example, an order should log payment attempts ('payment' template) and the items that were fulfilled ('fulfillment' template).

    Let's assume our order is here in the page tree, where 123 represents a page using the 'order' template (which contains the billing address and things like that): /orders/123/

    One scenario that I often come across when developing ProcessWire sites with strong data relationships is where to put related pieces of data.  In the situation I described, I could do it in one of three ways:

    Approach 1: as child pages of 'order' template
    I could make payments and fulfillments as children of the 'order' template.  This is a ProcessWire-y way to do it.

    Approach 2: under one separate master page
    I could make payments and fulfillments as children of /order-updates/ and establish the relationship using an 'order' page reference field on the 'payment' and 'fulfillment' templates.  This is a blend between traditional database design and a ProcessWire-y way to do it.

    Approach 3: under multiple master pages
    I could make payments as children of /payments/ and fulfillments as children of /fulfillments/ and establish the relationship using an 'order' page reference field on the 'payment' and 'fulfillment' templates.  This is a traditional database design way to do it.

    What are your thoughts in regards to this specific example?  Do any of them have pitfalls that I don't foresee?  If I had to switch from one technique to another, that would be easy to do with a simple migration script.

  5. I oftentimes create a checkbox field called 'test' and assign it to certain templates.  I check the box if the page is a test page.  These pages may exist on the live site and I don't want to hide or unpublish them, but at the same time, I don't want them to appear in the XML Sitemap.  (not part of this tutorial, but I also noindex,nofollow those pages using a meta tag in the head so search engines don't index them)

    In that case, you can remove them from the WireSitemapXML like this in /site/ready.php:

    $wire->addHookAfter('WireSitemapXML::allowPage', function(HookEvent $event) {
      $page = $event->arguments('page');
      if($page->hasField('test') && $page->test) $event->return = false;
    });

     

    • Like 11
    • Thanks 1
  6. 3 hours ago, rick said:

    You can check out the blog module. It will handle the article content and related info.
    As far as the front-end looking like other magazine layouts, there are numerous free magazine html/css templates and more paid templates. You may want to consider a paid template. The free templates look like free templates. 🙂

    If accessibility and avoiding lawsuits matters, I'd avoid going that route.  I spoke with a developer friend recently whose client got hit with an accessibility lawsuit.  They then had a special accessibility firm audit and maintain the website.  Sometime afterwards they got hit with 2 more accessibility lawsuits, although they were thrown out.  This might be mainly a US phenomenon however... gotta keep those lawyers busy!

    UIkit pushed a big update today that (finally) addresses a lot of accessibility issues.

    • Like 2
  7. I have a field that uses the Files fieldtype.  Images and videos are being uploaded to it.  Because it is not an Image fieldtype, I can't get an image width or height.  I believe there is a way with the Pageimages class, but I'm a bit rusty on how to do this.  There was a post on here that discussed how to do it but I can't find it.  Any help would be appreciated.

  8. I originally developed and launched Real SF Properties in 2015 and did a complete design and programming refresh in 2022:
    https://realsfproperties.com/

    The site was designed by BuzzCandy.Design:
    http://buzzcandy.design/

    This was my first time using Tailwind CSS and it was a great fit for this project. I wish it existed back in 2015 because while UIkit has been my go-to CSS framework for several years now, there are some site designs (and designers) that I work with that simply need a higher level of precision to slice correctly and be maintainable.  Sure, I could have used vanilla CSS and done it the classic way (separation of concerns), but Tailwind CSS and doing everything with utility classes (locality of behavior) does come with major benefits, even if the markup is not so easy on the eyes.

    This site does not use a matrix page builder or anything fancy.  The sections are hardcoded but with the ability to add data using the various page data structures that feed in accordingly.  It has also has an accessibility score that is extremely high.  It's a quick loading site even though ProCache or CDN is not yet enabled.

    Other frontend libraries include Flickity and Headroom.js.

    More details on my personal website:
    https://jonathanlahijani.com/projects/real-sf-properties/

    • Like 6
  9. I wanted to share this tip which I'm going to implement on Transferware Collectors Club Database.

    That site has a form which is a set of filters.  It takes many queries to build that form and all of its options and as a result, it takes over 5 seconds to load the page.  ProCache is out of the question because using a full page cache on a site like that doesn't make sense, but caching various areas with WireCache $cache does.

    The form is developed in a way where it will automatically populate/select the various form fields based on what it reads from the URL.  So going to /?color=123 will automatically check the appropriate radio button for that color.  Therefore, when using $cache to cache the form (or parts of the form), we need to cache the form in a clean, unpopulated state.

    The problem then becomes how do we use the cached form but also populate the fields accordingly based on the URL variables?  Markup regions can do this.

    Assuming we had a set of radio options coming from our WireCache'd form like this:

    ...
    <input type="radio" name="color" id="color-123" value="123"> Red
    <input type="radio" name="color" id="color-124" value="124"> Blue
    ...

    We could devise some code that also outputs this on our page:

    <region pw-replace="color-123" checked></region>

    Markup regions will then "check" that radio.

    Perhaps this isn't mind blowing, but I've never thought of using Markup Regions in this way.

    • Like 7
  10. 1 minute ago, adrian said:

    Interesting. I am pretty sure I was testing this feature on my local dev which was running 8.1 at the time, but great to hear it's now working for you regardless. I no longer have access to the dev tools support board so I can't test the latest version of the module - maybe there were multiple issues?

    I should clarify that php 7.4.3 was fpm and php 8.1 was non-fpm.  Not sure if php-fpm played a role.

  11. 1 hour ago, adrian said:

    Nah sorry, I gave up 🙂

    OK I figured it out but don't know the exact reason.  Upgrading from php 7.4.3 to php 8.1 resolved the issue.  I noticed in 7.4.3, the http headers of the request are in lowercase, but in php 8.1, they are in the more proper case.  Also, the headers are listed a little bit differently in 7.4 vs 8.1.  That's probably where the issue is.

  12. On 11/14/2021 at 10:52 AM, adrian said:

    But back to the more important issue of why the module doesn't actually work for me. Firstly, the module does work on my local dev environment, but on a live servers, it doesn't.

    I still keep getting: "ajax error: error"

    If I inspect the Network tab, I see a 500 error for: /page/edit/?id=8074&modified=1636913850&fields=body but there don't seem to be any PHP errors, so I went looking in the apache logs and I am seeing these:

    [Sun Nov 14 09:54:27.525633 2021] [proxy_fcgi:error] [pid 24560:tid 139854520305408] (70007)The timeout specified has expired: [client 154.5.162.190:51384] AH01075: Error dispatching request to : (polling), referer: /?live_preview=1
    
    [Sun Nov 14 09:54:34.477785 2021] [proxy_fcgi:error] [pid 24560:tid 139854579054336] [client 154.5.162.190:51384] malformed header from script 'index.php': Bad header: {"error":false,"message":"Ajax, referer: /page/edit/?id=8074
    
    [Sun Nov 14 09:54:34.477904 2021] [proxy_fcgi:error] [pid 24560:tid 139854579054336] [client 154.5.162.190:51384] AH01070: Error parsing script headers, referer: /page/edit/?id=8074
    
    [Sun Nov 14 09:54:34.477913 2021] [proxy_fcgi:error] [pid 24560:tid 139854579054336] (22)Invalid argument: [client 154.5.162.190:51384] AH01075: Error dispatching request to : , referer: /page/edit/?id=8074

    The Network tab shows Response Headers: content-length: 0

    I did a a little investigating to see if there are any known issues with SSE and these errors, but nothing useful so far.

     

     

    I'm getting the same 500 errors as well in my particular case.  To clarify my situation:

    • occurs on live site (Ubuntu 20.04, Apache 2.4.41, php 7.4.3), but not dev site (Ubuntu 22.04, Apache 2.4.52, php 8.1.2); i mirrored live to dev database as well
    • enable live preview = on (not sse)

    While it 500 errors, the field technically does get autosaved (I can refresh the page without hitting the save button and the updated value is still there).

    I wonder if the Apache or PHP version matters.  Will have to check.

    @adrian Did you ever find a solution to this?

  13. While I'm not using it in real world project yet, the Combo field works well for a "link" field.  For example, you could link something to a page (page field), a external website (url field) or a modal (page field), or a page + url parameters.  Also, what about absolute vs relative URLs?

    Here's an export of that field you can import and play around with:
    https://pastebin.com/N8UuiFKQ

    Somewhat related is this module:

     

    • Like 2
    • Thanks 1
  14. I have a page field that I am hooking into and providing the custom dropdown values like this:

    $this->addHookAfter('InputfieldPage::getSelectablePages', function(HookEvent $event) {
      if($event->object->hasField == 'my_page_field') {
        $ids = [];
        foreach(wire('pages')->find("...") as $p) {
          $ids[] = $p;
        }
        $event->return = $ids;
      }
    });

    Due to the nature of my site, the amount of items that will populate in that dropdown field will be quite high (over 2000 pages).  Due to this high amount of pages in that dropdown, the PW admin slows down quite a bit (extra 2 seconds) on edit pages that utilize that field.  To counteract this, I have made that field have the Visibility Presentation of Closed + Load when opened (AJAX), however because I am using the hook described above, it will still load the pages even if the field has not yet been opened.

    So my question is, how do I improve the the hook above to execute only after the field has been opened?

×
×
  • Create New...