Deployed 2f7be76 to 5.4 with MkDocs 1.1.2 and mike 0.5.5
[GitHub/WoltLab/woltlab.github.io.git] / 5.3 / php_database-access.html
CommitLineData
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">&nbsp;<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">&nbsp;</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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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-&gt;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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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:
742Fetching two columns and using the first column’s value as the array key and the second column’s value as the array value.
743This 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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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">&lt;?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">-&gt;</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">-&gt;</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">&lt;?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">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</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">&lt;?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">=&gt;</span> <span class="s1">'abc'</span><span class="p">,</span>
807 <span class="mi">3</span> <span class="o">=&gt;</span> <span class="s1">'def'</span><span class="p">,</span>
808 <span class="mi">4</span> <span class="o">=&gt;</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">-&gt;</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">-&gt;</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">=&gt;</span> <span class="nv">$bar</span><span class="p">)</span> <span class="p">{</span>
818 <span class="nv">$statement</span><span class="o">-&gt;</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">-&gt;</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 &copy; 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>