API - Username instead of id on _by/_mby

Hi Guys/Girls

First of all I wanted to make it very clear that, I love Cockpit, I just intended to test it and now I’m using it on everything hahaha.

But I have a question, when requesting /collections/get/posts for example, I get the field _by and _mby which in this case, is referring to the ID of the user who created/changed the entry, right?

How do I bring the username instead of the ID? Because, when adding the AccountLink in the entry, it also returns the ID instead of the Name or even the object with some data of the user who created the entry.

Can anyone give me a hand?
Thank you very much in advance!

By default, it only show id as you said, you have to add populate=1 to display all fields from account link.
e.g

/collections/get/posts?token=1234567890&populate=1

Edit Note

populate only work with CollectionLink, not Account-Link.

2 Likes

I understood,

In a way, it helped me a lot to know about this “populate=1”, I confess that I didn’t know.
I needed to show the Name of a collection called Category, linked as CollectionLink, but the display was just the Slug, and with this “Populate” it worked to show all fields :slight_smile:

But with AccountLink, even using “Populate=1”, it doesn’t show the username or any other field, it just returns the ID anyway :frowning:

My bad, I should have mentioned that populate only work with collectionLink.

And you can’t retrieve accountLink data with collection data at the same time. Maybe it could be the security reason.

Option 1

Fire one more API request with account ID to get the user data

Option 2

Ref answer by raffaelj: How to refer to another Collections or "Accounts" - #7 by raffaelj

  • create config directory in the root folder, under that directory create bootstrap.php file. Add the below codes. Make sure you don’t expose account sensitive data.

Replace “collection_name” with your actual collection name.

<?php

// This will append "author" object into API response. 

if (COCKPIT_API_REQUEST) {

    $app->on('collections.find.after.collection_name', function($name, &$entries) {


        function getSomeFields($array){
            $author_name = !empty($array['name'])?$array['name']:$array['user'];

            // Only return 2 fields "name" and "_id"
            return [
            "name" => $author_name,
            "_id"  => $array['_id']
           ];
        }

        foreach ($entries as &$entry) {

                $account         = $this->storage->findOne('cockpit/accounts', ['_id' => $entry['_by']]);
                $account         = !empty($account)?getSomeFields($account):[];

                // You can rename "author" as you want                
                $entry['author'] = $account;

        }

    });

}
2 Likes

This I really thought about doing, but I thought it could be less performant, even more so with a relevant amount of data to consult…

My friend, this is awesome, it worked perfectly for me, and it opened my mind to do other things, it may be my fault, but is there anything in the documentation talking about creating this “bootstrap.php” file? I didn’t think… Anyway, thank you very much, it worked perfectly!

I don’t think the official docs have the detail about building addons and doing some logic on hook events.
I can share you how I understand it.

Disclaimer - the below information is based on my experience, so I could be wrong

config/bootstrap.php is like an init file. But it’s used for general purpose and you can add your common codes inside it.

For a specific type of init file, you can create your own addon under addons directory.
So, it would be something like this - addons/{your_addon_name}/bootstrap.php


Let me explain how a very simple addon works.

if (COCKPIT_API_REQUEST) {
    $app->on('cockpit.rest.init', function ($routes) use ($app) {
        $routes['test'] = function () use ($app) {
             $my_variable = $this->param('my_variable'); 
        }
     } 
}

API Authentication

COCKPIT_API_REQUEST is API authentication / middleware

if(COCKPIT_API_REQUEST){
    // The requests must includes token to access this 
}

Event

cockpit.reset.init is like your codes will execute when Cockpit CMS init.
This is very similar to Jquery or JS events.

 $app->on('cockpit.rest.init', function ($routes) use ($app) {
         // do your logic here
     } 

So, you might say how do I know those events?
Here is the list of Cockpit events.


Routes

To declare routes, you can write as below.

if (COCKPIT_API_REQUEST) {
    $app->on('cockpit.rest.init', function ($routes) use ($app) {
        $routes['test'] = function () use ($app) {
             // access api route at "api/test" and do your logic here 
       }
    })
}

This is an example test route, so you can access your route like /api/test


Request Parameters

You can simply grab the request parameter like $this->param("my_variable")

e.g

     $my_variable = $this->param('my_variable'); 

Lime framework

Cockpit was built on top of Lime micro php framework https://github.com/agentejo/lime
So, most of it basic functions would be the same as lime.

You can also learn from this scripts list by @raffaelj

Hope this also help someone.

3 Likes

That was very enlightening, I’ll save it all here!
It will definitely be of great help, thank you very much!

1 Like