ukyo Posted May 5, 2023 Share Posted May 5, 2023 I want to track and modify all called $page->* (fields) properties, before property get a value or after property get a value. is it possible to do it with a method like hooks ?? like: id, title, body, image <?php $wire->addHookProperty('Page::*,Page::[id,title,body,image]', function(HookEvent $e) { $page = $e->object; // How to get name of property ??? $property = '???'; $isCached = true; if ($isCached) { $cachedValue = 'Cached value from somewhere'; $value = $cachedValue; } else { $value = $page->get($property); } if ($property === 'title') { $value = "<h1>{$value}</h1>"; } $e->return = $value; }); Link to comment Share on other sites More sharing options...
bernhard Posted May 6, 2023 Share Posted May 6, 2023 I think it would help if you give us some context on why you want to do that and what the actual goal of that is. Link to comment Share on other sites More sharing options...
ukyo Posted May 7, 2023 Author Share Posted May 7, 2023 When I checked a page I created with ProcessWire, I noticed that it was using a lot of SQL queries when displaying a page (600+ SQL queries). This page contains a page builder and similar page links from other pages. The number of queries seemed excessive to me, and I believe it is because a separate table is created for each field. Therefore, I have observed that the number of SQL queries increases based on the number of fields when accessing page data. To address this issue, I have implemented a solution where I save or delete the page data as JSON when the page is saved or deleted (I also want to use this module when generating static pages). If a field needs to be displayed on the page, I want it to be shown from the JSON output if it exists there, otherwise I want it to be retrieved with an SQL query. Link to comment Share on other sites More sharing options...
Robin S Posted May 7, 2023 Share Posted May 7, 2023 28 minutes ago, ukyo said: If a field needs to be displayed on the page, I want it to be shown from the JSON output if it exists there, otherwise I want it to be retrieved with an SQL query. Sounds like it would be a good case for a custom Page method (either added by hook or by custom Page class) that falls back to the core $page->get() when no value exists. $value = $page->getFromJson('some_field'); 2 Link to comment Share on other sites More sharing options...
ukyo Posted May 7, 2023 Author Share Posted May 7, 2023 Sure, However, I don't want to make any changes to regular page displays. When this option is enabled in the module settings, I want it to directly reflect on the page. I am looking for a solution while continuing to use the normal page API. When I use $page->title and if the transfer is enabled for the title field in the module settings and it has been saved as JSON, I want this information to come from the JSON data. When I remove the title field from the module settings, I want this information to be retrieved and displayed using SQL. Link to comment Share on other sites More sharing options...
Jan Romero Posted May 7, 2023 Share Posted May 7, 2023 Maybe you can hook Fieldtype::loadPageField()? https://github.com/processwire/processwire/blob/6ff498f503db118d5b6c190b35bd937b38b80a77/wire/core/Fieldtype.php#L1108 1 Link to comment Share on other sites More sharing options...
ukyo Posted May 8, 2023 Author Share Posted May 8, 2023 18 hours ago, Jan Romero said: Maybe you can hook Fieldtype::loadPageField()? https://github.com/processwire/processwire/blob/6ff498f503db118d5b6c190b35bd937b38b80a77/wire/core/Fieldtype.php#L1108 When using this method, the data is retrieved in its raw form. It requires further processing to display the data. When $page->title is called, the data is initially fetched from the database using this method and undergoes certain operations before appearing as $page->title. The part I want to intervene in is as follows: If the data is present in the saved JSON, show it directly without processing; otherwise, retrieve the data from the database, process it, and display it. Link to comment Share on other sites More sharing options...
Jan Romero Posted May 8, 2023 Share Posted May 8, 2023 Robin’s suggestion of using a custom page class should work for that, just override get(): <?php namespace ProcessWire; class DefaultPage extends Page { private $cache = [ 'title' => 'look at me. i’m the title now.' ]; public function get($key) { return $this->cache[$key] ?? parent::get($key); } } IRL you may want to add logic dealing with output formatting and what not, but that should be a complete working example. Unfortunately get() is not hookable, so I don’t believe this can be accomplished in a module. That said, have you investigated other avenues? Why not cache the whole markup and be done with it? 1 Link to comment Share on other sites More sharing options...
ukyo Posted May 8, 2023 Author Share Posted May 8, 2023 1 hour ago, Jan Romero said: Robin’s suggestion of using a custom page class should work for that, just override get(): <?php namespace ProcessWire; class DefaultPage extends Page { private $cache = [ 'title' => 'look at me. i’m the title now.' ]; public function get($key) { return $this->cache[$key] ?? parent::get($key); } } IRL you may want to add logic dealing with output formatting and what not, but that should be a complete working example. Unfortunately get() is not hookable, so I don’t believe this can be accomplished in a module. That said, have you investigated other avenues? Why not cache the whole markup and be done with it? This seems like the most reasonable solution. When pages are updated or deleted, the data will be automatically updated or removed. I can manage the templates and fields that will be cached easily through module settings. The desired fields and templates are cached, while other fields and templates continue to function as usual in ProcessWire. I have three reasons for obtaining the raw JSON output: 1. To fetch the data and display it directly in the desired format. I don't want the data to be influenced by HTML, so I can use it anywhere. 2. To generate static pages using the data (using libraries like Astro.js). 3. To make the saved data accessible for other applications through an API. Link to comment Share on other sites More sharing options...
Pixrael Posted May 9, 2023 Share Posted May 9, 2023 Read this, it might give you an idea using JSON files: Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now