Get all linked objects with 1 API call

Collapse
X
 
  • Time
  • Show
Clear All
new posts

  • bandtank
    replied
    Thanks. That worked perfectly.

    Leave a comment:


  • tanya
    replied
    You could also override the method toArray in custom/Espo/Custom/Entities/TimesheetData.php

    application/Espo/ORM/Entity.php - base path

    Leave a comment:


  • bandtank
    replied
    So far, this is the best I've been able to accomplish:

    PHP Code:
    
      1 <?php
      2
      3 namespace Espo\Custom\Controllers;
      4
      5 use Espo\Core\Exceptions\BadRequest;
      6
      7 class Timesheet extends \Espo\Core\Templates\Controllers\BasePlus
      8 {
      9   public function getActionData($params, $data, $request) {
     10     $assignedUserId = $request->get('assignedUserId');
     11     $timesheetId    = $request->get('timesheetId');
     12     if(!$assignedUserId || !$timesheetId) {
     13       throw new BadRequest();
     14     }
     15
     16     $timesheetData = $this->getEntityManager()->getRepository('TimesheetData')
     17       ->where(array(
     18         'timesheetId' => $timesheetId
     19       ))->order('order',false)->find();
     20
     21     $projectIds = array();
     22     foreach($timesheetData->toArray() as $td) {
     23       $projectIds[$td['projectId']] = 1;
     24     }
     25
     26     $projects = array();
     27     foreach(array_keys($projectIds) as $projectId) {
     28       $temp = $this->getEntityManager()->getRepository('Project')
     29         ->where(array(
     30           'id' => $projectId
     31         ))->findOne();
     32       array_push($projects,$temp->toArray());
     33     }
     34
     35
     36     return json_encode(
     37       array(
     38         'timesheetData' => $timesheetData->toArray(),
     39         'projects'      => $projects
     40       )
     41     );
     42   }
     43 }
    which returns something like this:

    Code:
    {
        "timesheetDatas": [
            {
                "id": "59f6a7bdbd420aad7",
                "name": "data",
                "deleted": false,
               ...
                "projectId": "5a05a8d950803350d",
                "projectName": "17-0001-D1"
            },
            ...
        ],
        "projects": [
            {
                "id": "5a05a8d950803350d",
                "name": "17-0001-D1",
               ...
            },
            ...
        ]
    }
    It's not quite the same, but it will work if there's no other way.

    Leave a comment:


  • bandtank
    replied
    Ok, so the solution above worked in terms of setting up the controller method, route, etc. I posted my solution there. However, I can't figure out how to get the repository to select my TimesheetData objects with the related Project objects. This is what I have so far:

    PHP Code:
    
    18     $data = $this->getEntityManager()->getRepository('TimesheetData')
    19       ->where(array(
    20         'timesheetId' => $timesheetId
    21       ))->order('order',false)->find();
            ...
    25     return json_encode(array('total' => $data->count(), 'data' => $data->toArray())); 
    
    The result is this:

    Code:
    {
        "total": 8,
        "data": [
            {
                "id": "59f6a7bdbd420aad7",
                "name": "data",
                "deleted": false,
                ...
                "projectId": "59ed70ee523556f77",
                "projectName": "00-0000-Z1"
            },
            {
                "id": "59f6a7bdb1568fc33",
                "name": "data",
                "deleted": false,
                ...
                "projectId": "59ed76c96e05dd548",
                "projectName": "00-0000-Z3"
            },
            {
                 ...
            }
        ]
    }
    How do I get it to include the actual project object? I'm trying to get something like this:

    Code:
    {
        "total": 8,
        "data": [
            {
                "id": "59f6a7bdbd420aad7",
                "name": "data",
                "deleted": false,
                ...
                "project":{
                    "projectId": "59ed70ee523556f77",
                    "projectName": "00-0000-Z1"
                    ...
                }
    
            },
            {
                "id": "59f6a7bdb1568fc33",
                "name": "data",
                "deleted": false,
                ...
                "project":{
                    "id: "59ed76c96e05dd548",
                    "projectName": "00-0000-Z3"
                    ...
                }
            },
            {
                 ...
            }
        ]
    }
    I've seen this called 'with(...)' in other frameworks. I know of the findRelated function, which works on single objects in a collection:

    PHP Code:
    $related = $this->getEntityManager()->getRepository('TimesheetData')->findRelated($data->current(),'project'); 
    
    but that still requires a loop to query for each Project in each TimesheetData object.

    Leave a comment:


  • bandtank
    replied
    Does the solution in the following post accomplish my goal? It seems like it does, but he didn't say to add a route. Is the getActionxxxxx parsed automatically by the base controller?

    Hi ! I am new to EspoCRM and I find it very cool with a very high potential with good structure and good technologies used. But I have many questions to be

    Leave a comment:


  • tanya
    replied
    Hello
    No, but you can create own action. Add it to controller and define the route

    Leave a comment:


  • bandtank
    started a topic Get all linked objects with 1 API call

    Get all linked objects with 1 API call

    I have the following linked entities:

    Code:
    Timesheet
    TimesheetData (many-to-one relationship with Timesheet)
    Project (one-to-many relationship with TimesheetData)
    For example, this is what you might see in the database:

    Code:
    Timesheet0
      TimesheetData0 Project0
      TimesheetData1 Project4
      TimesheetData2 Project5
    Timesheet1
      TimesheetData3 Project10
      TimesheetData4 Project5
      TimesheetData5 Project0
    To get all of the data, I'm currently doing this:

    Code:
    // Get list of timesheets
    GET /timesheet
    
    //Get the timesheetData objects that are linked to a timesheet object
    GET /timesheet/{id}/timesheetData
    
    // Get the project object that is linked to a timesheetData object
    GET /timesheetData/{id}/project
    I have to parse many, many calls to the server because the objects are queried like this:
    Code:
    timesheets = get Timesheet objects from API (GET /timesheet)
    for each timesheet
      timesheetDatas = get TimesheetData objects from API (GET /timesheet/{id}/timesheetdata)
      foreach timesheetData
        project = get Project objects from API (GET /timesheetData/{id}/project)

    However, it would be a lot less load on my server if I could get all of that data at once. It would also be a big improvement if I could get the project object associated with each timesheetData object while also getting the timesheetData object. It would drastically reduce the number of calls. I can't figure out how to do any of that, though.

    Ideally, I would be able to do this:

    Code:
    GET timesheet with all timesheet/id/timesheetData and timesheet/id/timesheetData/id/project objects
    I see this in application/Espo/Resources/routes.json:

    PHP Code:
    
    311   {
    312     "route":"/:controller/:id/:link",
    313     "method":"get",
    314     "params":{
    315         "controller":":controller",
    316         "action":"listLinked",
    317         "id":":id",
    318         "link":":link"
    319     }
    320   } 
    

    It looks like 'listLinked' is the action that queries linked objects. Is there a way to use that action to query the parent object AND all of the child objects at the same time?
Working...