Strapi V4 填充动态区域 媒体未填充

Rod*_*bio 11 controller strapi

通过使用下面建议的补丁,数据字段似乎填充正常,但是,媒体字段未填充。

尝试了以下但没有运气 -

* http://localhost:1337/api/pages?populate=*
* {{protocol}}://{{host}}:{{port}}/api/pages?populate[Content][populate]=images
Run Code Online (Sandbox Code Playgroud)

参考 - https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest/populate-fields.html#component-dynamic-zones

下面的示例来自 - https://forum.strapi.io/t/strapi-v4-populate-media-and-dynamiczones-from-components/12670/9

还尝试了这个插件(没有运气) - https://www.npmjs.com/package/strapi-plugin-populate-deep

下面带有动态区域的页面示例 -

在此输入图像描述

/helpers/populate.js(这适用于除图像之外的所有数据)-

const { createCoreController } = require("@strapi/strapi/lib/factories");

function populateAttribute({ components }) {
  if (components) {
    const populate = components.reduce((currentValue, current) => {
      return { ...currentValue, [current.split(".").pop()]: { populate: "*" } };
    }, {});
    return { populate };
  }
  return { populate: "*" };
}

const getPopulateFromSchema = function (schema) {
  return Object.keys(schema.attributes).reduce((currentValue, current) => {
    const attribute = schema.attributes[current];
    if (!["dynamiczone", "component"].includes(attribute.type)) {
      return currentValue;
    }
    return {
      ...currentValue,
      [current]: populateAttribute(attribute),
    };
  }, {});
};

function createPopulatedController(uid, schema) {
  return createCoreController(uid, () => {
    console.log(schema.collectionName, JSON.stringify(getPopulateFromSchema(schema)));
    return {
      async find(ctx) {
        ctx.query = {
          ...ctx.query,
          populate: getPopulateFromSchema(schema),
        //   populate: '*',
        };
        return await super.find(ctx);
      },
      async findOne(ctx) {
        ctx.query = {
          ...ctx.query,
          populate: getPopulateFromSchema(schema),
          // populate: '*',
        };
        return await super.findOne(ctx);
      },
    };
  });
}

module.exports = createPopulatedController;
Run Code Online (Sandbox Code Playgroud)

/src/api/page/controllers/pages.js -

"use strict";

const collectionType = 'page'

const schema = require(`../content-types/${collectionType}/schema.json`);
const createPopulatedController = require("../../../helpers/populate");

module.exports = createPopulatedController(`api::${collectionType}.${collectionType}`, schema);
Run Code Online (Sandbox Code Playgroud)

以下图片的响应无法通过 -

{
  "data": [
    {
      "id": 1,
      "attributes": {
        "title": "testing home page",
        "slug": "/",
        "publish_at": null,
        "createdAt": "2022-04-12T12:08:32.002Z",
        "updatedAt": "2022-04-12T15:07:11.990Z",
        "publishedAt": "2022-04-12T12:42:55.682Z",
        "locale": "en",
        "seoComponent": null,
        "block": [
          {
            "id": 1,
            "__component": "image.image-copy-full",
            "heading": "Delivering something amazing",
            "subHeading": "test sadasdf",
            "ctaButton": "test",
            "miscValues": {
              "testing": "object field"
            },
            "actionUrl": null,
            "isInternal": true,
            "isVisible": true
          },
          {
            "id": 1,
            "__component": "image.image-copy-chip",
            "heading": "A platform",
            "subHeading": "Allowing full integration",
            "ctaButton": null,
            "miscValues": null,
            "actionUrl": null,
            "isInternal": true,
            "isVisible": false
          },
          {
            "id": 1,
            "__component": "image.image-copy",
            "heading": "To transform our world",
            "subHeading": "In order to reach that scale",
            "ctaButton": null,
            "miscValues": null,
            "actionUrl": null,
            "isInternal": true
          }
        ]
      }
    }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "pageSize": 25,
      "pageCount": 1,
      "total": 1
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

屏幕截图中“ImageCopyFull”的架构示例 -

{
  "collectionName": "components_image_image_copy_fulls",
  "info": {
    "displayName": "ImageCopyFull",
    "icon": "file-image",
    "description": ""
  },
  "options": {},
  "attributes": {
    "heading": {
      "type": "string"
    },
    "subHeading": {
      "type": "string"
    },
    "ctaButton": {
      "type": "string"
    },
    "miscValues": {
      "type": "json"
    },
    "actionUrl": {
      "type": "string"
    },
    "isInternal": {
      "type": "boolean",
      "default": true
    },
    "image": {
      "type": "media",
      "multiple": false,
      "required": true,
      "allowedTypes": [
        "images",
        "videos",
        "audios",
        "files"
      ]
    },
    "isVisible": {
      "type": "boolean",
      "default": false
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Rub*_*shi 17

受到推崇的

强烈建议您观看此YouTube 视频以了解本机解决方案。

简单快速的解决方案

您可以使用市场上的Populate Deep 插件。

您只需使用以下命令安装该软件包:

yarn add strapi-plugin-populate-deep
Run Code Online (Sandbox Code Playgroud)

然后使用您的填充参数及其值,deep如下所示:

/api/articles/1?populate=deep
Run Code Online (Sandbox Code Playgroud)

  • 尽管它是一个很好的插件,但它会影响应用程序的性能。我停止使用它并在 Strapi 中本地处理填充。这是一本很好的书,可以了解更多信息 https://strapi.io/blog/demystifying-strapi-s-populate-and-filtering (2认同)

Pau*_*aul 5

我不使用填充插件并在 Strapi 中本地处理它。您知道吗,您可以在 Strapi 路由中间件中添加填充逻辑。

这是一个简单的例子。

在我的 Next JS 项目中。我调用 getPageBySlug() 函数

export default async function PageRoute({params}: Props) {
    const page = await getPageBySlug(params.slug, params.lang);
    if (page.data.length === 0) return null;
    const contentSections = page.data[0].attributes.contentSections;
    return contentSections.map((section: any, index: number) => sectionRenderer(section, index));
}
Run Code Online (Sandbox Code Playgroud)

getPageBySlug() 调用 Strapi API。请注意我如何没有传递任何填充逻辑。相反,这是在我的 Strapi 应用程序路由中间件中处理的。

import {fetchAPI} from "@/app/[lang]/utils/fetch-api";

export async function getPageBySlug(slug: string, lang: string) {
    const token = process.env.NEXT_PUBLIC_STRAPI_API_TOKEN;

    const path = `/pages`;
    const urlParamsObject = {filters: {slug}, locale: lang};
    const options = {headers: {Authorization: `Bearer ${token}`}};
    return await fetchAPI(path, urlParamsObject, options);

Run Code Online (Sandbox Code Playgroud)

这是我的 Strapi 应用程序中处理人口的路线中间件。无需使用填充深度插件,它将返回所有内容。

相反,我的中间件仅返回我的网站所需的项目。

"use strict";

/**
 * `page-populate-middleware` middleware
 */

const populate = {
  contentSections: {
    populate: {
      picture: {
        fields: ["url", "alternativeText", "caption", "width", "height"],
      },
      buttons: {
        populate: true,
      },
      feature: {
        populate: {
          fields: ["title", "description", "showLink", "newTab", "url", "text"],
          media: {
            fields: ["url", "alternativeText", "caption", "width", "height"],
          },
        },
      },
      testimonials: {
        populate: {
          picture: {
            fields: ["url", "alternativeText", "caption", "width", "height"],
          },
        },
      },
      plans: {
        populate: ["product_features"],
      },
      submitButton: {
        populate: true,
      },
    },
  },
  seo: {
    fields: ["metaTitle", "metaDescription"],
    populate: { shareImage: true },
  }
};

module.exports = (config, { strapi }) => {
  // Add your own logic here.
  return async (ctx, next) => {
    ctx.query = {
      populate,
      filters: { slug: ctx.query.filters.slug },
      locale: ctx.query.locale,
    };

    console.log("page-populate-middleware.js: ctx.query = ", ctx.query);

    await next();
  };
};
Run Code Online (Sandbox Code Playgroud)

我并不是说您不应该使用填充深度插件,但要知道这可能会对性能产生影响。

以下是一些资源,可帮助您了解有关如何本地执行 Strapi 填充和过滤的更多信息。

https://strapi.io/blog/demystifying-strapi-s-populate-and-filtering

示例项目: https: //github.com/strapi/nextjs-corporate-starter

如果您对 Strapi 有其他疑问,请随时在此处提问。但我们在 Strapi 的 Discord 上也有开放办公时间(中部标准时间周一至周五中午 12:30)。

希望这有帮助。

我还制作了一个涵盖所有这些主题的速成课程视频。 https://youtu.be/RceLeh9D85o?feature=shared

保罗