[ Index ] |
PHP Cross Reference of YOURLS |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * This file is part of Aura for PHP. 5 * 6 * @license https://opensource.org/licenses/MIT MIT 7 * 8 */ 9 namespace Aura\Sql; 10 11 use Aura\Sql\Parser\ParserInterface; 12 use Aura\Sql\Profiler\ProfilerInterface; 13 use BadMethodCallException; 14 use Generator; 15 use PDO; 16 use PDOStatement; 17 18 /** 19 * 20 * Provides array quoting, profiling, a new `perform()` method, new `fetch*()` 21 * methods, and new `yield*()` methods. 22 * 23 * @package Aura.Sql 24 * 25 */ 26 abstract class AbstractExtendedPdo extends PDO implements ExtendedPdoInterface 27 { 28 /** 29 * 30 * The internal PDO connection. 31 * 32 * @var PDO|null 33 * 34 */ 35 protected ?PDO $pdo = null; 36 37 /** 38 * 39 * Tracks and logs query profiles. 40 * 41 * @var ProfilerInterface 42 * 43 */ 44 protected ProfilerInterface $profiler; 45 46 /** 47 * 48 * Parses queries to rebuild them for easier parameter binding. 49 * 50 * @var ParserInterface 51 * 52 */ 53 protected ParserInterface $parser; 54 55 /** 56 * 57 * Prefix to use when quoting identifier names. 58 * 59 * @var string 60 * 61 */ 62 protected string $quoteNamePrefix = '"'; 63 64 /** 65 * 66 * Suffix to use when quoting identifier names. 67 * 68 * @var string 69 * 70 */ 71 protected string $quoteNameSuffix = '"'; 72 73 /** 74 * 75 * Find this string when escaping identifier names. 76 * 77 * @var string 78 * 79 */ 80 protected string $quoteNameEscapeFind = '"'; 81 82 /** 83 * 84 * Use this as the replacement when escaping identifier names. 85 * 86 * @var string 87 * 88 */ 89 protected string $quoteNameEscapeRepl = '""'; 90 91 /** 92 * 93 * Proxies to PDO methods created for specific drivers; in particular, 94 * `sqlite` and `pgsql`. 95 * 96 * @param string $name The PDO method to call; e.g. `sqliteCreateFunction` 97 * or `pgsqlGetPid`. 98 * 99 * @param array $arguments Arguments to pass to the called method. 100 * 101 * @return mixed 102 * 103 * @throws BadMethodCallException when the method does not exist. 104 * 105 */ 106 public function __call(string $name, array $arguments) 107 { 108 $this->lazyConnect(); 109 110 if (! method_exists($this->pdo, $name)) { 111 $class = get_class($this); 112 $message = "Class '$class' does not have a method '$name'"; 113 throw new BadMethodCallException($message); 114 } 115 116 return call_user_func_array([$this->pdo, $name], $arguments); 117 } 118 119 /** 120 * 121 * Begins a transaction and turns off autocommit mode. 122 * 123 * @return bool True on success, false on failure. 124 * 125 * @see http://php.net/manual/en/pdo.begintransaction.php 126 * 127 */ 128 public function beginTransaction(): bool 129 { 130 $this->lazyConnect(); 131 $this->profiler->start(__FUNCTION__); 132 $result = $this->pdo->beginTransaction(); 133 $this->profiler->finish(); 134 return $result; 135 } 136 137 /** 138 * 139 * Commits the existing transaction and restores autocommit mode. 140 * 141 * @return bool True on success, false on failure. 142 * 143 * @see http://php.net/manual/en/pdo.commit.php 144 * 145 */ 146 public function commit(): bool 147 { 148 $this->lazyConnect(); 149 $this->profiler->start(__FUNCTION__); 150 $result = $this->pdo->commit(); 151 $this->profiler->finish(); 152 return $result; 153 } 154 155 /** 156 * 157 * Connects to the database. 158 * 159 * @return void 160 */ 161 abstract public function lazyConnect(): void; 162 163 /** 164 * 165 * Disconnects from the database. 166 * 167 * @return void 168 */ 169 abstract public function disconnect(): void; 170 171 /** 172 * 173 * Gets the most recent error code. 174 * 175 * @return string|null 176 * 177 */ 178 public function errorCode(): ?string 179 { 180 $this->lazyConnect(); 181 return $this->pdo->errorCode(); 182 } 183 184 /** 185 * 186 * Gets the most recent error info. 187 * 188 * @return array 189 * 190 */ 191 public function errorInfo(): array 192 { 193 $this->lazyConnect(); 194 return $this->pdo->errorInfo(); 195 } 196 197 /** 198 * 199 * Executes an SQL statement and returns the number of affected rows. 200 * 201 * @param string $statement The SQL statement to prepare and execute. 202 * 203 * @return int|false The number of affected rows. 204 * 205 * @see http://php.net/manual/en/pdo.exec.php 206 * 207 */ 208 public function exec(string $statement): int|false 209 { 210 $this->lazyConnect(); 211 $this->profiler->start(__FUNCTION__); 212 $affectedRows = $this->pdo->exec($statement); 213 $this->profiler->finish($statement); 214 return $affectedRows; 215 } 216 217 /** 218 * 219 * Performs a statement and returns the number of affected rows. 220 * 221 * @param string $statement The SQL statement to prepare and execute. 222 * 223 * @param array $values Values to bind to the query. 224 * 225 * @return int 226 * 227 */ 228 public function fetchAffected(string $statement, array $values = []): int 229 { 230 $sth = $this->perform($statement, $values); 231 return $sth->rowCount(); 232 } 233 234 /** 235 * 236 * Fetches a sequential array of rows from the database; the rows 237 * are returned as associative arrays. 238 * 239 * @param string $statement The SQL statement to prepare and execute. 240 * 241 * @param array $values Values to bind to the query. 242 * 243 * @return array 244 * 245 */ 246 public function fetchAll(string $statement, array $values = []): array 247 { 248 $sth = $this->perform($statement, $values); 249 return $sth->fetchAll(self::FETCH_ASSOC); 250 } 251 252 /** 253 * 254 * Fetches an associative array of rows from the database; the rows 255 * are returned as associative arrays, and the array of rows is keyed 256 * on the first column of each row. 257 * 258 * N.b.: If multiple rows have the same first column value, the last 259 * row with that value will override earlier rows. 260 * 261 * @param string $statement The SQL statement to prepare and execute. 262 * 263 * @param array $values Values to bind to the query. 264 * 265 * @return array 266 * 267 */ 268 public function fetchAssoc(string $statement, array $values = []): array 269 { 270 $sth = $this->perform($statement, $values); 271 $data = []; 272 while ($row = $sth->fetch(self::FETCH_ASSOC)) { 273 $data[current($row)] = $row; 274 } 275 return $data; 276 } 277 278 /** 279 * 280 * Fetches the first column of rows as a sequential array. 281 * 282 * @param string $statement The SQL statement to prepare and execute. 283 * 284 * @param array $values Values to bind to the query. 285 * 286 * @return array 287 * 288 */ 289 public function fetchCol(string $statement, array $values = []): array 290 { 291 $sth = $this->perform($statement, $values); 292 return $sth->fetchAll(self::FETCH_COLUMN, 0); 293 } 294 295 /** 296 * 297 * Fetches multiple from the database as an associative array. The first 298 * column will be the index key. 299 * 300 * @param string $statement The SQL statement to prepare and execute. 301 * 302 * @param array $values Values to bind to the query. 303 * 304 * @param int $style a fetch style defaults to PDO::FETCH_COLUMN for single 305 * values, use PDO::FETCH_NAMED when fetching a multiple columns 306 * 307 * @return array 308 * 309 */ 310 public function fetchGroup( 311 string $statement, 312 array $values = [], 313 int $style = PDO::FETCH_COLUMN 314 ): array { 315 $sth = $this->perform($statement, $values); 316 return $sth->fetchAll(self::FETCH_GROUP | $style); 317 } 318 319 /** 320 * 321 * Fetches one row from the database as an object where the column values 322 * are mapped to object properties. 323 * 324 * Warning: PDO "injects property-values BEFORE invoking the constructor - 325 * in other words, if your class initializes property-values to defaults 326 * in the constructor, you will be overwriting the values injected by 327 * fetchObject() !" 328 * 329 * <http://www.php.net/manual/en/pdostatement.fetchobject.php#111744> 330 * 331 * @param string $statement The SQL statement to prepare and execute. 332 * 333 * @param array $values Values to bind to the query. 334 * 335 * @param string $class The name of the class to create. 336 * 337 * @param array $args Arguments to pass to the object constructor. 338 * 339 * @return object 340 * 341 */ 342 public function fetchObject( 343 string $statement, 344 array $values = [], 345 string $class = 'stdClass', 346 array $args = [] 347 ): object|false { 348 $sth = $this->perform($statement, $values); 349 350 if (! empty($args)) { 351 return $sth->fetchObject($class, $args); 352 } 353 354 return $sth->fetchObject($class); 355 } 356 357 /** 358 * 359 * Fetches a sequential array of rows from the database; the rows 360 * are returned as objects where the column values are mapped to 361 * object properties. 362 * 363 * Warning: PDO "injects property-values BEFORE invoking the constructor - 364 * in other words, if your class initializes property-values to defaults 365 * in the constructor, you will be overwriting the values injected by 366 * fetchObject() !" 367 * 368 * <http://www.php.net/manual/en/pdostatement.fetchobject.php#111744> 369 * 370 * @param string $statement The SQL statement to prepare and execute. 371 * 372 * @param array $values Values to bind to the query. 373 * 374 * @param string $class The name of the class to create from each 375 * row. 376 * 377 * @param array $args Arguments to pass to each object constructor. 378 * 379 * @return array 380 * 381 */ 382 public function fetchObjects( 383 string $statement, 384 array $values = [], 385 string $class = 'stdClass', 386 array $args = [] 387 ): array { 388 $sth = $this->perform($statement, $values); 389 390 if (! empty($args)) { 391 return $sth->fetchAll(self::FETCH_CLASS, $class, $args); 392 } 393 394 return $sth->fetchAll(self::FETCH_CLASS, $class); 395 } 396 397 /** 398 * 399 * Fetches one row from the database as an associative array. 400 * 401 * @param string $statement The SQL statement to prepare and execute. 402 * 403 * @param array $values Values to bind to the query. 404 * 405 * @return array|false 406 * 407 */ 408 public function fetchOne(string $statement, array $values = []): array|false 409 { 410 $sth = $this->perform($statement, $values); 411 return $sth->fetch(self::FETCH_ASSOC); 412 } 413 414 /** 415 * 416 * Fetches an associative array of rows as key-value pairs (first 417 * column is the key, second column is the value). 418 * 419 * @param string $statement The SQL statement to prepare and execute. 420 * 421 * @param array $values Values to bind to the query. 422 * 423 * @return array 424 * 425 */ 426 public function fetchPairs(string $statement, array $values = []): array 427 { 428 $sth = $this->perform($statement, $values); 429 return $sth->fetchAll(self::FETCH_KEY_PAIR); 430 } 431 432 /** 433 * 434 * Fetches the very first value (i.e., first column of the first row). 435 * 436 * @param string $statement The SQL statement to prepare and execute. 437 * 438 * @param array $values Values to bind to the query. 439 * 440 * @return mixed 441 * 442 */ 443 public function fetchValue(string $statement, array $values = []): mixed 444 { 445 $sth = $this->perform($statement, $values); 446 return $sth->fetchColumn(0); 447 } 448 449 /** 450 * 451 * Returns the Parser instance. 452 * 453 * @return ParserInterface 454 * 455 */ 456 public function getParser(): ParserInterface 457 { 458 return $this->parser; 459 } 460 461 /** 462 * 463 * Return the inner PDO (if any) 464 * 465 * @return \PDO 466 * 467 */ 468 public function getPdo(): PDO 469 { 470 return $this->pdo; 471 } 472 473 /** 474 * 475 * Returns the Profiler instance. 476 * 477 * @return ProfilerInterface 478 * 479 */ 480 public function getProfiler(): ProfilerInterface 481 { 482 return $this->profiler; 483 } 484 485 /** 486 * 487 * Is a transaction currently active? 488 * 489 * @return bool 490 * 491 * @see http://php.net/manual/en/pdo.intransaction.php 492 * 493 */ 494 public function inTransaction(): bool 495 { 496 $this->lazyConnect(); 497 $this->profiler->start(__FUNCTION__); 498 $result = $this->pdo->inTransaction(); 499 $this->profiler->finish(); 500 return $result; 501 } 502 503 /** 504 * 505 * Is the PDO connection active? 506 * 507 * @return bool 508 * 509 */ 510 public function isConnected(): bool 511 { 512 return (bool) $this->pdo; 513 } 514 515 /** 516 * 517 * Returns the last inserted autoincrement sequence value. 518 * 519 * @param string|null $name The name of the sequence to check; typically needed 520 * only for PostgreSQL, where it takes the form of `<table>_<column>_seq`. 521 * 522 * @return string|false 523 * 524 * @see http://php.net/manual/en/pdo.lastinsertid.php 525 */ 526 public function lastInsertId(?string $name = null): string|false 527 { 528 $this->lazyConnect(); 529 $this->profiler->start(__FUNCTION__); 530 $result = $this->pdo->lastInsertId($name); 531 $this->profiler->finish(); 532 return $result; 533 } 534 535 /** 536 * 537 * Performs a query with bound values and returns the resulting 538 * PDOStatement; array values will be passed through `quote()` and their 539 * respective placeholders will be replaced in the query string. 540 * 541 * @param string $statement The SQL statement to perform. 542 * 543 * @param array $values Values to bind to the query 544 * 545 * @return PDOStatement 546 * 547 * @throws \Aura\Sql\Exception\CannotBindValue 548 * @see quote() 549 * 550 */ 551 public function perform(string $statement, array $values = []): PDOStatement 552 { 553 $this->lazyConnect(); 554 $sth = $this->prepareWithValues($statement, $values); 555 $this->profiler->start(__FUNCTION__); 556 $sth->execute(); 557 $this->profiler->finish($statement, $values); 558 return $sth; 559 } 560 561 /** 562 * 563 * Prepares an SQL statement for execution. 564 * 565 * @param string $query The SQL statement to prepare for execution. 566 * 567 * @param array $options Set these attributes on the returned 568 * PDOStatement. 569 * 570 * @return PDOStatement|false 571 * 572 * @see http://php.net/manual/en/pdo.prepare.php 573 * 574 */ 575 public function prepare(string $query, array $options = []): PDOStatement|false 576 { 577 $this->lazyConnect(); 578 $sth = $this->pdo->prepare($query, $options); 579 return $sth; 580 } 581 582 /** 583 * 584 * Prepares an SQL statement with bound values. 585 * 586 * This method only binds values that have placeholders in the 587 * statement, thereby avoiding errors from PDO regarding too many bound 588 * values. It also binds all sequential (question-mark) placeholders. 589 * 590 * If a placeholder value is an array, the array is converted to a string 591 * of comma-separated quoted values; e.g., for an `IN (...)` condition. 592 * The quoted string is replaced directly into the statement instead of 593 * using `PDOStatement::bindValue()` proper. 594 * 595 * @param string $statement The SQL statement to prepare for execution. 596 * 597 * @param array $values The values to bind to the statement, if any. 598 * 599 * @return PDOStatement 600 * 601 * @throws \Aura\Sql\Exception\CannotBindValue 602 * @see http://php.net/manual/en/pdo.prepare.php 603 * 604 */ 605 public function prepareWithValues(string $statement, array $values = []): PDOStatement 606 { 607 // if there are no values to bind ... 608 if (empty($values)) { 609 // ... use the normal preparation 610 return $this->prepare($statement); 611 } 612 613 $this->lazyConnect(); 614 615 // rebuild the statement and values 616 $parser = clone $this->parser; 617 list($statement, $values) = $parser->rebuild($statement, $values); 618 619 // prepare the statement 620 $sth = $this->pdo->prepare($statement); 621 622 // for the placeholders we found, bind the corresponding data values 623 foreach ($values as $key => $val) { 624 $this->bindValue($sth, $key, $val); 625 } 626 627 // done 628 return $sth; 629 } 630 631 /** 632 * 633 * Queries the database and returns a PDOStatement. 634 * 635 * @param string $query The SQL statement to prepare and execute. 636 * 637 * @param int|null $fetchMode 638 * 639 * @param mixed ...$fetch_mode_args Optional fetch-related parameters. 640 * 641 * @return PDOStatement|false 642 * 643 * @see http://php.net/manual/en/pdo.query.php 644 * 645 */ 646 public function query(string $query, ?int $fetchMode = null, mixed ...$fetch_mode_args): PDOStatement|false 647 { 648 $this->lazyConnect(); 649 $this->profiler->start(__FUNCTION__); 650 $sth = $this->pdo->query($query, $fetchMode, ...$fetch_mode_args); 651 $this->profiler->finish($sth->queryString); 652 return $sth; 653 } 654 655 /** 656 * 657 * Quotes a value for use in an SQL statement. 658 * 659 * This differs from `PDO::quote()` in that it will convert an array into 660 * a string of comma-separated quoted values. 661 * 662 * @param string|int|array|float|null $value The value to quote. 663 * 664 * @param int $type A data type hint for the database driver. 665 * 666 * @return string|false The quoted value or false if the driver does not support quoting in this way. 667 * 668 * @see http://php.net/manual/en/pdo.quote.php 669 * 670 */ 671 public function quote(string|int|array|float|null $value, int $type = self::PARAM_STR): string|false 672 { 673 $this->lazyConnect(); 674 675 $value = $value ?? ""; 676 677 // non-array quoting 678 if (! is_array($value)) { 679 return $this->pdo->quote($value, $type); 680 } 681 682 // quote array values, not keys, then combine with commas 683 foreach ($value as $k => $v) { 684 $value[$k] = $this->pdo->quote($v, $type); 685 } 686 return implode(', ', $value); 687 } 688 689 /** 690 * 691 * Quotes a multi-part (dotted) identifier name. 692 * 693 * @param string $name The multi-part identifier name. 694 * 695 * @return string The multi-part identifier name, quoted. 696 * 697 */ 698 public function quoteName(string $name): string 699 { 700 if (! str_contains($name, '.')) { 701 return $this->quoteSingleName($name); 702 } 703 704 return implode( 705 '.', 706 array_map( 707 [$this, 'quoteSingleName'], 708 explode('.', $name) 709 ) 710 ); 711 } 712 713 /** 714 * 715 * Quotes a single identifier name. 716 * 717 * @param string $name The identifier name. 718 * 719 * @return string The quoted identifier name. 720 * 721 */ 722 public function quoteSingleName(string $name): string 723 { 724 $name = str_replace( 725 $this->quoteNameEscapeFind, 726 $this->quoteNameEscapeRepl, 727 $name 728 ); 729 return $this->quoteNamePrefix 730 . $name 731 . $this->quoteNameSuffix; 732 } 733 734 /** 735 * 736 * Rolls back the current transaction, and restores autocommit mode. 737 * 738 * @return bool True on success, false on failure. 739 * 740 * @see http://php.net/manual/en/pdo.rollback.php 741 * 742 */ 743 public function rollBack(): bool 744 { 745 $this->lazyConnect(); 746 $this->profiler->start(__FUNCTION__); 747 $result = $this->pdo->rollBack(); 748 $this->profiler->finish(); 749 return $result; 750 } 751 752 /** 753 * 754 * Sets the Parser instance. 755 * 756 * @param ParserInterface $parser The Parser instance. 757 * 758 */ 759 public function setParser(ParserInterface $parser): void 760 { 761 $this->parser = $parser; 762 } 763 764 /** 765 * 766 * Sets the Profiler instance. 767 * 768 * @param ProfilerInterface $profiler The Profiler instance. 769 * 770 */ 771 public function setProfiler(ProfilerInterface $profiler): void 772 { 773 $this->profiler = $profiler; 774 } 775 776 /** 777 * 778 * Yields rows from the database. 779 * 780 * @param string $statement The SQL statement to prepare and execute. 781 * 782 * @param array $values Values to bind to the query. 783 * 784 * @return \Generator 785 * 786 */ 787 public function yieldAll(string $statement, array $values = []): Generator 788 { 789 $sth = $this->perform($statement, $values); 790 while ($row = $sth->fetch(self::FETCH_ASSOC)) { 791 yield $row; 792 } 793 } 794 795 /** 796 * 797 * Yields rows from the database keyed on the first column of each row. 798 * 799 * @param string $statement The SQL statement to prepare and execute. 800 * 801 * @param array $values Values to bind to the query. 802 * 803 * @return \Generator 804 * 805 */ 806 public function yieldAssoc(string $statement, array $values = []): Generator 807 { 808 $sth = $this->perform($statement, $values); 809 while ($row = $sth->fetch(self::FETCH_ASSOC)) { 810 $key = current($row); 811 yield $key => $row; 812 } 813 } 814 815 /** 816 * 817 * Yields the first column of each row. 818 * 819 * @param string $statement The SQL statement to prepare and execute. 820 * 821 * @param array $values Values to bind to the query. 822 * 823 * @return \Generator 824 * 825 */ 826 public function yieldCol(string $statement, array $values = []): Generator 827 { 828 $sth = $this->perform($statement, $values); 829 while ($row = $sth->fetch(self::FETCH_NUM)) { 830 yield $row[0]; 831 } 832 } 833 834 /** 835 * 836 * Yields objects where the column values are mapped to object properties. 837 * 838 * Warning: PDO "injects property-values BEFORE invoking the constructor - 839 * in other words, if your class initializes property-values to defaults 840 * in the constructor, you will be overwriting the values injected by 841 * fetchObject() !" 842 * <http://www.php.net/manual/en/pdostatement.fetchobject.php#111744> 843 * 844 * @param string $statement The SQL statement to prepare and execute. 845 * 846 * @param array $values Values to bind to the query. 847 * 848 * @param string $class The name of the class to create from each 849 * row. 850 * 851 * @param array $args Arguments to pass to each object constructor. 852 * 853 * @return \Generator 854 * 855 */ 856 public function yieldObjects( 857 string $statement, 858 array $values = [], 859 string $class = 'stdClass', 860 array $args = [] 861 ): Generator { 862 $sth = $this->perform($statement, $values); 863 864 if (empty($args)) { 865 while ($instance = $sth->fetchObject($class)) { 866 yield $instance; 867 } 868 } else { 869 while ($instance = $sth->fetchObject($class, $args)) { 870 yield $instance; 871 } 872 } 873 } 874 875 /** 876 * 877 * Yields key-value pairs (first column is the key, second column is the 878 * value). 879 * 880 * @param string $statement The SQL statement to prepare and execute. 881 * 882 * @param array $values Values to bind to the query. 883 * 884 * @return \Generator 885 * 886 */ 887 public function yieldPairs(string $statement, array $values = []): Generator 888 { 889 $sth = $this->perform($statement, $values); 890 while ($row = $sth->fetch(self::FETCH_NUM)) { 891 yield $row[0] => $row[1]; 892 } 893 } 894 895 /** 896 * 897 * Bind a value using the proper PDO::PARAM_* type. 898 * 899 * @param PDOStatement $sth The statement to bind to. 900 * 901 * @param mixed $key The placeholder key. 902 * 903 * @param mixed $val The value to bind to the statement. 904 * 905 * @return bool 906 * 907 * @throws Exception\CannotBindValue when the value to be bound is not 908 * bindable (e.g., array, object, or resource). 909 * 910 */ 911 protected function bindValue(PDOStatement $sth, mixed $key, mixed $val): bool 912 { 913 if (is_int($val)) { 914 return $sth->bindValue($key, $val, self::PARAM_INT); 915 } 916 917 if (is_bool($val)) { 918 return $sth->bindValue($key, $val, self::PARAM_BOOL); 919 } 920 921 if (is_null($val)) { 922 return $sth->bindValue($key, $val, self::PARAM_NULL); 923 } 924 925 if (! is_scalar($val)) { 926 $type = gettype($val); 927 throw new Exception\CannotBindValue( 928 "Cannot bind value of type '{$type}' to placeholder '{$key}'" 929 ); 930 } 931 932 return $sth->bindValue($key, $val); 933 } 934 935 /** 936 * 937 * Returns a new Parser instance. 938 * 939 * @param string $driver Return a parser for this driver. 940 * 941 * @return ParserInterface 942 * 943 */ 944 protected function newParser(string $driver): ParserInterface 945 { 946 $class = 'Aura\Sql\Parser\\' . ucfirst($driver) . 'Parser'; 947 if (! class_exists($class)) { 948 $class = 'Aura\Sql\Parser\SqliteParser'; 949 } 950 return new $class(); 951 } 952 953 /** 954 * 955 * Sets quoting properties based on the PDO driver. 956 * 957 * @param string $driver The PDO driver name. 958 * 959 * @return void 960 * 961 */ 962 protected function setQuoteName(string $driver): void 963 { 964 switch ($driver) { 965 case 'mysql': 966 $this->quoteNamePrefix = '`'; 967 $this->quoteNameSuffix = '`'; 968 $this->quoteNameEscapeFind = '`'; 969 $this->quoteNameEscapeRepl = '``'; 970 return; 971 case 'sqlsrv': 972 $this->quoteNamePrefix = '['; 973 $this->quoteNameSuffix = ']'; 974 $this->quoteNameEscapeFind = ']'; 975 $this->quoteNameEscapeRepl = ']['; 976 return; 977 default: 978 $this->quoteNamePrefix = '"'; 979 $this->quoteNameSuffix = '"'; 980 $this->quoteNameEscapeFind = '"'; 981 $this->quoteNameEscapeRepl = '""'; 982 return; 983 } 984 } 985 986 /** 987 * 988 * Retrieve a database connection attribute 989 * 990 * @param int $attribute 991 * @return bool|int|string|array|null 992 */ 993 public function getAttribute(int $attribute): bool|int|string|array|null 994 { 995 $this->lazyConnect(); 996 return $this->pdo->getAttribute($attribute); 997 } 998 999 /** 1000 * 1001 * Set a database connection attribute 1002 * 1003 * @param int $attribute 1004 * @param mixed $value 1005 * @return bool 1006 */ 1007 public function setAttribute(int $attribute, mixed $value): bool 1008 { 1009 $this->lazyConnect(); 1010 return $this->pdo->setAttribute($attribute, $value); 1011 } 1012 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Mar 31 05:10:02 2025 | Cross-referenced by PHPXref 0.7.1 |