table = strtolower(__CLASS__); //~ echo "TABLE = " . $this->table . "\n"; //~ } // getters public function getTable(): string { return $this->table; } public function getAll(): array // à améliorer pour ne pas renvoyer $db et $table { return get_object_vars($this); // retourne les propriétés de l'objet } // setters public function setID(int $value = 0) { if($value === 0) { $this->ID = $this->db->lastInsertId(); // méthode de PDO, attention lastInsertId() ne gère pas la concurence } else { $this->ID = $value; } return $this; } public function hydrate(array $data): bool // $data = tableau associatif en entrée: nom_du_champ => valeur { foreach($data as $key => $value) { // nom du setter // nom_propriete => setPropriete // on sépare les mots par des espaces, ucwords met la première lettre de chaque mot en majuscule, puis on supprime les espaces $setter_name = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); // ucwords: première lettre de chaque mot en majuscule if(method_exists($this, $setter_name)) { $this->$setter_name($value); } else { echo "debug: la méthode $setter_name n'existe pas\n"; return false; } } return true; } // cette fonction reçoit des données d'un tableau simple, permettant d'associer des champs de formulaires aux noms différents des champs de la BDD function hydrateFromForm(string $data_string, Object $Presta = NULL): bool // quand l'objet est $Details, on hydrate aussi $Presta { //~ $tableSize = count(StructTablesDB::$structureOfTables[$this->getTable()]); // int if($data_string !== '') { $data_array = explode('|', $data_string); // array $check = false; switch($this->getTable()) { case 'clients'; if($data_array[0] == '') { echo "debug: données insuffisantes, le nom du client doit au minimum être renseigné\n"; return false; } else { $check = $this->hydrate(['prenom_nom' => $data_array[0], 'code_client' => $data_array[1], 'adresse' => $data_array[2], 'code_postal' => $data_array[3], 'ville' => $data_array[4], 'telephone' => $data_array[5], 'courriel' => $data_array[6], 'apropos' => $data_array[7]]); } break; case 'prestations'; // inutilisé break; case 'devis'; //~ $check = $Presta->hydrate(['mode_paiement' => $data_array[6]]); //~ if($check) //~ { //~ $check = $this->hydrate(['taches' => $data_array[0], 'total_main_d_oeuvre' => $data_array[1], 'pieces' => $data_array[2], 'total_pieces' => $data_array[3], 'deplacement' => $data_array[4], 'total_HT' => $data_array[5], 'delai_livraison' => $data_array[7], 'validite_devis' => $data_array[8], 'signature_devis' => $data_array[9]]); $check = $this->hydrate(['taches' => $data_array[0], 'total_main_d_oeuvre' => $data_array[1], 'pieces' => $data_array[2], 'total_pieces' => $data_array[3], 'deplacement' => $data_array[4], 'total_HT' => $data_array[5], 'delai_livraison' => $data_array[6], 'validite_devis' => $data_array[7]]); //~ } break; case 'factures'; $check = $Presta->hydrate(['mode_paiement' => $data_array[10]]); if($check) { $check = $this->hydrate(['taches' => $data_array[0], 'machine' => $data_array[1], 'OS' => $data_array[2], 'donnees' => $data_array[3], 'cles_licences' => $data_array[4], 'total_main_d_oeuvre' => $data_array[5], 'pieces' => $data_array[6], 'total_pieces' => $data_array[7], 'deplacement' => $data_array[8], 'total_HT' => $data_array[9]]); } break; case 'cesu'; $check = $Presta->hydrate(['mode_paiement' => $data_array[3]]); if($check) { $check = $this->hydrate(['taches' => $data_array[0], 'duree_travail' => $data_array[1], 'salaire' => $data_array[2]]); } break; case 'locations'; //~ $check = $Presta->hydrate(['mode_paiement' => $data_array[11]]); //~ if($check) //~ { $check = $this->hydrate(['designation' => $data_array[0], 'modele_description' => $data_array[1], 'valeur' => $data_array[2], 'etat_des_lieux_debut' => $data_array[3], 'etat_des_lieux_fin' => $data_array[4], 'duree_location' => $data_array[5], 'loyer_mensuel' => $data_array[6], 'loyers_payes' => $data_array[7], 'caution' => $data_array[8]]); //~ } break; default: // inutilisé echo "debug: table inconnue hydrateFromForm()"; return false; } return $check; } else { echo "debug: annulation lors du formulaire\n"; return false; } } // exécuter le SQL // les attributs correspondent aux ? dans les requêtes préparées // ne pas surcharger la méthode PDO::query() qui n'est pas compatible protected function execQuery(string $sql, array $attributes = null) { $this->db = parent::getInstance(); // connexion if($attributes !== null) // requête préparée { //~ var_dump($sql); //~ var_dump($attributes); $query = $this->db->prepare($sql); $query->execute($attributes); return $query; } else // requête simple { return $this->db->query($sql); } } // méthodes CRUD // create INSERT public function create() // = write { $fields = []; $question_marks = []; // ? $values = []; //~ var_dump($this); foreach($this as $field => $value) { //~ var_dump($field); var_dump($value); // champs non renseignées et variables de l'objet qui ne sont pas des champs // note: avec le !== (au lieu de !=) une valeur 0 est différente de null if($value !== null && $field != 'db' && $field != 'table') { $fields[] = $field; // push $question_marks[] = '?'; $values[] = $value; } } $field_list = implode(', ', $fields); $question_mark_list = implode(', ', $question_marks); // INSERT INTO annonces (titre, description, actif) VALUES (?, ?, ?) return($this->execQuery('INSERT INTO ' . $this->table . ' (' . $field_list . ') VALUES (' . $question_mark_list . ')', $values)); } // read SELECT protected function readAll(): array // obtenir une table { return($this->execQuery('SELECT * FROM ' . $this->table)->fetchAll()); // fonctionne aussi sans le point virgule dans le SQL!! } public function findById() // obtenir une entrée grace à son ID { return($this->execQuery('SELECT * FROM ' . $this->table . ' WHERE id = ' . $this->ID)->fetch()); } public function getDetailsByIdPresta() { if($this->table == 'prestations') { // à l'occaz, créer une classe NonVendue et rendre Prestations abstraite echo 'erreur: ne pas appeler Model::getDetailsByIdPresta() si la table ciblée est "prestations".'; return 0; } else { return $this->execQuery('SELECT * FROM ' . $this->table . ' WHERE id_Presta = ' . $this->ID_presta)->fetch(); // type array } } protected function find(array $criteria): array // obtenir une entrée avec un tableau associatif 'champ' => 'valeur' { $fields = []; $values = []; // change "'ID' => 2" en "'ID' = ?" et "2" foreach($criteria as $field => $value) { $fields[] = "$field = ?"; // même chose que: $field . " = ?" $values[] = $value; } $field_list = implode(' AND ', $fields); // créer une chaîne reliant les morceaux avec le morceau AND en paramètre: 'adresse = ? AND ID = ?' // SELECT * FROM annonces WHERE actif = 1; return($this->execQuery('SELECT * FROM ' . $this->table . ' WHERE ' . $field_list, $values)->fetchAll()); } // update UPDATE public function update() { $fields = []; $values = []; foreach($this as $field => $value) { if($value !== null && $field != 'db' && $field != 'table') // champs non renseignées et variables de l'objet qui ne sont pas des champs { $fields[] = $field . ' = ?'; $values[] = $value; } } $values[] = $this->ID; // cette syntaxe ajoute une valeur au tableau $field_list = implode(', ', $fields); // UPDATE annonces SET titre = ?, description = ?, actif = ? WHERE id = ? return($this->execQuery('UPDATE ' . $this->table . ' SET ' . $field_list . ' WHERE id = ?', $values)); } public function updateOneValue(string $field, $value) { return($this->execQuery('UPDATE ' . $this->table . ' SET ' . $field . ' = ? WHERE id = ?', [$value, $this->ID])); } // delete DELETE protected function delete(int $id) { return($this->execQuery("DELETE FROM {$this->table} WHERE id = ?", [$id])); // double quotes "" pour insertion de variable, paramètre [$id] parce qu'on veut un tableau } // fonction appelée une seule fois au lancement du programme // le tableau nécessaire n'est pas copié en mémoire à l'instanciation (pas de fuite de mémoire), mais uniquement à l'appel de cette fonction statique, à la fin de la fonction la mémoire est libérée // DBStructure::${self::$tableStructure} permet de nommer une variable statique de classe static public function createTables() { foreach(StructTablesDB::$structureOfTables as $tableName => $oneTable) { //var_dump(StructTablesDB::${self::$tableStructure}); => propriété statique de classe dans une variable $fields_and_types = []; $query = 'CREATE TABLE IF NOT EXISTS ' . $tableName . ' ('; foreach($oneTable as $key => $value) { $fields_and_types[] = $key . ' ' . $value; } $query .= implode(', ', $fields_and_types); // implode() convertit un tableau en une chaîne avec un séparateur entre chaque élément $query .= ', PRIMARY KEY(ID AUTOINCREMENT));'; //echo($query . "\n\n"); parent::getInstance()->exec($query); // merci singleton! } } }