summaryrefslogtreecommitdiff
path: root/src/model/Model.php
blob: ad9e6c7b5e56f5e6fcf2529f3007bb7c35f86c48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<?php
// php/Model.php

class Model extends DB
{
    private $db; // instance de PDO
    protected $table; // <= enfant
    //static protected $tableStructure;
    
    public function __construct()
    {
        $this->db = parent::getInstance(); // connexion
    }
    
    
    // setters (plusieurs en même temps)
	public function hydrate(array $data) // $data = tableau associatif en entrée: nom_du_champ => valeur
	{
		foreach($data as $key => $value)
		{
			// nom d'un setter, forme "setMachin()"
			$setterName = 'set' . ucfirst($key); // ucfirst met la première lettre en majuscule
			// détection
			if(method_exists($this, $setterName)) // on trouve aussi la méthode is_callable()
			{
				// on renseigne les propriétés des l'instance
				$this->$setterName($value); // nom d'une méthode dans une variable
			}
		}
		return($this);
	}
    
    
    // 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
        {
            $query = $this->db->prepare($sql);
            $query->execute($attributes);
            return $query;
        }
        else // requête simple
        {
            return $this->db->query($sql);
        }
    }
    
    
    // méthodes CRUD qui marchent (les spécifiques sont dans les classes enfant)
    
    // create INSERT
    public function create() // = write
    {
        $fields = [];
        $question_marks = []; // ?
        $values = [];
        foreach($this as $field => $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 passe le filtre
            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
    public function readAll()
    {
        $query = $this->execQuery('SELECT * FROM ' . $this->table . ';'); // fonctionne aussi sans le point virgule dans le SQL!!
        return($query->fetchAll());
    }
    public function findById(int $id)
    {
        return($this->execQuery('SELECT * FROM ' . $this->table . ' WHERE id = ' . $id)->fetch());
    }
    
    public function find(array $criteria)
    {
        $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(int $id)
    {
        $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[] = $id;
        $field_list = implode(', ', $fields);
        
        // UPDATE annonces SET titre = ?, description = ?, actif = ? WHERE id= ?
        return($this->execQuery('UPDATE ' . $this->table . ' SET ' . $field_list . ' WHERE id = ?', $values));
    }
    
    
    // delete DELETE
    public 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 pour chaque table
    // 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()
    {
        //~ var_dump(StructTablesDB::$structureOfTables);
        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!
        }
        
        
    }
}