PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
← All changes | api/Resource/ShopResource.php +74 -1 1.3.20 → 1.6.5 View file →
@@ -94,9 +94,9 @@
94 94
95 95
96 96 $query = static::getQuery()
97 97 ->select(Arr::get($params, 'select', '*'))
98 - ->with(Arr::get($params, 'with', []));
98 + ->with(static::expandAppendRelations(Arr::get($params, 'with', [])));
99 99
100 100 $query = apply_filters('fluent_cart/shop_query', $query, $params);
101 101
102 102 $query = $query->when(!Arr::get($params, 'selected_status'), function ($query) use ($params) {
@@ -261,8 +261,10 @@
261 261 } else {
262 262 $products = $query->simplePaginate(Arr::get($params, 'per_page', 10), ['*'], 'current_page', Arr::get($params, 'page'));
263 263 }
264 264
265 + static::primePostCaches($products);
266 +
265 267 return [
266 268 'products' => $products,
267 269 'total' => $totalCount
268 270 ];
@@ -268,8 +270,66 @@
268 270 ];
269 271 }
270 272
271 273 /**
274 + * Expand the caller's `with` list so the relations that the models' default
275 + * appends read are eager loaded rather than fetched one row at a time.
276 + *
277 + * `ProductVariation::$appends` renders `thumbnail` from its `media` relation and
278 + * `ProductDetail::$appends` renders `featured_media` from `galleryImage`, so every
279 + * serialized row issued its own query — one per variant plus one per product, on a
280 + * public list endpoint. Only relations the caller already asked for are expanded,
281 + * so the response shape is byte-identical; callers that never load `variants` or
282 + * `detail` are untouched.
283 + *
284 + * @param array|string $with Relations the caller requested.
285 + * @return array
286 + */
287 + protected static function expandAppendRelations($with): array
288 + {
289 + $with = Arr::wrap($with);
290 +
291 + $appendRelations = [
292 + 'variants' => 'variants.media',
293 + 'detail' => 'detail.galleryImage',
294 + ];
295 +
296 + foreach ($appendRelations as $relation => $nestedRelation) {
297 + if (in_array($relation, $with, true) && !in_array($nestedRelation, $with, true)) {
298 + $with[] = $nestedRelation;
299 + }
300 + }
301 +
302 + return $with;
303 + }
304 +
305 + /**
306 + * Prime the WordPress post cache for the products on this page.
307 + *
308 + * These rows come from the ORM, not WP_Query, so nothing populates the `posts`
309 + * cache. Every `get_permalink()` behind the `view_url` append — and every core
310 + * template helper a storefront card calls — then fell through to `get_post()`,
311 + * one SELECT per product. This replaces them with a single `IN (...)` read.
312 + * Terms and meta are deliberately not primed: no product-list path reads them
313 + * here, and priming them would cost two more queries.
314 + *
315 + * @param mixed $products Paginator returned by the list query.
316 + * @return void
317 + */
318 + protected static function primePostCaches($products)
319 + {
320 + if (!$products || !method_exists($products, 'getCollection')) {
321 + return;
322 + }
323 +
324 + $postIds = $products->getCollection()->pluck('ID')->filter()->all();
325 +
326 + if ($postIds) {
327 + _prime_post_caches($postIds, false, false);
328 + }
329 + }
330 +
331 + /**
272 332 * Find product by its ID.
273 333 *
274 334 * @param int $productId The ID of the post.
275 335 * @param array $data Additional data for finding product (optional).
@@ -341,8 +401,21 @@
341 401 } else {
342 402 $args['orderby'] = $orderField;
343 403 $args['order'] = $orderDir;
344 404 }
405 +
406 + // Filters the query arguments used to fetch related products.
407 + // Developers can customize the query as needed, such as excluding products
408 + // or modifying the query parameters.
409 + $args = apply_filters(
410 + 'fluent_cart/related_products/query_args',
411 + $args,
412 + [
413 + 'product_id' => $id,
414 + 'post' => $post,
415 + 'config' => $config,
416 + ]
417 + );
345 418
346 419 $query = new \WP_Query($args);
347 420
348 421 // Remove the price filter if applied