Order records by translation table in cakephp 4.4

I am using TranslateBehavior in Acl Acos table with ShadowStrategy, and have a MenuGroups table that has a belongsToMany association with Acos to show the site menu dynamically, and I want to show the Acos records ordered by AcosTranslations.alias, is there a way to do that?

If you can’t figure out how to do this directly with a query, you could sort the result set after retrieving them using your own sorting code.

You could use any of the tools in the Collection library possibly sortBy().

The query system even integrates the Collection::map() and Collection::reduce() methods directly for post-processing query results. You might be able to work out a sort routine using that feature. Or you can use map() or reduce() manually on your result.

There is alway the built-in PHP SplHeap classes you can sort with. There is some example code there that should help.

I don’t know how to order the records with sortBy method, I need to sort by two fields (MenuGroups.name and Acos._translations.es.alias) but is not ordering the records with that combination, I saw that I can use a function but I don’t know how to put the objects to do the ordering.
This is the code to create the collection and try to order it:

$collection = new Collection($menuGroups);
$list = $collection->toList();
$sorted = $collection->sortBy('Acos._translations.es.alias');

And this is what it shows debug($list):

APP/Controller\AppController.php (line 143)
[
  (int) 0 => object(App\Model\Entity\MenuGroup) id:0 {
    'id' => (int) 1
    'name' => 'Administración'
    'created' => object(Cake\I18n\FrozenTime) id:1 {
      'time' => '2023-10-10 16:24:06.000000-03:00'
      'timezone' => 'America/Argentina/Cordoba'
      'fixedNowTime' => false
    }
    'modified' => object(Cake\I18n\FrozenTime) id:2 {
      'time' => '2023-10-10 16:24:06.000000-03:00'
      'timezone' => 'America/Argentina/Cordoba'
      'fixedNowTime' => false
    }
    'acos' => [
      (int) 0 => object(Acl\Model\Entity\Aco) id:3 {
        'id' => (int) 2
        'parent_id' => (int) 1
        'model' => null
        'foreign_key' => null
        'alias' => 'AcosMenuGroups'
        'lft' => (int) 2
        'rght' => (int) 13
        '_joinData' => object(App\Model\Entity\AcosMenuGroup) id:4 {
          'id' => (int) 1
          'menu_group_id' => (int) 1
          'aco_id' => (int) 2
          'created' => object(Cake\I18n\FrozenTime) id:5 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          'modified' => object(Cake\I18n\FrozenTime) id:6 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          '[new]' => false
          '[accessible]' => [
            'menu_group_id' => true,
            'aco_id' => true,
            'created' => true,
            'modified' => true,
            'menu_group' => true,
            'aco' => true,
          ]
          '[dirty]' => [
          ]
          '[original]' => [
          ]
          '[virtual]' => [
          ]
          '[hasErrors]' => false
          '[errors]' => [
          ]
          '[invalid]' => [
          ]
          '[repository]' => 'AcosMenuGroups'
        }
        '_translations' => [
          'es' => object(Cake\ORM\Entity) id:7 {
            'locale' => 'es'
            'parent_id' => (int) 1
            'model' => ''
            'foreign_key' => null
            'alias' => 'Permisos de los Grupos de Menú'
            'lft' => (int) 2
            'rght' => (int) 13
            '[new]' => false
            '[accessible]' => [
              '*' => true,
            ]
            '[dirty]' => [
            ]
            '[original]' => [
            ]
            '[virtual]' => [
            ]
            '[hasErrors]' => false
            '[errors]' => [
            ]
            '[invalid]' => [
            ]
            '[repository]' => 'Acl.AcosTranslations'
          },
        ]
        '[new]' => false
        '[accessible]' => [
          '*' => true,
        ]
        '[dirty]' => [
        ]
        '[original]' => [
        ]
        '[virtual]' => [
        ]
        '[hasErrors]' => false
        '[errors]' => [
        ]
        '[invalid]' => [
        ]
        '[repository]' => 'Acl.Acos'
      },
      (int) 1 => object(Acl\Model\Entity\Aco) id:8 {
        'id' => (int) 13
        'parent_id' => (int) 1
        'model' => null
        'foreign_key' => null
        'alias' => 'MenuGroups'
        'lft' => (int) 24
        'rght' => (int) 35
        '_joinData' => object(App\Model\Entity\AcosMenuGroup) id:9 {
          'id' => (int) 2
          'menu_group_id' => (int) 1
          'aco_id' => (int) 13
          'created' => object(Cake\I18n\FrozenTime) id:10 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          'modified' => object(Cake\I18n\FrozenTime) id:11 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          '[new]' => false
          '[accessible]' => [
            'menu_group_id' => true,
            'aco_id' => true,
            'created' => true,
            'modified' => true,
            'menu_group' => true,
            'aco' => true,
          ]
          '[dirty]' => [
          ]
          '[original]' => [
          ]
          '[virtual]' => [
          ]
          '[hasErrors]' => false
          '[errors]' => [
          ]
          '[invalid]' => [
          ]
          '[repository]' => 'AcosMenuGroups'
        }
        '_translations' => [
          'es' => object(Cake\ORM\Entity) id:12 {
            'locale' => 'es'
            'parent_id' => (int) 1
            'model' => ''
            'foreign_key' => null
            'alias' => 'Grupos de Menú'
            'lft' => (int) 24
            'rght' => (int) 35
            '[new]' => false
            '[accessible]' => [
              '*' => true,
            ]
            '[dirty]' => [
            ]
            '[original]' => [
            ]
            '[virtual]' => [
            ]
            '[hasErrors]' => false
            '[errors]' => [
            ]
            '[invalid]' => [
            ]
            '[repository]' => 'Acl.AcosTranslations'
          },
        ]
        '[new]' => false
        '[accessible]' => [
          '*' => true,
        ]
        '[dirty]' => [
        ]
        '[original]' => [
        ]
        '[virtual]' => [
        ]
        '[hasErrors]' => false
        '[errors]' => [
        ]
        '[invalid]' => [
        ]
        '[repository]' => 'Acl.Acos'
      },
      (int) 2 => object(Acl\Model\Entity\Aco) id:13 {
        'id' => (int) 19
        'parent_id' => (int) 1
        'model' => null
        'foreign_key' => null
        'alias' => 'MyPermissions'
        'lft' => (int) 36
        'rght' => (int) 49
        '_joinData' => object(App\Model\Entity\AcosMenuGroup) id:14 {
          'id' => (int) 3
          'menu_group_id' => (int) 1
          'aco_id' => (int) 19
          'created' => object(Cake\I18n\FrozenTime) id:15 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          'modified' => object(Cake\I18n\FrozenTime) id:16 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          '[new]' => false
          '[accessible]' => [
            'menu_group_id' => true,
            'aco_id' => true,
            'created' => true,
            'modified' => true,
            'menu_group' => true,
            'aco' => true,
          ]
          '[dirty]' => [
          ]
          '[original]' => [
          ]
          '[virtual]' => [
          ]
          '[hasErrors]' => false
          '[errors]' => [
          ]
          '[invalid]' => [
          ]
          '[repository]' => 'AcosMenuGroups'
        }
        '_translations' => [
          'es' => object(Cake\ORM\Entity) id:17 {
            'locale' => 'es'
            'parent_id' => (int) 1
            'model' => ''
            'foreign_key' => null
            'alias' => 'Permisos'
            'lft' => (int) 36
            'rght' => (int) 49
            '[new]' => false
            '[accessible]' => [
              '*' => true,
            ]
            '[dirty]' => [
            ]
            '[original]' => [
            ]
            '[virtual]' => [
            ]
            '[hasErrors]' => false
            '[errors]' => [
            ]
            '[invalid]' => [
            ]
            '[repository]' => 'Acl.AcosTranslations'
          },
        ]
        '[new]' => false
        '[accessible]' => [
          '*' => true,
        ]
        '[dirty]' => [
        ]
        '[original]' => [
        ]
        '[virtual]' => [
        ]
        '[hasErrors]' => false
        '[errors]' => [
        ]
        '[invalid]' => [
        ]
        '[repository]' => 'Acl.Acos'
      },
      (int) 3 => object(Acl\Model\Entity\Aco) id:18 {
        'id' => (int) 26
        'parent_id' => (int) 1
        'model' => null
        'foreign_key' => null
        'alias' => 'Pacients'
        'lft' => (int) 50
        'rght' => (int) 65
        '_joinData' => object(App\Model\Entity\AcosMenuGroup) id:19 {
          'id' => (int) 4
          'menu_group_id' => (int) 1
          'aco_id' => (int) 26
          'created' => object(Cake\I18n\FrozenTime) id:20 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          'modified' => object(Cake\I18n\FrozenTime) id:21 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          '[new]' => false
          '[accessible]' => [
            'menu_group_id' => true,
            'aco_id' => true,
            'created' => true,
            'modified' => true,
            'menu_group' => true,
            'aco' => true,
          ]
          '[dirty]' => [
          ]
          '[original]' => [
          ]
          '[virtual]' => [
          ]
          '[hasErrors]' => false
          '[errors]' => [
          ]
          '[invalid]' => [
          ]
          '[repository]' => 'AcosMenuGroups'
        }
        '_translations' => [
          'es' => object(Cake\ORM\Entity) id:22 {
            'locale' => 'es'
            'parent_id' => (int) 1
            'model' => ''
            'foreign_key' => null
            'alias' => 'Pacientes'
            'lft' => (int) 50
            'rght' => (int) 65
            '[new]' => false
            '[accessible]' => [
              '*' => true,
            ]
            '[dirty]' => [
            ]
            '[original]' => [
            ]
            '[virtual]' => [
            ]
            '[hasErrors]' => false
            '[errors]' => [
            ]
            '[invalid]' => [
            ]
            '[repository]' => 'Acl.AcosTranslations'
          },
        ]
        '[new]' => false
        '[accessible]' => [
          '*' => true,
        ]
        '[dirty]' => [
        ]
        '[original]' => [
        ]
        '[virtual]' => [
        ]
        '[hasErrors]' => false
        '[errors]' => [
        ]
        '[invalid]' => [
        ]
        '[repository]' => 'Acl.Acos'
      },
      (int) 4 => object(Acl\Model\Entity\Aco) id:23 {
        'id' => (int) 34
        'parent_id' => (int) 1
        'model' => null
        'foreign_key' => null
        'alias' => 'Professionals'
        'lft' => (int) 66
        'rght' => (int) 83
        '_joinData' => object(App\Model\Entity\AcosMenuGroup) id:24 {
          'id' => (int) 5
          'menu_group_id' => (int) 1
          'aco_id' => (int) 34
          'created' => object(Cake\I18n\FrozenTime) id:25 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          'modified' => object(Cake\I18n\FrozenTime) id:26 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          '[new]' => false
          '[accessible]' => [
            'menu_group_id' => true,
            'aco_id' => true,
            'created' => true,
            'modified' => true,
            'menu_group' => true,
            'aco' => true,
          ]
          '[dirty]' => [
          ]
          '[original]' => [
          ]
          '[virtual]' => [
          ]
          '[hasErrors]' => false
          '[errors]' => [
          ]
          '[invalid]' => [
          ]
          '[repository]' => 'AcosMenuGroups'
        }
        '_translations' => [
          'es' => object(Cake\ORM\Entity) id:27 {
            'locale' => 'es'
            'parent_id' => (int) 1
            'model' => ''
            'foreign_key' => null
            'alias' => 'Profesionales'
            'lft' => (int) 66
            'rght' => (int) 83
            '[new]' => false
            '[accessible]' => [
              '*' => true,
            ]
            '[dirty]' => [
            ]
            '[original]' => [
            ]
            '[virtual]' => [
            ]
            '[hasErrors]' => false
            '[errors]' => [
            ]
            '[invalid]' => [
            ]
            '[repository]' => 'Acl.AcosTranslations'
          },
        ]
        '[new]' => false
        '[accessible]' => [
          '*' => true,
        ]
        '[dirty]' => [
        ]
        '[original]' => [
        ]
        '[virtual]' => [
        ]
        '[hasErrors]' => false
        '[errors]' => [
        ]
        '[invalid]' => [
        ]
        '[repository]' => 'Acl.Acos'
      },
      (int) 5 => object(Acl\Model\Entity\Aco) id:28 {
        'id' => (int) 43
        'parent_id' => (int) 1
        'model' => null
        'foreign_key' => null
        'alias' => 'Professions'
        'lft' => (int) 84
        'rght' => (int) 95
        '_joinData' => object(App\Model\Entity\AcosMenuGroup) id:29 {
          'id' => (int) 6
          'menu_group_id' => (int) 1
          'aco_id' => (int) 43
          'created' => object(Cake\I18n\FrozenTime) id:30 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          'modified' => object(Cake\I18n\FrozenTime) id:31 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          '[new]' => false
          '[accessible]' => [
            'menu_group_id' => true,
            'aco_id' => true,
            'created' => true,
            'modified' => true,
            'menu_group' => true,
            'aco' => true,
          ]
          '[dirty]' => [
          ]
          '[original]' => [
          ]
          '[virtual]' => [
          ]
          '[hasErrors]' => false
          '[errors]' => [
          ]
          '[invalid]' => [
          ]
          '[repository]' => 'AcosMenuGroups'
        }
        '_translations' => [
          'es' => object(Cake\ORM\Entity) id:32 {
            'locale' => 'es'
            'parent_id' => (int) 1
            'model' => ''
            'foreign_key' => null
            'alias' => 'Profesiones'
            'lft' => (int) 84
            'rght' => (int) 95
            '[new]' => false
            '[accessible]' => [
              '*' => true,
            ]
            '[dirty]' => [
            ]
            '[original]' => [
            ]
            '[virtual]' => [
            ]
            '[hasErrors]' => false
            '[errors]' => [
            ]
            '[invalid]' => [
            ]
            '[repository]' => 'Acl.AcosTranslations'
          },
        ]
        '[new]' => false
        '[accessible]' => [
          '*' => true,
        ]
        '[dirty]' => [
        ]
        '[original]' => [
        ]
        '[virtual]' => [
        ]
        '[hasErrors]' => false
        '[errors]' => [
        ]
        '[invalid]' => [
        ]
        '[repository]' => 'Acl.Acos'
      },
      (int) 6 => object(Acl\Model\Entity\Aco) id:33 {
        'id' => (int) 49
        'parent_id' => (int) 1
        'model' => null
        'foreign_key' => null
        'alias' => 'Profiles'
        'lft' => (int) 96
        'rght' => (int) 107
        '_joinData' => object(App\Model\Entity\AcosMenuGroup) id:34 {
          'id' => (int) 7
          'menu_group_id' => (int) 1
          'aco_id' => (int) 49
          'created' => object(Cake\I18n\FrozenTime) id:35 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          'modified' => object(Cake\I18n\FrozenTime) id:36 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          '[new]' => false
          '[accessible]' => [
            'menu_group_id' => true,
            'aco_id' => true,
            'created' => true,
            'modified' => true,
            'menu_group' => true,
            'aco' => true,
          ]
          '[dirty]' => [
          ]
          '[original]' => [
          ]
          '[virtual]' => [
          ]
          '[hasErrors]' => false
          '[errors]' => [
          ]
          '[invalid]' => [
          ]
          '[repository]' => 'AcosMenuGroups'
        }
        '_translations' => [
          'es' => object(Cake\ORM\Entity) id:37 {
            'locale' => 'es'
            'parent_id' => (int) 1
            'model' => ''
            'foreign_key' => null
            'alias' => 'Perfiles'
            'lft' => (int) 96
            'rght' => (int) 107
            '[new]' => false
            '[accessible]' => [
              '*' => true,
            ]
            '[dirty]' => [
            ]
            '[original]' => [
            ]
            '[virtual]' => [
            ]
            '[hasErrors]' => false
            '[errors]' => [
            ]
            '[invalid]' => [
            ]
            '[repository]' => 'Acl.AcosTranslations'
          },
        ]
        '[new]' => false
        '[accessible]' => [
          '*' => true,
        ]
        '[dirty]' => [
        ]
        '[original]' => [
        ]
        '[virtual]' => [
        ]
        '[hasErrors]' => false
        '[errors]' => [
        ]
        '[invalid]' => [
        ]
        '[repository]' => 'Acl.Acos'
      },
      (int) 7 => object(Acl\Model\Entity\Aco) id:38 {
        'id' => (int) 57
        'parent_id' => (int) 1
        'model' => null
        'foreign_key' => null
        'alias' => 'Teams'
        'lft' => (int) 112
        'rght' => (int) 127
        '_joinData' => object(App\Model\Entity\AcosMenuGroup) id:39 {
          'id' => (int) 8
          'menu_group_id' => (int) 1
          'aco_id' => (int) 57
          'created' => object(Cake\I18n\FrozenTime) id:40 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          'modified' => object(Cake\I18n\FrozenTime) id:41 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          '[new]' => false
          '[accessible]' => [
            'menu_group_id' => true,
            'aco_id' => true,
            'created' => true,
            'modified' => true,
            'menu_group' => true,
            'aco' => true,
          ]
          '[dirty]' => [
          ]
          '[original]' => [
          ]
          '[virtual]' => [
          ]
          '[hasErrors]' => false
          '[errors]' => [
          ]
          '[invalid]' => [
          ]
          '[repository]' => 'AcosMenuGroups'
        }
        '_translations' => [
          'es' => object(Cake\ORM\Entity) id:42 {
            'locale' => 'es'
            'parent_id' => (int) 1
            'model' => ''
            'foreign_key' => null
            'alias' => 'Equipos'
            'lft' => (int) 112
            'rght' => (int) 127
            '[new]' => false
            '[accessible]' => [
              '*' => true,
            ]
            '[dirty]' => [
            ]
            '[original]' => [
            ]
            '[virtual]' => [
            ]
            '[hasErrors]' => false
            '[errors]' => [
            ]
            '[invalid]' => [
            ]
            '[repository]' => 'Acl.AcosTranslations'
          },
        ]
        '[new]' => false
        '[accessible]' => [
          '*' => true,
        ]
        '[dirty]' => [
        ]
        '[original]' => [
        ]
        '[virtual]' => [
        ]
        '[hasErrors]' => false
        '[errors]' => [
        ]
        '[invalid]' => [
        ]
        '[repository]' => 'Acl.Acos'
      },
      (int) 8 => object(Acl\Model\Entity\Aco) id:43 {
        'id' => (int) 65
        'parent_id' => (int) 1
        'model' => null
        'foreign_key' => null
        'alias' => 'Users'
        'lft' => (int) 128
        'rght' => (int) 151
        '_joinData' => object(App\Model\Entity\AcosMenuGroup) id:44 {
          'id' => (int) 9
          'menu_group_id' => (int) 1
          'aco_id' => (int) 65
          'created' => object(Cake\I18n\FrozenTime) id:45 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          'modified' => object(Cake\I18n\FrozenTime) id:46 {
            'time' => '2023-10-10 16:24:06.000000-03:00'
            'timezone' => 'America/Argentina/Cordoba'
            'fixedNowTime' => false
          }
          '[new]' => false
          '[accessible]' => [
            'menu_group_id' => true,
            'aco_id' => true,
            'created' => true,
            'modified' => true,
            'menu_group' => true,
            'aco' => true,
          ]
          '[dirty]' => [
          ]
          '[original]' => [
          ]
          '[virtual]' => [
          ]
          '[hasErrors]' => false
          '[errors]' => [
          ]
          '[invalid]' => [
          ]
          '[repository]' => 'AcosMenuGroups'
        }
        '_translations' => [
          'es' => object(Cake\ORM\Entity) id:47 {
            'locale' => 'es'
            'parent_id' => (int) 1
            'model' => ''
            'foreign_key' => null
            'alias' => 'Usuarios'
            'lft' => (int) 128
            'rght' => (int) 151
            '[new]' => false
            '[accessible]' => [
              '*' => true,
            ]
            '[dirty]' => [
            ]
            '[original]' => [
            ]
            '[virtual]' => [
            ]
            '[hasErrors]' => false
            '[errors]' => [
            ]
            '[invalid]' => [
            ]
            '[repository]' => 'Acl.AcosTranslations'
          },
        ]
        '[new]' => false
        '[accessible]' => [
          '*' => true,
        ]
        '[dirty]' => [
        ]
        '[original]' => [
        ]
        '[virtual]' => [
        ]
        '[hasErrors]' => false
        '[errors]' => [
        ]
        '[invalid]' => [
        ]
        '[repository]' => 'Acl.Acos'
      },
    ]
    '[new]' => false
    '[accessible]' => [
      'name' => true,
      'created' => true,
      'modified' => true,
      'acos' => true,
    ]
    '[dirty]' => [
    ]
    '[original]' => [
    ]
    '[virtual]' => [
    ]
    '[hasErrors]' => false
    '[errors]' => [
    ]
    '[invalid]' => [
    ]
    '[repository]' => 'MenuGroups'
  },
]

To sort by menu group name and then the translation, I think you want something like

$sorted = $collection->sortBy(fn(MenuGroup $group) =>
    $group->name . '-' . $group->acos[0]->_translactions['es']->alias, SORT_ASC, SORT_STRING);

First a request:

Tighten up your queries so you are only selecting relevant columns. It takes a ton of work to weed through these giant data dumps.

Now the (first tier) problems:

  1. You’ve made a Collection from an array of one element so there can be no sorting or any other iterating activity. This is the general content of your $menuGroups:

Screen Shot 2023-10-31 at 1.23.04 PM

  1. toList() is one of the ‘trigger’ function for Collections. It is used at the end of your set-up to ‘do’ the processes you have requested and get the result. toArray() is a similar trigger.

So if you really had a collection with more than 1 member, you would do something like this:

$callback = function ($a) {
    return $a->property->deepProperty;
}
$collection = new Collection($lotOfStuff);

$sorted = $collection->sortBy($callback)->toList();

I would recommend doing some simpler code to gain an understanding of the way collection sorting works. Among the questions that need to be answered, “can you use dot notation with an object or would you have to write a callback as shown in the documentation?”

Simplified test code will help you back into a solution bit by bit. Starting with an super-deep object like your query result and dumping it into an unfamiliar system is guaranteed to fail (in my experience).

Thank you @Zuluru, I tried with your suggestion but it didn’t order the resultset, is there a way to pass all the array of acos or how does it work the sortBy method?

Oh, you’re trying to sort the acos entries? Despite calling sortBy on a collection, as @dreamingmind pointed out, of menu groups? There is much here that’s not clear. Do you want the sorted list to be in a new variable, or do you want the acos property updated? Does this need to work when you have multiple menu groups in the result set, each of which has some acos entries? Is there some reason (apart from “I tried that and couldn’t get it to work”) that you’re not doing this sorting in the query?

You can pass any iterable to the collection.

$collection = new Collection($menuGroups->acos);

//should get you something to work with given your current query result
//then maybe:

$callable = function($aco) {
    return $aco->_translations['es']->alias;
}

$sorted = $collection->sortBy($callable)->toArray();

I don’t know if that is actually right because your query has so much noise, I’m having a hard time making sense of it.

if it does works it will probably still be a sorted list of Acts records with all the extra stuff muddying up the waters.

$collection = new Collection($menuGroups->acos);

$callable = function($aco) {
    return $aco->_translations['es']->alias;
}

$aliases = $collection->map($callable)->toArray();

//might extract the values of interest. Or get you close enough you could 
//figure out how to get the values you want. Then you could simply:

sort($aliases); //god 'ol php sort function

But this is still a fair question.

Since we started here:

I want to sort the collection by MenuGroups.name and AcosTranslations.alias, in the first example I sent I only have one MenuGroup because I am testing the site, but there will be more MenuGroups that will be developed by a coworker.
This is the code to retrieve the MenuGroups with it’s Acos ordered by AcosTranslations.alias:

$menuGroups = $this->MenuGroups->find('all')->contain(['Acos' => function(Query $q) use ($controllers) {
	return $q->find('translations')->where(['Acos.alias in' => $controllers])->order('AcosTranslations.alias'); 
}])->all();

But this is giving me this exception:


How can I make the query to order the records by AcosTranslatios.alias and not Acos.alias?

Well, AcosTranslations isn’t in that query at all, so not surprising that it can’t sort on it. Hopefully someone who knows a little more about how translations are loaded in these scenarios can suggest something. Otherwise, we’ll be back to sorting after the query.

Is this based on the query that pulled that first result set you posted?

That earlier query successfully returned the fields you wanted. It would be a logical place to start and work out how sorting might be added to the query object.

Personally, I would live with the big, unsorted query result that you first posted, then do the sorting in two stages.

First I’d walk through the $menuGroups and sort the acos array based on their translations['es']->alias value.

Second I’d sort the set of $menuGroups' on their name` property.

While it may not be as efficient to do this in two stages, I’ve learned that I’m terrible at remembering how my dense, clever, and efficient solutions work after a couple of months (or weeks) go by. I’m better off breaking things into simple stages.

And often, after writing these simple steps, I realize some equally simple way to pull everything together into more streamlined code.

In fact, first I’d extract only the data I wanted from the query so I had a nice, easy to read array that could be used by my page rendering code. That’s what I would sort, not the big, messy query result.

And how can I do the ordering in two stages? I tried doing this:

$menuGroups = $this->MenuGroups->find('all')->order('name');
I18n::setLocale('es');
$profile = $this->Profiles->get($profile_id);
$permissions = [];
$i = 0;
foreach($menuGroups as $menuGroup){
	$acosMenuGroups = $this->MenuGroups->AcosMenuGroups->find('all')->contain(['Acos' => function($q) use ($controllers){
		return $q->where(['Acos.alias in' => $controllers]); 
	}])->where(['AcosMenuGroups.menu_group_id' => $menuGroup->id])->order('Acos.alias')->toList();
	$acosArray = [];
	foreach($acosMenuGroups[$i]->aco as $acoM){
		$checkI1 = $this->Acl->check($profile, $acoM->alias.'/index');
		$checkI2 = $this->Acl->check($profile, $acoM->alias.'/index', 'create');
		$checkI3 = $this->Acl->check($profile, $acoM->alias.'/index', 'read');
		$checkI4 = $this->Acl->check($profile, $acoM->alias.'/index', 'update');
		$checkI5 = $this->Acl->check($profile, $acoM->alias.'/index', 'delete');
		if(!empty($checkI1) || !empty($checkI2) || !empty($checkI3) || !empty($checkI4) || !empty($checkI5)){
			$text = $acoM->alias;
			array_push($acosArray, ['text' => $text, 'controller' => $acoM->alias]);
		}
	}
	$j = count($acosArray);
	if(!empty($j)) array_push($permissions, ['group' => $menuGroup->name, 'acos' => $acosArray]);
	$i++;
}

But gives me this exception:


That exception occurs in another part of the code, but I found out that is querying the AcosTranslations for the alias in controllers in english and of course doesn’t find anything and doesn’t show me the menu in the site, how can I solve this issue?

I’ve never used the translation features and don’t know anything about the All->check() method.

The Acl->check is to check the permission for the aro in the aco and action passed as parameter for the method, the first parameter is the aro, the second parameter is the aco and the third parameter is the action (create, read, update, delete)

How can I do that with the translations?

Is this correct or do I have to do it in another way?
I’m not finding the correct way to do it because it always gives me an exception or doesn’t retrieve the records.

I don’t know what’s wrong with that query. but didn’t you have a working query on Oct 31?

Yes, but that query is not sorted, I don’t know how to sort it.

This is an example that creates a simple, sorted array from that original result.

It has the virtue of using simple, native php.

See comments in the code for how and why I translated that result.

Save this code as templates/Pages/sample.php then you can view the results at yourlocalserver/pages/sample.php

<?php

echo '<h1>Raw Data</h1>';
debug(getMenuGroups());

echo '<h1>Sorted Data</h1>';
debug(sortData());

echo '<h1>Sorted Data Keyed By Id</h1>';
debug(keyedById());

/**
 * Here I reduce the data to an array that might be sent to
 * a template for output. You can send sorted data that contains
 * all the entities if you want, but that will make your
 * output code more complicated and harder to maintain (IMHO)
 *
 * Working from your result-set with entities, you'll have
 * to change the lines that extract values so they can
 * work with your objects rather than this example array
 */
function sortData()
{
    $simpleArray = [];

    foreach (getMenuGroups() as $menuGroup) {
        $groupName = $menuGroup['name']; //fix this value reference
        $simpleArray[$groupName] = [];

        foreach ($menuGroup['acos'] as $aco) {
            $simpleArray[$groupName][] = $aco['_translations']['es']['alias']; //fix this value reference
        }

        sort($simpleArray[$groupName]);
    }

    ksort($simpleArray);

    return $simpleArray;
}

function keyedById()
{
    $simpleArray = [];

    foreach (getMenuGroups() as $menuGroup) {
        $groupName = $menuGroup['name']; //fix this value reference
        $simpleArray[$groupName] = [];

        foreach ($menuGroup['acos'] as $aco) {
            $translation = $aco['_translations']['es']['alias']; //fix this value reference
            $id = $aco['id']; //fix this value reference
            $simpleArray[$groupName][$translation] = $id;
        }

        ksort($simpleArray[$groupName]);
        $simpleArray[$groupName] = array_flip($simpleArray[$groupName]);
    }

    ksort($simpleArray);

    return $simpleArray;
}

/**
 * I don't have all your entity classes, so I simplified this
 * data down to an array and I dumped most of the fields that
 * had nothing to do with sorting or linking
 */
function getMenuGroups(): array
{
    return [
        0 => [
            'id' => 1,
            'name' => 'Administración',
            'acos' => [
                0 => [
                    'id' => 2,
                    'alias' => 'AcosMenuGroups',
                    '_joinData' => [
                        'id' => 1,
                        'menu_group_id' => 1,
                        'aco_id' => 2,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Permisos de los Grupos de Menú',
                        ],
                    ],
                ],
                1 => [
                    'id' => 13,
                    'alias' => 'MenuGroups',
                    '_joinData' => [
                        'id' => 2,
                        'menu_group_id' => 1,
                        'aco_id' => 13,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Grupos de Menú',
                        ],
                    ],
                ],
                2 => [
                    'id' => 19,
                    'alias' => 'MyPermissions',
                    '_joinData' => [
                        'id' => 3,
                        'menu_group_id' => 1,
                        'aco_id' => 19,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Permisos',
                        ],
                    ],
                ],
                3 => [
                    'id' => 26,
                    'alias' => 'Pacients',
                    '_joinData' => [
                        'id' => 4,
                        'menu_group_id' => 1,
                        'aco_id' => 26,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Pacientes',
                        ],
                    ],
                ],
                4 => [
                    'id' => 34,
                    'alias' => 'Professionals',
                    '_joinData' => [
                        'id' => 5,
                        'menu_group_id' => 1,
                        'aco_id' => 34,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Profesionales',
                        ],
                    ],
                ],
                5 => [
                    'id' => 43,
                    'alias' => 'Professions',
                    '_joinData' => [
                        'id' => 6,
                        'menu_group_id' => 1,
                        'aco_id' => 43,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Profesiones',
                        ],
                    ],
                ],
                6 => [
                    'id' => 49,
                    'alias' => 'Profiles',
                    '_joinData' => [
                        'id' => 7,
                        'menu_group_id' => 1,
                        'aco_id' => 49,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Perfiles',
                        ],
                    ],
                ],
                7 => [
                    'id' => 57,
                    'alias' => 'Teams',
                    '_joinData' => [
                        'id' => 8,
                        'menu_group_id' => 1,
                        'aco_id' => 57,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Equipos',
                        ],
                    ],
                ],
                8 => [
                    'id' => 65,
                    'alias' => 'Users',
                    '_joinData' => [
                        'id' => 9,
                        'menu_group_id' => 1,
                        'aco_id' => 65,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Usuarios',
                        ],
                    ],
                ],
            ],
        ],
        1 => [
            'id' => 1,
            'name' => 'CAdministración',
            'acos' => [
                0 => [
                    'id' => 2,
                    'alias' => 'AcosMenuGroups',
                    '_joinData' => [
                        'id' => 1,
                        'menu_group_id' => 1,
                        'aco_id' => 2,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Permisos de los Grupos de Menú',
                        ],
                    ],
                ],
                1 => [
                    'id' => 13,
                    'alias' => 'MenuGroups',
                    '_joinData' => [
                        'id' => 2,
                        'menu_group_id' => 1,
                        'aco_id' => 13,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Grupos de Menú',
                        ],
                    ],
                ],
                2 => [
                    'id' => 19,
                    'alias' => 'MyPermissions',
                    '_joinData' => [
                        'id' => 3,
                        'menu_group_id' => 1,
                        'aco_id' => 19,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Permisos',
                        ],
                    ],
                ],
                3 => [
                    'id' => 26,
                    'alias' => 'Pacients',
                    '_joinData' => [
                        'id' => 4,
                        'menu_group_id' => 1,
                        'aco_id' => 26,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Pacientes',
                        ],
                    ],
                ],
                4 => [
                    'id' => 34,
                    'alias' => 'Professionals',
                    '_joinData' => [
                        'id' => 5,
                        'menu_group_id' => 1,
                        'aco_id' => 34,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Profesionales',
                        ],
                    ],
                ],
                5 => [
                    'id' => 43,
                    'alias' => 'Professions',
                    '_joinData' => [
                        'id' => 6,
                        'menu_group_id' => 1,
                        'aco_id' => 43,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Profesiones',
                        ],
                    ],
                ],
                6 => [
                    'id' => 49,
                    'alias' => 'Profiles',
                    '_joinData' => [
                        'id' => 7,
                        'menu_group_id' => 1,
                        'aco_id' => 49,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Perfiles',
                        ],
                    ],
                ],
                7 => [
                    'id' => 57,
                    'alias' => 'Teams',
                    '_joinData' => [
                        'id' => 8,
                        'menu_group_id' => 1,
                        'aco_id' => 57,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Equipos',
                        ],
                    ],
                ],
                8 => [
                    'id' => 65,
                    'alias' => 'Users',
                    '_joinData' => [
                        'id' => 9,
                        'menu_group_id' => 1,
                        'aco_id' => 65,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Usuarios',
                        ],
                    ],
                ],
            ],
        ],
        2 => [
            'id' => 1,
            'name' => 'BAdministración',
            'acos' => [
                0 => [
                    'id' => 2,
                    'alias' => 'AcosMenuGroups',
                    '_joinData' => [
                        'id' => 1,
                        'menu_group_id' => 1,
                        'aco_id' => 2,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Permisos de los Grupos de Menú',
                        ],
                    ],
                ],
                1 => [
                    'id' => 13,
                    'alias' => 'MenuGroups',
                    '_joinData' => [
                        'id' => 2,
                        'menu_group_id' => 1,
                        'aco_id' => 13,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Grupos de Menú',
                        ],
                    ],
                ],
                2 => [
                    'id' => 19,
                    'alias' => 'MyPermissions',
                    '_joinData' => [
                        'id' => 3,
                        'menu_group_id' => 1,
                        'aco_id' => 19,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Permisos',
                        ],
                    ],
                ],
                3 => [
                    'id' => 26,
                    'alias' => 'Pacients',
                    '_joinData' => [
                        'id' => 4,
                        'menu_group_id' => 1,
                        'aco_id' => 26,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Pacientes',
                        ],
                    ],
                ],
                4 => [
                    'id' => 34,
                    'alias' => 'Professionals',
                    '_joinData' => [
                        'id' => 5,
                        'menu_group_id' => 1,
                        'aco_id' => 34,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Profesionales',
                        ],
                    ],
                ],
                5 => [
                    'id' => 43,
                    'alias' => 'Professions',
                    '_joinData' => [
                        'id' => 6,
                        'menu_group_id' => 1,
                        'aco_id' => 43,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Profesiones',
                        ],
                    ],
                ],
                6 => [
                    'id' => 49,
                    'alias' => 'Profiles',
                    '_joinData' => [
                        'id' => 7,
                        'menu_group_id' => 1,
                        'aco_id' => 49,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Perfiles',
                        ],
                    ],
                ],
                7 => [
                    'id' => 57,
                    'alias' => 'Teams',
                    '_joinData' => [
                        'id' => 8,
                        'menu_group_id' => 1,
                        'aco_id' => 57,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Equipos',
                        ],
                    ],
                ],
                8 => [
                    'id' => 65,
                    'alias' => 'Users',
                    '_joinData' => [
                        'id' => 9,
                        'menu_group_id' => 1,
                        'aco_id' => 65,
                    ],
                    '_translations' => [
                        'es' => [
                            'locale' => 'es',
                            'alias' => 'Usuarios',
                        ],
                    ],
                ],
            ],
        ],
    ];
}

Thank you @dreamingmind that worked perfect.
I don’t know why that didn’t occur to me.