Commit | Line | Data |
---|---|---|
d9cdc0cc TD |
1 | <!DOCTYPE html> |
2 | <head> | |
3 | <meta charset="utf-8"> | |
4 | <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
5 | <meta name="viewport" content="width=device-width, initial-scale=1"> | |
6 | <meta name="description" content=""> | |
7 | <meta name="keywords" content=" "> | |
8 | <title>Database Access | WoltLab Suite 5.3 Documentation</title> | |
9 | ||
e2f8eee7 | 10 | <link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/syntax.css"> |
d9cdc0cc | 11 | <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,300,600"> |
e2f8eee7 | 12 | <link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/font-awesome.min.css"> |
d9cdc0cc | 13 | <!--<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">--> |
e2f8eee7 TD |
14 | <link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/modern-business.css"> |
15 | <link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/lavish-bootstrap.css"> | |
16 | <link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/customstyles.css"> | |
17 | <link rel="stylesheet" href="https://docs.woltlab.com/5.3/css/theme-blue.css?v=3"> | |
d9cdc0cc | 18 | |
e2f8eee7 TD |
19 | <script src="https://docs.woltlab.com/5.3/js/jquery.min.js"></script> |
20 | <script src="https://docs.woltlab.com/5.3/js/jquery.cookie.min.js"></script> | |
21 | <script src="https://docs.woltlab.com/5.3/js/jquery.navgoco.min.js"></script> | |
22 | <script src="https://docs.woltlab.com/5.3/js/bootstrap.min.js"></script> | |
23 | <script src="https://docs.woltlab.com/5.3/js/anchor.min.js"></script> | |
24 | <script src="https://docs.woltlab.com/5.3/js/toc.js"></script> | |
25 | <script src="https://docs.woltlab.com/5.3/js/customscripts.js"></script> | |
d9cdc0cc | 26 | |
e2f8eee7 | 27 | <link rel="shortcut icon" href="https://docs.woltlab.com/5.3/images/favicon.ico"> |
d9cdc0cc | 28 | |
e2f8eee7 | 29 | <link rel="alternate" type="application/rss+xml" title="woltlab.github.io" href="https://docs.woltlab.com/5.3feed.xml"> |
d9cdc0cc TD |
30 | |
31 | <script> | |
32 | $(document).ready(function() { | |
33 | // Initialize navgoco with default options | |
34 | $("#mysidebar").navgoco({ | |
35 | caretHtml: '', | |
36 | accordion: true, | |
37 | openClass: 'active', // open | |
38 | save: false, // leave false or nav highlighting doesn't work right | |
39 | cookie: { | |
40 | name: 'navgoco', | |
41 | expires: false, | |
42 | path: '/' | |
43 | }, | |
44 | slide: { | |
45 | duration: 400, | |
46 | easing: 'swing' | |
47 | } | |
48 | }); | |
49 | ||
50 | $("#collapseAll").click(function(e) { | |
51 | e.preventDefault(); | |
52 | $("#mysidebar").navgoco('toggle', false); | |
53 | }); | |
54 | ||
55 | $("#expandAll").click(function(e) { | |
56 | e.preventDefault(); | |
57 | $("#mysidebar").navgoco('toggle', true); | |
58 | }); | |
59 | ||
60 | }); | |
61 | ||
62 | </script> | |
63 | <script> | |
64 | $(function () { | |
65 | $('[data-toggle="tooltip"]').tooltip() | |
66 | }) | |
67 | </script> | |
68 | ||
69 | ||
70 | </head> | |
71 | <body> | |
72 | <!-- Navigation --> | |
73 | <nav class="navbar navbar-inverse navbar-fixed-top"> | |
74 | <div class="container topnavlinks"> | |
75 | <div class="navbar-header"> | |
76 | <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> | |
77 | <span class="sr-only">Toggle navigation</span> | |
78 | <span class="icon-bar"></span> | |
79 | <span class="icon-bar"></span> | |
80 | <span class="icon-bar"></span> | |
81 | </button> | |
82 | <a class="fa fa-home fa-lg navbar-brand" href="index.html"> <span class="projectTitle"> WoltLab Suite 5.3 Documentation</span></a> | |
83 | </div> | |
84 | <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> | |
85 | <ul class="nav navbar-nav navbar-right"> | |
86 | <!-- entries without drop-downs appear here --> | |
87 | ||
88 | ||
89 | ||
90 | <li><a href="https://www.woltlab.com" target="_blank">woltlab.com</a></li> | |
91 | ||
92 | ||
93 | ||
94 | ||
95 | ||
96 | <li><a href="https://github.com/WoltLab/WCF/" target="_blank">Code on github.com</a></li> | |
97 | ||
98 | ||
99 | ||
100 | <!-- entries with drop-downs appear here --> | |
101 | <!-- conditional logic to control which topnav appears for the audience defined in the configuration file.--> | |
102 | ||
103 | ||
104 | <!--comment out this block if you want to hide search--> | |
105 | <li> | |
106 | <!--start search--> | |
107 | <div id="search-demo-container"> | |
108 | <input type="text" id="search-input" placeholder="search..."> | |
109 | <ul id="results-container"></ul> | |
110 | </div> | |
e2f8eee7 | 111 | <script src="https://docs.woltlab.com/5.3/js/jekyll-search.js" type="text/javascript"></script> |
d9cdc0cc TD |
112 | <script type="text/javascript"> |
113 | SimpleJekyllSearch.init({ | |
114 | searchInput: document.getElementById('search-input'), | |
115 | resultsContainer: document.getElementById('results-container'), | |
e2f8eee7 | 116 | dataSource: 'https://docs.woltlab.com/5.3/search.json', |
d9cdc0cc TD |
117 | searchResultTemplate: '<li><a href="{url}" title="Database Access">{title}</a></li>', |
118 | noResultsText: 'No results found.', | |
119 | limit: 10, | |
120 | fuzzy: true, | |
121 | }) | |
122 | </script> | |
123 | <!--end search--> | |
124 | </li> | |
125 | </ul> | |
126 | </div> | |
127 | </div> | |
128 | <!-- /.container --> | |
129 | </nav> | |
130 | ||
131 | ||
132 | <div class="container"> | |
133 | <div class="col-lg-12"> </div> | |
134 | ||
135 | <div class="row"> | |
136 | <div class="col-md-3"> | |
137 | ||
138 | ||
139 | ||
140 | <ul id="mysidebar" class="nav"> | |
141 | <li class="sidebarTitle">WoltLab Suite 5.3</li> | |
142 | ||
143 | ||
144 | ||
145 | <li> | |
146 | <a href="#">Getting Started</a> | |
147 | <ul> | |
148 | ||
149 | ||
150 | ||
151 | ||
152 | <li data-identifier="index"><a href="index.html">Introduction</a></li> | |
153 | ||
154 | ||
155 | ||
156 | ||
157 | ||
158 | ||
159 | ||
160 | ||
161 | <li data-identifier="getting-started_quick-start"><a href="getting-started_quick-start.html">Quick Start</a></li> | |
162 | ||
163 | ||
164 | ||
165 | ||
166 | ||
167 | </ul> | |
168 | </li> | |
169 | ||
170 | <li> | |
171 | <a href="#">PHP API</a> | |
172 | <ul> | |
173 | ||
174 | ||
175 | ||
176 | ||
177 | <li data-identifier="php_pages"><a href="php_pages.html">Pages</a></li> | |
178 | ||
179 | ||
180 | ||
181 | ||
182 | ||
183 | ||
184 | ||
185 | ||
186 | <li data-identifier="php_database-objects"><a href="php_database-objects.html">Database Objects</a></li> | |
187 | ||
188 | ||
189 | ||
190 | ||
191 | ||
192 | ||
193 | ||
194 | ||
195 | <li class="active" data-identifier="php_database-access"><a href="php_database-access.html">Database Access</a></li> | |
196 | ||
197 | ||
198 | ||
199 | ||
200 | ||
201 | ||
202 | ||
203 | ||
204 | <li data-identifier="php_exceptions"><a href="php_exceptions.html">Exceptions</a></li> | |
205 | ||
206 | ||
207 | ||
208 | ||
209 | ||
210 | ||
211 | ||
212 | ||
213 | <li class="subfolders"> | |
214 | <a href="#">API</a> | |
215 | <ul> | |
216 | ||
217 | ||
218 | ||
219 | <li data-identifier="php_api_caches"><a href="php_api_caches.html">Caches</a></li> | |
220 | ||
221 | ||
222 | ||
223 | ||
224 | <li data-identifier="php_api_comments"><a href="php_api_comments.html">Comments</a></li> | |
225 | ||
226 | ||
227 | ||
228 | ||
229 | <li data-identifier="php_api_cronjobs"><a href="php_api_cronjobs.html">Cronjobs</a></li> | |
230 | ||
231 | ||
232 | ||
233 | ||
234 | <li data-identifier="php_api_events"><a href="php_api_events.html">Events</a></li> | |
235 | ||
236 | ||
237 | ||
238 | ||
239 | <li data-identifier="php_api_form_builder"><a href="php_api_form_builder.html">Form Builder</a></li> | |
240 | ||
241 | ||
242 | ||
243 | ||
244 | <li data-identifier="php_api_package_installation_plugins"><a href="php_api_package_installation_plugins.html">Package Installation Plugins</a></li> | |
245 | ||
246 | ||
247 | ||
248 | ||
249 | <li data-identifier="php_api_user_activity_points"><a href="php_api_user_activity_points.html">User Activity Points</a></li> | |
250 | ||
251 | ||
252 | ||
253 | ||
254 | <li data-identifier="php_api_user_notifications"><a href="php_api_user_notifications.html">User Notifications</a></li> | |
255 | ||
256 | ||
257 | ||
258 | ||
259 | <li data-identifier="php_api_sitemaps"><a href="php_api_sitemaps.html">Sitemaps</a></li> | |
260 | ||
261 | ||
262 | </ul> | |
263 | </li> | |
264 | ||
265 | ||
266 | ||
267 | ||
268 | ||
269 | <li data-identifier="php_code-style"><a href="php_code-style.html">Code Style</a></li> | |
270 | ||
271 | ||
272 | ||
273 | ||
274 | ||
275 | ||
276 | ||
277 | ||
278 | <li data-identifier="php_apps"><a href="php_apps.html">Apps</a></li> | |
279 | ||
280 | ||
281 | ||
282 | ||
283 | ||
284 | ||
285 | ||
286 | ||
287 | <li data-identifier="php_gdpr"><a href="php_gdpr.html">GDPR</a></li> | |
288 | ||
289 | ||
290 | ||
291 | ||
292 | ||
293 | </ul> | |
294 | </li> | |
295 | ||
296 | <li> | |
297 | <a href="#">Languages, Templates & CSS</a> | |
298 | <ul> | |
299 | ||
300 | ||
301 | ||
302 | ||
303 | <li data-identifier="view_languages"><a href="view_languages.html">Languages</a></li> | |
304 | ||
305 | ||
306 | ||
307 | ||
308 | ||
309 | ||
310 | ||
311 | ||
312 | <li data-identifier="view_templates"><a href="view_templates.html">Templates</a></li> | |
313 | ||
314 | ||
315 | ||
316 | ||
317 | ||
318 | ||
319 | ||
320 | ||
321 | <li data-identifier="view_css"><a href="view_css.html">CSS</a></li> | |
322 | ||
323 | ||
324 | ||
325 | ||
326 | ||
327 | </ul> | |
328 | </li> | |
329 | ||
330 | <li> | |
331 | <a href="#">JavaScript API</a> | |
332 | <ul> | |
333 | ||
334 | ||
335 | ||
336 | ||
337 | <li data-identifier="javascript_general-usage"><a href="javascript_general-usage.html">General Usage</a></li> | |
338 | ||
339 | ||
340 | ||
341 | ||
342 | ||
343 | ||
344 | ||
345 | ||
346 | <li class="subfolders"> | |
347 | <a href="#">New API</a> | |
348 | <ul> | |
349 | ||
350 | ||
351 | ||
352 | <li data-identifier="javascript_new-api_writing-a-module"><a href="javascript_new-api_writing-a-module.html">Writing a module</a></li> | |
353 | ||
354 | ||
355 | ||
356 | ||
357 | <li data-identifier="javascript_new-api_data-structures"><a href="javascript_new-api_data-structures.html">Data Structures</a></li> | |
358 | ||
359 | ||
360 | ||
361 | ||
362 | <li data-identifier="javascript_new-api_core"><a href="javascript_new-api_core.html">Core Functions</a></li> | |
363 | ||
364 | ||
365 | ||
366 | ||
367 | <li data-identifier="javascript_new-api_dom"><a href="javascript_new-api_dom.html">DOM</a></li> | |
368 | ||
369 | ||
370 | ||
371 | ||
372 | <li data-identifier="javascript_new-api_events"><a href="javascript_new-api_events.html">Event Handling</a></li> | |
373 | ||
374 | ||
375 | ||
376 | ||
377 | <li data-identifier="javascript_new-api_ajax"><a href="javascript_new-api_ajax.html">Ajax</a></li> | |
378 | ||
379 | ||
380 | ||
381 | ||
382 | <li data-identifier="javascript_new-api_dialogs"><a href="javascript_new-api_dialogs.html">Dialogs</a></li> | |
383 | ||
384 | ||
385 | ||
386 | ||
387 | <li data-identifier="javascript_new-api_browser"><a href="javascript_new-api_browser.html">Browser and Screen Sizes</a></li> | |
388 | ||
389 | ||
390 | ||
391 | ||
392 | <li data-identifier="javascript_new-api_ui"><a href="javascript_new-api_ui.html">User Interface</a></li> | |
393 | ||
394 | ||
395 | </ul> | |
396 | </li> | |
397 | ||
398 | ||
399 | ||
400 | ||
401 | ||
402 | <li data-identifier="javascript_legacy-api"><a href="javascript_legacy-api.html">Legacy API</a></li> | |
403 | ||
404 | ||
405 | ||
406 | ||
407 | ||
408 | ||
409 | ||
410 | ||
411 | <li data-identifier="javascript_helper-functions"><a href="javascript_helper-functions.html">Helper Functions</a></li> | |
412 | ||
413 | ||
414 | ||
415 | ||
416 | ||
417 | ||
418 | ||
419 | ||
420 | <li data-identifier="javascript_code-snippets"><a href="javascript_code-snippets.html">Code Snippets</a></li> | |
421 | ||
422 | ||
423 | ||
424 | ||
425 | ||
426 | </ul> | |
427 | </li> | |
428 | ||
429 | <li> | |
430 | <a href="#">Package Components</a> | |
431 | <ul> | |
432 | ||
433 | ||
434 | ||
435 | ||
436 | <li data-identifier="package_package-xml"><a href="package_package-xml.html">package.xml</a></li> | |
437 | ||
438 | ||
439 | ||
440 | ||
441 | ||
442 | ||
443 | ||
444 | ||
445 | <li data-identifier="package_pip"><a href="package_pip.html">PIPs</a></li> | |
446 | ||
447 | ||
448 | ||
449 | ||
450 | ||
451 | </ul> | |
452 | </li> | |
453 | ||
454 | <li> | |
455 | <a href="#">Migration</a> | |
456 | <ul> | |
457 | ||
458 | ||
459 | ||
460 | ||
461 | <li class="subfolders"> | |
462 | <a href="#">Migrating from WSC 5.2</a> | |
463 | <ul> | |
464 | ||
465 | ||
466 | ||
467 | <li data-identifier="migration_wsc-52_php"><a href="migration_wsc-52_php.html">PHP API</a></li> | |
468 | ||
469 | ||
470 | ||
471 | ||
472 | <li data-identifier="migration_wsc-52_templates"><a href="migration_wsc-52_templates.html">Templates and Languages</a></li> | |
473 | ||
474 | ||
475 | ||
476 | ||
477 | <li data-identifier="migration_wsc-52_libraries"><a href="migration_wsc-52_libraries.html">Third Party Libraries</a></li> | |
478 | ||
479 | ||
480 | </ul> | |
481 | </li> | |
482 | ||
483 | <li class="subfolders"> | |
484 | <a href="#">Migrating from WSC 3.1</a> | |
485 | <ul> | |
486 | ||
487 | ||
488 | ||
489 | <li data-identifier="migration_wsc-31_php"><a href="migration_wsc-31_php.html">PHP API</a></li> | |
490 | ||
491 | ||
492 | </ul> | |
493 | </li> | |
494 | ||
495 | <li class="subfolders"> | |
496 | <a href="#">Migrating from WSC 3.0</a> | |
497 | <ul> | |
498 | ||
499 | ||
500 | ||
501 | <li data-identifier="migration_wsc-30_php"><a href="migration_wsc-30_php.html">PHP API</a></li> | |
502 | ||
503 | ||
504 | ||
505 | ||
506 | <li data-identifier="migration_wsc-30_javascript"><a href="migration_wsc-30_javascript.html">JavaScript API</a></li> | |
507 | ||
508 | ||
509 | ||
510 | ||
511 | <li data-identifier="migration_wsc-30_templates"><a href="migration_wsc-30_templates.html">Templates</a></li> | |
512 | ||
513 | ||
514 | ||
515 | ||
516 | <li data-identifier="migration_wsc-30_css"><a href="migration_wsc-30_css.html">CSS</a></li> | |
517 | ||
518 | ||
519 | ||
520 | ||
521 | <li data-identifier="migration_wsc-30_package"><a href="migration_wsc-30_package.html">Package Components</a></li> | |
522 | ||
523 | ||
524 | </ul> | |
525 | </li> | |
526 | ||
527 | <li class="subfolders"> | |
528 | <a href="#">Migrating from WCF 2.1</a> | |
529 | <ul> | |
530 | ||
531 | ||
532 | ||
533 | <li data-identifier="migration_wcf-21_php"><a href="migration_wcf-21_php.html">PHP API</a></li> | |
534 | ||
535 | ||
536 | ||
537 | ||
538 | <li data-identifier="migration_wcf-21_templates"><a href="migration_wcf-21_templates.html">Templates</a></li> | |
539 | ||
540 | ||
541 | ||
542 | ||
543 | <li data-identifier="migration_wcf-21_css"><a href="migration_wcf-21_css.html">CSS</a></li> | |
544 | ||
545 | ||
546 | ||
547 | ||
548 | <li data-identifier="migration_wcf-21_package"><a href="migration_wcf-21_package.html">Package Components</a></li> | |
549 | ||
550 | ||
551 | </ul> | |
552 | </li> | |
553 | ||
554 | ||
555 | </ul> | |
556 | </li> | |
557 | ||
558 | <li> | |
559 | <a href="#">Tutorials</a> | |
560 | <ul> | |
561 | ||
562 | ||
563 | ||
564 | ||
565 | <li data-identifier="tutorial_tutorial-series"><a href="tutorial_tutorial-series.html">Tutorial Series</a></li> | |
566 | ||
567 | ||
568 | ||
569 | ||
570 | ||
571 | </ul> | |
572 | </li> | |
573 | ||
574 | ||
575 | </ul> | |
576 | ||
577 | <script> | |
578 | (function() { | |
579 | var sidebar = $('#mysidebar'); | |
580 | var item = sidebar.find('.active'); | |
581 | if (item.length === 0) { | |
582 | var parent = ''; | |
583 | if (parent) { | |
584 | sidebar.find('li[data-identifier="' + parent + '"]').addClass('active'); | |
585 | } | |
586 | } | |
587 | ||
588 | sidebar.find(".active").parents('li').toggleClass("active"); | |
589 | })(); | |
590 | </script> | |
591 | ||
592 | </div> | |
593 | ||
594 | <div class="col-md-9"> | |
595 | <div class="post-header"> | |
596 | <h1 class="post-title-main">Database Access</h1> | |
597 | </div> | |
598 | ||
599 | ||
600 | ||
601 | <div class="post-content"> | |
602 | ||
603 | ||
604 | ||
605 | ||
606 | ||
607 | <!-- this handles the automatic toc. use ## for subheads to auto-generate the on-page minitoc. if you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc. --> | |
608 | <script> | |
609 | $( document ).ready(function() { | |
610 | // Handler for .ready() called. | |
611 | ||
612 | $('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2,h3,h4' }); | |
613 | ||
614 | /* this offset helps account for the space taken up by the floating toolbar. */ | |
615 | $('#toc').on('click', 'a', function() { | |
616 | var target = $(this.getAttribute('href')) | |
617 | , scroll_target = target.offset().top | |
618 | ||
619 | $(window).scrollTop(scroll_target - 10); | |
620 | return false | |
621 | }) | |
622 | ||
623 | }); | |
624 | </script> | |
625 | ||
626 | <div id="toc"></div> | |
627 | ||
628 | ||
629 | ||
630 | <p><a href="php_database-objects.html">Database Objects</a> provide a convenient and object-oriented approach to work with the database, but there can be use-cases that require raw access including writing methods for model classes. This section assumes that you have either used <a href="https://en.wikipedia.org/wiki/Prepared_statement">prepared statements</a> before or at least understand how it works.</p> | |
631 | ||
632 | <h2 id="the-preparedstatement-object">The PreparedStatement Object</h2> | |
633 | ||
634 | <p>The database access is designed around <a href="https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php">PreparedStatement</a>, built on top of PHP’s <code class="language-plaintext highlighter-rouge">PDOStatement</code> so that you call all of <code class="language-plaintext highlighter-rouge">PDOStatement</code>’s methods, and each query requires you to obtain a statement object.</p> | |
635 | ||
636 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
637 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="s2">"SELECT * FROM wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example"</span><span class="p">);</span> | |
638 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">();</span> | |
639 | <span class="k">while</span> <span class="p">(</span><span class="nv">$row</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchArray</span><span class="p">())</span> <span class="p">{</span> | |
640 | <span class="c1">// handle result</span> | |
641 | <span class="p">}</span> | |
642 | </code></pre></div></div> | |
643 | ||
644 | <h3 id="query-parameters">Query Parameters</h3> | |
645 | ||
646 | <p>The example below illustrates the usage of parameters where each value is replaced with the generic <code class="language-plaintext highlighter-rouge">?</code>-placeholder. Values are provided by calling <code class="language-plaintext highlighter-rouge">$statement->execute()</code> with a continuous, one-dimensional array that exactly match the number of question marks.</p> | |
647 | ||
648 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
649 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"SELECT * | |
650 | FROM wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example | |
651 | WHERE exampleID = ? | |
652 | OR bar IN (?, ?, ?, ?, ?)"</span><span class="p">;</span> | |
653 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span> | |
654 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">([</span> | |
655 | <span class="nv">$exampleID</span><span class="p">,</span> | |
656 | <span class="nv">$list</span><span class="p">,</span> <span class="nv">$of</span><span class="p">,</span> <span class="nv">$values</span><span class="p">,</span> <span class="nv">$for</span><span class="p">,</span> <span class="nv">$bar</span> | |
657 | <span class="p">]);</span> | |
658 | <span class="k">while</span> <span class="p">(</span><span class="nv">$row</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchArray</span><span class="p">())</span> <span class="p">{</span> | |
659 | <span class="c1">// handle result</span> | |
660 | <span class="p">}</span> | |
661 | </code></pre></div></div> | |
662 | ||
663 | <h3 id="fetching-a-single-result">Fetching a Single Result</h3> | |
664 | ||
665 | <div class="bs-callout bs-callout-danger">Do not attempt to use <code class="language-plaintext highlighter-rouge">fetchSingleRow()</code> or <code class="language-plaintext highlighter-rouge">fetchSingleColumn()</code> if the result contains more than one row.</div> | |
666 | ||
667 | <p>You can opt-in to retrieve only a single row from database and make use of shortcut methods to reduce the code that you have to write.</p> | |
668 | ||
669 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
670 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"SELECT * | |
671 | FROM wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example | |
672 | WHERE exampleID = ?"</span><span class="p">;</span> | |
673 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> | |
674 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">([</span><span class="nv">$exampleID</span><span class="p">]);</span> | |
675 | <span class="nv">$row</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchSingleRow</span><span class="p">();</span> | |
676 | </code></pre></div></div> | |
677 | ||
678 | <p>There are two distinct differences when comparing with the example on query parameters above:</p> | |
679 | ||
680 | <ol> | |
681 | <li>The method <code class="language-plaintext highlighter-rouge">prepareStatement()</code> receives a secondary parameter that will be appended to the query as <code class="language-plaintext highlighter-rouge">LIMIT 1</code>.</li> | |
682 | <li>Data is read using <code class="language-plaintext highlighter-rouge">fetchSingleRow()</code> instead of <code class="language-plaintext highlighter-rouge">fetchArray()</code> or similar methods, that will read one result and close the cursor.</li> | |
683 | </ol> | |
684 | ||
685 | <h3 id="fetch-by-column">Fetch by Column</h3> | |
686 | ||
687 | <div class="bs-callout bs-callout-warning">There is no way to return another column from the same row if you use <code class="language-plaintext highlighter-rouge">fetchColumn()</code> to retrieve data.</div> | |
688 | ||
689 | <p>Fetching an array is only useful if there is going to be more than one column per result row, otherwise accessing the column directly is much more convenient and increases the code readability.</p> | |
690 | ||
691 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
692 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"SELECT bar | |
693 | FROM wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example"</span><span class="p">;</span> | |
694 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span> | |
695 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">();</span> | |
696 | <span class="k">while</span> <span class="p">(</span><span class="nv">$bar</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchColumn</span><span class="p">())</span> <span class="p">{</span> | |
697 | <span class="c1">// handle result</span> | |
698 | <span class="p">}</span> | |
699 | <span class="nv">$bar</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchSingleColumn</span><span class="p">();</span> | |
700 | </code></pre></div></div> | |
701 | ||
702 | <p>Similar to fetching a single row, you can also issue a query that will select a single row, but reads only one column from the result row.</p> | |
703 | ||
704 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
705 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"SELECT bar | |
706 | FROM wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example | |
707 | WHERE exampleID = ?"</span><span class="p">;</span> | |
708 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> | |
709 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">([</span><span class="nv">$exampleID</span><span class="p">]);</span> | |
710 | <span class="nv">$bar</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchSingleColumn</span><span class="p">();</span> | |
711 | </code></pre></div></div> | |
712 | ||
713 | <h3 id="fetching-all-results">Fetching All Results</h3> | |
714 | ||
715 | <p>If you want to fetch all results of a query but only store them in an array without directly processing them, in most cases, you can rely on built-in methods.</p> | |
716 | ||
717 | <p>To fetch all rows of query, you can use <code class="language-plaintext highlighter-rouge">PDOStatement::fetchAll()</code> with <code class="language-plaintext highlighter-rouge">\PDO::FETCH_ASSOC</code> as the first parameter:</p> | |
718 | ||
719 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
720 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"SELECT * | |
721 | FROM wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example"</span><span class="p">;</span> | |
722 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span> | |
723 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">();</span> | |
724 | <span class="nv">$rows</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchAll</span><span class="p">(</span><span class="nx">\PDO</span><span class="o">::</span><span class="na">FETCH_ASSOC</span><span class="p">);</span> | |
725 | </code></pre></div></div> | |
726 | ||
727 | <p>As a result, you get an array containing associative arrays with the rows of the <code class="language-plaintext highlighter-rouge">wcf{WCF_N}_example</code> database table as content.</p> | |
728 | ||
729 | <p>If you only want to fetch a list of the values of a certain column, you can use <code class="language-plaintext highlighter-rouge">\PDO::FETCH_COLUMN</code> as the first parameter:</p> | |
730 | ||
731 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
732 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"SELECT exampleID | |
733 | FROM wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example"</span><span class="p">;</span> | |
734 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span> | |
735 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">();</span> | |
736 | <span class="nv">$exampleIDs</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchAll</span><span class="p">(</span><span class="nx">\PDO</span><span class="o">::</span><span class="na">FETCH_COLUMN</span><span class="p">);</span> | |
737 | </code></pre></div></div> | |
738 | ||
739 | <p>As a result, you get an array with all <code class="language-plaintext highlighter-rouge">exampleID</code> values.</p> | |
740 | ||
741 | <p>The <code class="language-plaintext highlighter-rouge">PreparedStatement</code> class adds an additional methods that covers another common use case in our code: | |
742 | Fetching two columns and using the first column’s value as the array key and the second column’s value as the array value. | |
743 | This case is covered by <code class="language-plaintext highlighter-rouge">PreparedStatement::fetchMap()</code>:</p> | |
744 | ||
745 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
746 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"SELECT exampleID, userID | |
747 | FROM wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example_mapping"</span><span class="p">;</span> | |
748 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span> | |
749 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">();</span> | |
750 | <span class="nv">$map</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchMap</span><span class="p">(</span><span class="s1">'exampleID'</span><span class="p">,</span> <span class="s1">'userID'</span><span class="p">);</span> | |
751 | </code></pre></div></div> | |
752 | ||
753 | <p><code class="language-plaintext highlighter-rouge">$map</code> is a one-dimensional array where each <code class="language-plaintext highlighter-rouge">exampleID</code> value maps to the corresponding <code class="language-plaintext highlighter-rouge">userID</code> value.</p> | |
754 | ||
755 | <div class="bs-callout bs-callout-warning">If there are multiple entries for a certain <code class="language-plaintext highlighter-rouge">exampleID</code> value with different <code class="language-plaintext highlighter-rouge">userID</code> values, the existing entry in the array will be overwritten and contain the last read value from the database table. Therefore, this method should generally only be used for unique combinations.</div> | |
756 | ||
757 | <p>If you do not have a combination of columns with unique pairs of values, but you want to get a list of <code class="language-plaintext highlighter-rouge">userID</code> values with the same <code class="language-plaintext highlighter-rouge">exampleID</code>, you can set the third parameter of <code class="language-plaintext highlighter-rouge">fetchMap()</code> to <code class="language-plaintext highlighter-rouge">false</code> and get a list:</p> | |
758 | ||
759 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
760 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"SELECT exampleID, userID | |
761 | FROM wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example_mapping"</span><span class="p">;</span> | |
762 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span> | |
763 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">();</span> | |
764 | <span class="nv">$map</span> <span class="o">=</span> <span class="nv">$statement</span><span class="o">-></span><span class="na">fetchMap</span><span class="p">(</span><span class="s1">'exampleID'</span><span class="p">,</span> <span class="s1">'userID'</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span> | |
765 | </code></pre></div></div> | |
766 | ||
767 | <p>Now, as a result, you get a two-dimensional array with the array keys being the <code class="language-plaintext highlighter-rouge">exampleID</code> values and the array values being arrays with all <code class="language-plaintext highlighter-rouge">userID</code> values from rows with the respective <code class="language-plaintext highlighter-rouge">exampleID</code> value.</p> | |
768 | ||
769 | <h2 id="building-complex-conditions">Building Complex Conditions</h2> | |
770 | ||
771 | <p>Building conditional conditions can turn out to be a real mess and it gets even worse with SQL’s <code class="language-plaintext highlighter-rouge">IN (…)</code> which requires as many placeholders as there will be values. The solutions is <code class="language-plaintext highlighter-rouge">PreparedStatementConditionBuilder</code>, a simple but useful helper class with a bulky name, it is also the class used when accessing <code class="language-plaintext highlighter-rouge">DatabaseObjecList::getConditionBuilder()</code>.</p> | |
772 | ||
773 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
774 | <span class="nv">$conditions</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\wcf\system\database\util\PreparedStatementConditionBuilder</span><span class="p">();</span> | |
775 | <span class="nv">$conditions</span><span class="o">-></span><span class="na">add</span><span class="p">(</span><span class="s2">"exampleID = ?"</span><span class="p">,</span> <span class="p">[</span><span class="nv">$exampleID</span><span class="p">]);</span> | |
776 | <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">empty</span><span class="p">(</span><span class="nv">$valuesForBar</span><span class="p">))</span> <span class="p">{</span> | |
777 | <span class="nv">$conditions</span><span class="o">-></span><span class="na">add</span><span class="p">(</span><span class="s2">"(bar IN (?) OR baz = ?)"</span><span class="p">,</span> <span class="p">[</span><span class="nv">$valuesForBar</span><span class="p">,</span> <span class="nv">$baz</span><span class="p">]);</span> | |
778 | <span class="p">}</span> | |
779 | </code></pre></div></div> | |
780 | ||
781 | <p>The <code class="language-plaintext highlighter-rouge">IN (?)</code> in the example above is automatically expanded to match the number of items contained in <code class="language-plaintext highlighter-rouge">$valuesForBar</code>. Be aware that the method will generate an invalid query if <code class="language-plaintext highlighter-rouge">$valuesForBar</code> is empty!</p> | |
782 | ||
783 | <h2 id="insert-or-update-in-bulk">INSERT or UPDATE in Bulk</h2> | |
784 | ||
785 | <p>Prepared statements not only protect against SQL injection by separating the logical query and the actual data, but also provides the ability to reuse the same query with different values. This leads to a performance improvement as the code does not have to transmit the query with for every data set and only has to parse and analyze the query once.</p> | |
786 | ||
787 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
788 | <span class="nv">$data</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'abc'</span><span class="p">,</span> <span class="s1">'def'</span><span class="p">,</span> <span class="s1">'ghi'</span><span class="p">];</span> | |
789 | ||
790 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"INSERT INTO wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example | |
791 | (bar) | |
792 | VALUES (?)"</span><span class="p">;</span> | |
793 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span> | |
794 | ||
795 | <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">beginTransaction</span><span class="p">();</span> | |
796 | <span class="k">foreach</span> <span class="p">(</span><span class="nv">$data</span> <span class="k">as</span> <span class="nv">$bar</span><span class="p">)</span> <span class="p">{</span> | |
797 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">([</span><span class="nv">$bar</span><span class="p">]);</span> | |
798 | <span class="p">}</span> | |
799 | <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">commitTransaction</span><span class="p">();</span> | |
800 | </code></pre></div></div> | |
801 | ||
802 | <p>It is generally advised to wrap bulk operations in a transaction as it allows the database to optimize the process, including fewer I/O operations.</p> | |
803 | ||
804 | <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> | |
805 | <span class="nv">$data</span> <span class="o">=</span> <span class="p">[</span> | |
806 | <span class="mi">1</span> <span class="o">=></span> <span class="s1">'abc'</span><span class="p">,</span> | |
807 | <span class="mi">3</span> <span class="o">=></span> <span class="s1">'def'</span><span class="p">,</span> | |
808 | <span class="mi">4</span> <span class="o">=></span> <span class="s1">'ghi'</span> | |
809 | <span class="p">];</span> | |
810 | ||
811 | <span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"UPDATE wcf"</span><span class="o">.</span><span class="nx">WCF_N</span><span class="o">.</span><span class="s2">"_example | |
812 | SET bar = ? | |
813 | WHERE exampleID = ?"</span><span class="p">;</span> | |
814 | <span class="nv">$statement</span> <span class="o">=</span> <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">prepareStatement</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span> | |
815 | ||
816 | <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">beginTransaction</span><span class="p">();</span> | |
817 | <span class="k">foreach</span> <span class="p">(</span><span class="nv">$data</span> <span class="k">as</span> <span class="nv">$exampleID</span> <span class="o">=></span> <span class="nv">$bar</span><span class="p">)</span> <span class="p">{</span> | |
818 | <span class="nv">$statement</span><span class="o">-></span><span class="na">execute</span><span class="p">([</span> | |
819 | <span class="nv">$bar</span><span class="p">,</span> | |
820 | <span class="nv">$exampleID</span> | |
821 | <span class="p">]);</span> | |
822 | <span class="p">}</span> | |
823 | <span class="nx">\wcf\system\WCF</span><span class="o">::</span><span class="na">getDB</span><span class="p">()</span><span class="o">-></span><span class="na">commitTransaction</span><span class="p">();</span> | |
824 | </code></pre></div></div> | |
825 | ||
826 | ||
827 | ||
828 | <div class="tags"> | |
829 | ||
830 | </div> | |
831 | ||
832 | ||
833 | ||
834 | </div> | |
835 | ||
836 | </div> | |
837 | </div> | |
838 | </div> | |
839 | ||
840 | <div class="footerBox"> | |
841 | <div class="container"> | |
842 | <div class="footerBoxLeft"> | |
843 | ||
844 | <a target="_blank" href="https://github.com/woltlab/woltlab.github.io/blob/master/pages/php/php_database-access.md" class="btn btn-default githubEditButton no_icon" role="button"><i class="fa fa-github fa-lg"></i> Edit on GitHub</a> | |
e2f8eee7 | 845 | <p>Site last generated: Mar 5, 2021</p> |
d9cdc0cc TD |
846 | </div> |
847 | <div class="footerBoxRight"> | |
e2f8eee7 | 848 | <a class="no_icon" href="https://www.woltlab.com"><img src="https://docs.woltlab.com/5.3/images/woltlab-black.png" srcset="https://docs.woltlab.com/5.3/images/woltlab-black@2x.png 2x" height="40" width="204" alt=""></a> |
d9cdc0cc TD |
849 | </div> |
850 | </div> | |
851 | </div> | |
852 | ||
853 | <div class="pageFooter"> | |
854 | <div class="container"> | |
855 | © 2001 ‐ 2021 <a class="no_icon" href="https://www.woltlab.com">WoltLab GmbH</a>. All rights reserved. | <a class="no_icon" href="https://www.woltlab.com/legal-notice/">Legal Notice</a> | <a class="no_icon" href="https://www.woltlab.com/privacy-policy/">Privacy Policy</a> | |
856 | </div> | |
857 | </div> | |
858 | </body> | |
859 | ||
860 | </html> |