Salutations chers amis dév ;)

Je suis face à un petit bloquant que je n'arrive pas à passer :(

J'ai un Model Cours que voici :

<?php
class Cours extends Model {

    private $isDoublon = false;
    protected $fillable = ['date_debut', 'date_fin', 'hres_tot', 'hres_lab', 'etud_th', 'etud_lab1', 'etud_lab2'];
?>

Je récupère ces cours dans des collections et j'aimerais alimenter la propriété $isDoublon si l'un d'eux est déjà présent dans ma collection (le premier doublon sera $isDoublon = false; mais les autres doublons seront à true !)

Je pensais y aller avec la méthode each() offerte par l'API de Laravel, mais je sèche sur comment faire ça puisque je n'ai pas accès à la Collection une fois dans la fonction anonyme.

$cours->each(function($item){
            dd($cours); #ErrorException in Scenario.php line 199: Undefined variable: cours
        });

Auriez vous une idée ou une piste sur laquelle je peux embarquer ? ;)

Merci d'avance.

5 réponses


Azorgh
Réponse acceptée

Hello,

J'ai une méthode qui me vient, un peu "crade" mais si ca peut t'aller la voici.
Tu utilise la méthode filter sur ta collection, en ajoutant les nom dans un tableau seulement si il n'existe pas. Par exemple :

<?php
$cours = Cour::all();
$cours_already_viewed = [];

$cours_unique = $cours->filter(function($cour){
    if(!in_array($cour->name, $cours_already_viewed)){
        $cours_already_viewed[] = $cour->name;
        return true;
    }

    return false;
});

Après réflexion, on pourrait utiliser dans mon cas les Collection Laravel en faisant :

$cours_already_viewed = collect([]);

//Dans le filter :
if( ! $cours_already_viewed->contains($cour->name)){
    $cours_already_viewed->push($cour->name);
    return true;
}

Je n'ai pas testé le code, mais sur le principe il devrait être bon. Je pense tout de même que le travail avec un tableau et non une collection serait plus rapide (simplement pour un in_array et un push, je vois pas trop l'interêt de faire une nouvelle collection surtout si tu ne t'en sert qu'ici).

En espérant t'avoir aidé !

Et as tu pensé à la possibilitée de créer une nouvelle collection en retravaillant l'ancienne ? Avec les collections de Laravel ?

rash
Auteur

Alors merci, je n'y avais pas pensé ! ;)
Mais je sèche toujours car je n'obtiens pas le résultat que j'attends.

Voici ce que j'ai fais :

<?php
$cours = Cours::all(); #Récupération des cours [dans mon code c'est différent mais bon poru l'exemple on va faire simple]
//On enlève les doublons (?)
$coursUnique = $cours->unique(); #Problème : ils sont tous unique puisque leur "id" est différent, mais le numéro de cours ne l'est pas et c'est sur cela que je souhaiterai différencier mon unicité
$coursDoublons = $cours->diff($coursUnique); #Renvoie une collection vide, sûrement à cause de la ligne du dessus qui doit comparer les id.

Comment puis-je dire à la Collection de tester l'unicité sur une autre clé que celle par défaut (id) ?

rash
Auteur

Salut PallMallShow !

Merci ton code m'a mis sur la piste. Malheureusement, je crois qu'on ne peut pas transmettre de variable à filter() (ou alors je m'y suis très mal pris, en tout cas il était incapable d'accèder aux variables en dehors de la fonction anonyme)

Du coup j'ai fais ceci :

$cours = Cours::all();
$resultat = [];

        foreach ($cours as $ligne) {
            if(in_array($ligne->cours_id, $resultat)) {

                $ligne->setDoublon(); #Passe la propriété $isDoublon à true
            }

            $resultat[] = $scenario->cours_id;
        }

        dd($cours);

Cela fonctionne ;)
Mon dd($cours) m'affiche correctement la liste des cours avec le dernier comme étant un doublon (car l'avant dernier possède le même cours_id et n'est pas marqué comme étant un doublon !) :)

Merci à vous deux ;)

Pour le faire propre avec filter, il faut faire ça :


$collection->filter(function($cour) use($vours_already_viewed){
    /* [...] */
});