Completed
Push — master ( c2185a...82d130 )
by Vitaly
02:29
created

Database::connect()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 0 Features 6
Metric Value
c 8
b 0
f 6
dl 0
loc 24
rs 8.9714
cc 2
eloc 15
nc 2
nop 7
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: egorov
5
 * Date: 09.05.2015
6
 * Time: 13:05
7
 */
8
namespace samsonframework\orm;
9
10
/**
11
 * Class Database
12
 * @package samsonframework\orm
13
 */
14
class Database
15
{
16
    /** @var \PDO Database driver */
17
    protected $driver;
18
19
    /** @var string Database name */
20
    protected $database;
21
22
    /** @var int Amount of milliseconds spent on queries */
23
    protected $elapsed;
24
25
    /** @var int Amount queries executed */
26
    protected $count;
27
28
    /**
29
     * Connect to a database using driver with parameters
30
     * @param string $database Database name
31
     * @param string $username Database username
32
     * @param string $password Database password
33
     * @param string $host Database host(localhost by default)
34
     * @param int $port Database port(3306 by default)
35
     * @param string $driver Database driver for interaction(MySQL by default)
36
     * @param string $charset Database character set
37
     * @return bool True if connection to database was successful
38
     */
39
    public function connect(
40
        $database,
41
        $username,
42
        $password,
43
        $host = 'localhost',
44
        $port = 3306,
45
        $driver = 'mysql',
46
        $charset = 'utf8'
47
    ) {
48
        // If we have not connected yet
49
        if (!isset($this->driver)) {
50
            $this->database = $database;
51
52
            // Check if configured database exists
53
            $this->driver = new PDO($host, $database, $username, $password, $charset, $port, $driver);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \samsonframework\orm...harset, $port, $driver) of type object<samsonframework\orm\PDO> is incompatible with the declared type object<PDO> of property $driver.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
54
55
            // Set correct encodings
56
            $this->query("set character_set_client='utf8'");
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\Database::query() has been deprecated with message: Use execute()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
57
            $this->query("set character_set_results='utf8'");
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\Database::query() has been deprecated with message: Use execute()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
58
            $this->query("set collation_connection='utf8_general_ci'");
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\Database::query() has been deprecated with message: Use execute()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
59
60
            new ManagerGenerator($this);
61
        }
62
    }
63
64
    /**
65
     * Get database name
66
     * @return string
67
     */
68
    public function database()
69
    {
70
        return $this->database;
71
    }
72
73
    /**
74
     * High-level database query executor
75
     * @param string $sql SQL statement
76
     * @return mixed Database query result
77
     * @deprecated Use execute()
78
     */
79
    public function query($sql)
80
    {
81
        return $this->execute($sql);
82
    }
83
84
85
86
    /**
87
     * Intreal error beautifier
88
     * @param \Exception $exception
89
     * @param $sql
90
     */
91
    private function outputError(\Exception $exception, $sql, $text = 'Error executing database query:')
92
    {
93
        echo("\n" . '<div style="font-size:12px; position:relative; background:red; z-index:9999999;">'
94
            .'<div style="padding:4px 10px;">'.$text.'</div>'
95
            .'<div style="padding:0px 10px;">['.htmlspecialchars($exception->getMessage()).']</div>'
96
            .'<textarea style="display:block; width:100%; min-height:100px;">'.$sql . '</textarea></div>');
97
    }
98
99
    /**
100
     * Proxy function for executing database fetching logic with exception,
101
     * error, profile handling
102
     * @param callback $fetcher Callback for fetching
103
     * @return mixed Fetching function result
104
     */
105
    private function executeFetcher($fetcher, $sql)
106
    {
107
        $result = array();
108
109
        if (isset($this->driver)) {
110
            // Store timestamp
111
            $tsLast = microtime(true);
112
113
            try { // Call fetcher
114
                // Get argument and remove first one
115
                $args = func_get_args();
116
                array_shift($args);
117
118
                // Proxy calling of fetcher function with passing parameters
119
                $result = call_user_func_array($fetcher, $args);
120
            } catch (\PDOException $exception) {
121
                $this->outputError($exception, $sql, 'Error executing ['.$fetcher.']');
122
            }
123
124
            // Store queries count
125
            $this->count++;
126
127
            // Count elapsed time
128
            $this->elapsed += microtime(true) - $tsLast;
129
        }
130
131
        return $result;
132
    }
133
134
    /**
135
     * High-level database query executor
136
     * @param string $sql SQL statement
137
     * @return mixed Database query result
138
     */
139
    private function innerQuery($sql)
140
    {
141
        try {
142
            // Perform database query
143
            return $this->driver->prepare($sql)->execute();
144
        } catch (\PDOException $e) {
145
            $this->outputError($e, $sql);
146
        }
147
148
        return null;
149
    }
150
151
    /**
152
     * Retrieve array of records from a database, if $className is passed method
153
     * will try to create an object of that type. If request has failed than
154
     * method will return empty array of stdClass all arrays regarding to $className is
155
     * passed or not.
156
     *
157
     * @param string $sql SQL statement
158
     * @return array Collection of arrays or objects
159
     */
160
    private function innerFetch($sql, $className = null)
161
    {
162
        try {
163
            // Perform database query
164
            if (!isset($className)) { // Return array
165
                return $this->driver->query($sql)->fetchAll(\PDO::FETCH_ASSOC);
166
            } else { // Create object of passed class name
167
                return $this->driver->query($sql)->fetchAll(\PDO::FETCH_CLASS, $className, array(&$this));
168
            }
169
        } catch (\PDOException $e) {
170
            $this->outputError($e, $sql, 'Fetching database records:');
171
        }
172
173
        return array();
174
    }
175
176
    /**
177
     * Special accelerated function to retrieve db record fields instead of objects
178
     *
179
     * @param string $sql SQL statement
180
     * @param int $columnIndex Needed column index
181
     *
182
     * @return array Database records column value collection
183
     */
184
    private function innerFetchColumn($sql, $columnIndex)
185
    {
186
        try {
187
            // Perform database query
188
            return $this->driver->query($sql)->fetchAll(\PDO::FETCH_COLUMN, $columnIndex);
189
        } catch (\PDOException $e) {
190
            $this->outputError($e, $sql, 'Error fetching records column values:');
191
        }
192
193
        return array();
194
    }
195
196
    /**
197
     * High-level database query executor
198
     * @param string $sql SQL statement
199
     * @return mixed Database query result
200
     */
201
    public function execute($sql)
202
    {
203
        return $this->executeFetcher(array($this, 'innerQuery'), $sql);
204
    }
205
206
    /**
207
     * Retrieve array of records from a database, if $className is passed method
208
     * will try to create an object of that type. If request has failed than
209
     * method will return empty array of stdClass all arrays regarding to $className is
210
     * passed or not.
211
     *
212
     * @param string $sql SQL statement
213
     * @return array Collection of arrays or objects
214
     */
215
    public function fetch($sql)
216
    {
217
        return $this->executeFetcher(array($this, 'innerFetch'), $sql);
218
    }
219
220
    /**
221
     * Special accelerated function to retrieve db record fields instead of objects
222
     * TODO: Change to be independent of query and class name, just SQL, this SQL
223
     * should only have one column in SELECT part and then we do not need parameter
224
     * for this as we can always take 0.
225
     *
226
     * @param string $className
227
     * @param mixed $query
228
     * @param string $field
229
     *
230
     * @return array
231
     */
232
    public function fetchColumn($className, $query, $field)
233
    {
234
        // Get SQL
235
        $sql = $this->prepareSQL($className, $query);
0 ignored issues
show
Bug introduced by
The method prepareSQL() does not seem to exist on object<samsonframework\orm\Database>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
236
237
        // TODO: Remove old attributes retrieval
238
        // Get table column index by its name
239
        $columnIndex = array_search($field, array_values($className::$_table_attributes));
240
241
        return $this->executeFetcher(array($this, 'innerFetchColumn'), $sql, $columnIndex);
242
    }
243
244
    /**
245
     * Quote variable for security reasons.
246
     *
247
     * @param string $value
248
     * @return string Quoted value
249
     */
250
    protected function quote($value)
251
    {
252
        return $this->driver->quote($value);
253
    }
254
}
255