Jump to content

How to track all called $page->* properties (fields) ?


ukyo
 Share

Recommended Posts

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

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

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');

 

  • Like 2
Link to comment
Share on other sites

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

18 hours ago, Jan Romero said:

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

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?

  • Like 1
Link to comment
Share on other sites

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.

709097057_EkranResmi2023-05-0900_48_07.png.d63d0b04abe572a7d40fe47319ec221c.png

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...