Bonjour, je rencontre des difficultés à effectuer un ajout d'attribut dans un résultat de requête :

$users = $this->Users->find('All');

$users contient la liste des utilisateurs et leurs attributs respectifs en base de données, j'aimerais ajouter un champ distance qui est complètement dynamique en fonction de leurs positions à l'instant de la demande.

UsersController :

foreach ($users as $key => $user) {                
    $user->distance = getDist($lat, $lng);
    // A ce stade j'ai bien ajouté 'distance' à mon objet users, enfin je présume je le retrouve bien dans le debug() du controller users (la fonction `getDist()` elle, me retourne un `float`)
}

Cependant dans mon foreach qui est dans la vue, $user->distance est inexistant.

Y a-t-il un moyen d'ajouter des données à la volé dans un objet de requête comme une Propriétés Virtuelles dynamique ?

Ensuite dans le cas ou le champ $user->distance est fonctionnel, je veux trier l'objet pour que le premier index soit la plus petite distance. Voici théoriquement comment je procèderai :

usort($users, function($a, $b){
        if ($a->distance === $b->distance) {
            return 0;
        }
        if ($a->distance < $b->distance) {
            return -1;
        }
        return 1;
});

Puis j'envoi à la vue :

$this->set('users', $this->paginate($users));

Merci, j'attend vos remarques avec impatience.

3 réponses


Bed0sk!l
Auteur
Réponse acceptée

Merci pour cette réponse parfaite concernant la première partie avec les Champs Calculés, par contre comme vous l'aviez prédit le tri sur le champ distance n'est pas reconnu, y a-t-il un moyen de l'effectuer ?

Bed0sk!l
Auteur
Réponse acceptée

Suite à de nombreuses complications pour trier le champ distance qui n'existe pas en base, j'ai décidé de changer la logique :

J'ai crée un table distances associé au utilisateurs qui contient le résultat de mon calcule et un uuidqui me permet d'isoler les résultats.

Merci pour votre aide qui ma permis de réviser ma logic.

Hello,

Voilà pour la première partie :

$users = $this->Users
    ->find('all')
    ->formatResults(function ($users) use ($lat, $lng) {
        return $users->map(function ($user) use ($lat, $lng) {
            $user->distance = getDist($lat, $lng);
            return $user;
        });
    });

Quand à la seconde, là je suis pas sûr de savoir comment faire. Essaye déjà avec ta méthode, si ça ne fonctionne pas, essaye avec un order comme ceci : (Mais c'est pas sûr qu'il reconnaisse le champ distance)

$users = $this->Users
    ->find('all')
    ->formatResults(function ($users) use ($lat, $lng) {
        return $users->map(function ($user) use ($lat, $lng) {
            $user->distance = getDist($lat, $lng);
            return $user;
        });
    })
    ->order(
        'distance' => 'ASC'
    );