Can't get createdBy from api

System Information
  • Strapi Version: 4.0.6
  • Operating System: Ubuntu 20.04
  • Database: Postgres
  • Node Version: 14.17
  • NPM Version: 6.14
  • Yarn Version: 1.22

I’m trying to reach a content information from a collection type by strapi api and I can’t get the createdBy data. I’ve already tried population and fields selection and it didn’t work. Can someone help please?

2 Likes

Seems like there is an issue related with “populateCreatorFields” in the documentation. I’ll paste my answer here. Hope it helps.

Here is some workaround. It doesn’t need to set “populateCreatorFields” options. You can use strapi db query and ask to populate createdBy field.

If you use Graphql API, you need to extend the query you want

// path: ./src/index.js

module.exports = {
  register({ strapi }) {
    const extensionService = strapi.plugin('graphql').service('extension');

    const extension = ({ nexus }) => ({
      types: [
        // creating new object type called Creator
        nexus.objectType({
          type: 'Creator',
          name: 'Creator',
          definition(t) {
            t.int('id');
            t.string('firstname');
            t.string('lastname');
          },
        }),
        nexus.extendType({
          type: 'Article',
          definition(t) {
            // we want to know who is the creator
            t.field('createdBy', {
              type: 'Creator',
              async resolve(root, args, ctx) {
                // when we use query, we can populate createdBy
                const query = strapi.db.query('api::article.article');
                const article = await query.findOne({
                  where: {
                    id: root.id,
                  },
                  populate: ['createdBy'],
                });
                
                return {
                  id: page.createdBy.id,
                  firstname: page.createdBy.firstname,
                  lastname: page.createdBy.lastname,
                };
              },
            })
          }
        }),
      ],
    });

    extensionService.use(extension);
  }
}    

When I query articles, I can ask for the createdBy

query {
  articles {
    data {
      attributes {
        createdBy {
          id
          firstname
          lastname
        }
      }
    }
  }
}

If you use REST API, you can extend the controller

'use strict';

/**
 *  article controller
 */

const { createCoreController } = require('@strapi/strapi').factories;

module.exports = createCoreController('api::article.article', ({ strapi }) => ({
  async find(ctx) {
    // Calling the default core action
    const { data, meta } = await super.find(ctx);

    const query = strapi.db.query('api::article.article');

    await Promise.all(
      data.map(async (item, index) => {
        const article = await query.findOne({
          where: {
            id: item.id,
          },
          populate: ['createdBy'],
        });
        
        data[index].attributes.createdBy = {
          id: page.createdBy.id,
          firstname: page.createdBy.firstname,
          lastname: page.createdBy.lastname,
        };
      })
    );

    return { data, meta };
  },
}));
2 Likes

Thanks @niwasmala .

Turns out that I found a solution too. I overwrote the findOne method in controller and did this:

"use strict";

/**
 *  member controller
 */

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

module.exports = createCoreController("api::member.member", ({strapi}) => ({
  async findOne(ctx) {
    const {id} = ctx.params;
    const {query} = ctx;

    const entity = await strapi.service('api::member.member').findOne(id, query);
    const sanitizedEntity = await this.sanitizeOutput(entity, ctx);

    sanitizedEntity.createdBy = {
      id: entity.createdBy.id,
      email: entity.createdBy.email
    };

    return this.transformResponse(sanitizedEntity);
  }
}));

I found that the sanitizeOutput method was the one responsible for omitting the createdBy info, so I just added the data myself.

Solution not working in Strapi V4. Need a detail solution from someone. @niwasmala @cillaeslopes
I am using GraphQL for fetching data. Please help me.

@Shekhar Solution posted by @niwasmala for GraphQL worked for me Strapi v4.3.6

src/index.js

"use strict";

module.exports = {
  /**
   * An asynchronous register function that runs before
   * your application is initialized.
   *
   * This gives you an opportunity to extend code.
   */
  register({ strapi }) {
    const extensionService = strapi.plugin("graphql").service("extension");

    const extension = ({ nexus }) => ({
      types: [
        nexus.objectType({
          type: "Creator",
          name: "Creator",
          definition(t) {
            t.int("id");
            t.string("firstname");
            t.string("lastname");
          },
        }),
        nexus.extendType({
          type: "Post",
          definition(t) {
            t.field("createdBy", {
              type: "Creator",
              async resolve(root) {
                const query = strapi.db.query("api::post.post");
                const post = await query.findOne({
                  where: {
                    id: root.id,
                  },
                  populate: ["createdBy"],
                });

                return {
                  id: post.createdBy.id,
                  firstname: post.createdBy.firstname,
                  lastname: post.createdBy.lastname,
                };
              },
            });
          },
        }),
      ],
    });

    extensionService.use(extension);
  },
  
  /**
   * An asynchronous bootstrap function that runs before
   * your application gets started.
   *
   * This gives you an opportunity to set up your data model,
   * run jobs, or perform some special logic.
   */
  bootstrap(/*{ strapi }*/) {},
};

the rest api should be like this

'use strict';

/**
 *  article controller
 */

const { createCoreController } = require('@strapi/strapi').factories;

module.exports = createCoreController('api::article.article', ({ strapi }) => ({
  async find(ctx) {
    // Calling the default core action
    const { data, meta } = await super.find(ctx);

    const query = strapi.db.query('api::article.article');

    await Promise.all(
      data.map(async (item, index) => {
        const article = await query.findOne({
          where: {
            id: item.id,
          },
          populate: ['createdBy'],
        });
        
        data[index].attributes.createdBy = {
          id: page.createdBy.id,
          // not work on me
          // firstname: page.createdBy.firstname,
          // lastname: page.createdBy.lastname,

          // change the page into article so it work
          firstname: article.createdBy.firstname,
          lastname: article.createdBy.lastname,
        };
      })
    );

    return { data, meta };
  },
}));
3 Likes

Thanks ! :slight_smile: