sparkapi / sparkapi4p2

A PHP wrapper for the flexmls REST API.
GNU General Public License v3.0
26 stars 28 forks source link

Question about enabling WordPress cache #56

Closed ygagnon closed 3 years ago

ygagnon commented 3 years ago

Good afternoon. I see in the examples that it's possible for us to enable the caching of the Spark API data in a WordPress database. I just have 2 quick questions regarding that.

1) Do I first need to manually create the "api_cache" table in the MySQL database? Or does the enabling of the WordPress cache create that table for me automatically?

2) How frequently does the WordPress cache get flushed and then repopulated? And is there a way that the flushing and repopulating of the cache can be forced or automated? If so, how?

Thanks, -- Yvan

dgmyrek commented 3 years ago

Hello, if you're attempting to use the WordPress caching built into the Spark API client it will piggyback on the innate WordPress caching mechanism set up for your site. Otherwise, if you're not using the default WordPress cache mechanism or a plugin has extended the WordPress cache you'd need to create the table here and ensure you're passing the appropriate cache object for your database type.

The cache time would be established by the client when calling one of the helper functions. There isn't a mechanism in the client to force a flush or repopulation. Note that each cache entry is prefixed with "SparkAPI_", which should aid in locating applicable cache keys for manual flushing in the database.

ygagnon commented 3 years ago

Thanks for your reply -- and I apologize for my delayed response. It's funny .. I've been building WordPress sites for well over 12+ years now, and I never even know that there was an "innate caching mechanism" within it. I always thought that 3rd party caching plugins were necessary for that. So .. thank you for enlightening me about that.

On the site that I'm currently developing, I'm routinely using this method to retrieve data from the API:

$mlsdata = $api->get("listings", array( "parameters" => array( '_select' => "ListingId, ListAgentMlsId, ListOfficeName, Photos, MlsStatus, OpenHousesCount, OnMarketContractDate, UnparsedAddress, ListPrice, OriginalListPrice, UnparsedFirstLineAddress, BathroomsTotalDecimal, BedsTotal, PublicRemarks, GarageSpaces, BuildingAreaTotal, LotSizeDimensions, OpenHousesCount, LotSizeArea, WaterFrontYN, VirtualTourURLUnbranded, YearBuilt, Rooms, CustomFieldsExpanded", '_pagination' => 1, "_filter" => "ListingId Eq '$querystring*'", '_limit' => 1, '_page' => 1, '_expand' => 'Photos, Videos, VirtualTours, OpenHouses, Rooms, CustomFieldsExpanded' ) ));

Is this were I would need to add the "cache_time" parameter? I ask because most of the parameters appear to be prefixed with underscores, so I'm wondering if I might be needing to specify this parameter elsewhere, and if so where exactly.

Assuming that I'm looking in the correct place, .. how and where might I modify that above query so that it specifies a cache_time value of - say - 24 hours (or 86400 seconds) ?

Thanks! -- Yvan

dgmyrek commented 3 years ago

Is this were I would need to add the "cache_time" parameter? I ask because most of the parameters appear to be prefixed with underscores, so I'm wondering if I might be needing to specify this parameter elsewhere, and if so where exactly.

Yes, that is the correct function. "cache_time" would be inserted as a top level parameter. In other words, it isn't nested within the "parameters" array. Here's an example to help demonstrate the proper syntax:

$api->get("listings", array( "cache_time" => 86400, "parameters" => array( '_select' => "ListingId....

If you'd prefer not to pass your cache timer in seconds and would rather use some other measure there is a parse_cache_time helper function for that as well: https://github.com/sparkapi/sparkapi4p2/blob/master/lib/Core.php#L145

ygagnon commented 3 years ago

Thanks so much for your reply -- and I apologize for my delayed response.

I have a related question, and am hoping that the answer is simple. I currently have multiple different API queries in place throughout the WordPress site that I've been developing. For example, in one place I have a query that retrieves only a minimal amount of data for listings that are in a specific neighborhood, and that meet specific filter criteria (for displaying a grid of listings sorted from highest price to lowest price). And in another place, I have an altogether different query that retrieves data for just a single listing (based on the MLS number - for a property detail page). My intention is to eventually implement additional queries, .. like one for retrieving only SOLD listings, for example. Or for retrieving only land / empty lots, etc.

My assumption is that what I'm describing is a very common scenario, representing how the API is generally used. So my question is, .. how does caching play in to this? If, for example, I specify the same exact cache time value for each of my multiple different API queries, .. do they all automatically just use the same cache / object store? Or does each of the different queries create and retrieve from it's own separate cache / object store?

And if there's only one main cache that's shared by all of the different API queries .. should my "main" query be crafted so that it retrieves ALL of the necessary data so it'll be available to the other queries? To clarify -- I'm only retrieving about 10 different data fields when I'm displaying a grid of listings. But I'm then retrieving 25+ different fields on my property detail page. So .. what's the best practice here?

One final question regarding the flushing of the cache .. can I simply (and temporarily) just specify a cache time value of -- say -- 2 seconds if I want to quickly flush and re-populate my cache? Or is it only possible to flush the cache by deleting those "SparkAPI_" prefixed entries from the database?

Thanks! -- Yvan

ygagnon commented 3 years ago

Hi again. It's now been a few weeks and I still haven't heard back, .. so I thought I'd take a stab at trying to summarize my question a bit more:

On a site where there are multiple, completely different Spark API queries scattered throughout it .... do they all share the exact same cache? Or does each of these separate queries have it's own unique cache?

-- Yvan

dgmyrek commented 3 years ago

Tracing the caching functions and the code that calls it indicates that each cache key is constructed based on the URI, headers, and "cacheable_query_string" variable. That cacheable_query_string variable is better defined here. This indicates that any difference in parameters values (such as a different _filter, _page, _limit, etc) would not share a cache key with other queries. Only an effectively identical request should share a key.

ygagnon commented 3 years ago

Thanks so much .. I think that clears it up for me. And what about flushing and repopulating these caches? Can I just temporarily specify a cache time value of -- say -- 2 seconds if I want to quickly flush and re-populate it? Or is it only possible to flush the cache by deleting those "SparkAPI_" prefixed entries from the database?

dgmyrek commented 3 years ago

I haven't tried that myself, so I can't say with certainty how the environment will behave. My expectation is that the client would still detect the pre-existing cache record and not create a new cache key in that instance, thus not working for a flush.

ygagnon commented 3 years ago

I can't seem to figure out how to update my query with the "cache_time" parameter when using the "GetListings()" method. Would you be so kind as to point out where I should put it in my code example below?

UPDATE #1: I think I figured it out (see updated code below). However .. I can't seem to locate any kind of "api_cache" table in my WordPress database. I don't have any kinds of caching plugins installed on the site or anything, so if I'm really using WordPress's innate caching mechanism, then where exactly is the cached data being stored?

UPDATE #2: I've located the cache entries in the wp_options table, and I created a simple plugin that fires off this query to purge all of the Spark API specific entries:

$wpdb;
$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '%_SparkAPI_%'" );

It seems to be working great. Thanks again for all your help.

$api->SetCache( new SparkAPI_WordPressCache() );

$mlsdata = $api->GetListings(
array(
        'cache_time' => 3600,
    '_select' => "ListingId, ListAgentMlsId, PrimaryPhoto, MlsStatus, OpenHousesCount, UnparsedAddress, ListPrice, OriginalListPrice, OnMarketContractDate, UnparsedFirstLineAddress, BathroomsTotalDecimal, BedsTotal, BuildingAreaTotal, LotSizeDimensions, OpenHousesCount, LotSizeArea, WaterFrontYN, YearBuilt, PropertyType, PriceChangeTimestamp", 
    '_pagination' => 1, 
    '_filter' => "MLSAreaMinor eq '4190' and (PropertyType eq 'A' or PropertyType eq 'C') and (MlsStatus eq 'Active' or MlsStatus eq 'Pending' or MlsStatus eq 'Contingent' or MlsStatus eq 'Backup')",
    '_limit' => 50,         
    '_page' => 1,
    '_expand' => 'PrimaryPhoto', 
    '_orderby' => '-ListPrice'
    )                       
);  
dgmyrek commented 3 years ago

My apologies for the delayed response @ygagnon. I've been covering for a coworker who has been out of the office for the past couple of weeks. It sounds like you have things up and running appropriately now?

ygagnon commented 3 years ago

Yes .. I think I do have everything up and running now, ... unless, of course, you're noticing any issues with my code examples above. Does everything appear to be in order?

Thanks, -- Yvan

dgmyrek commented 3 years ago

Eyeballing your example here, I don't see any problems!