-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
1900 lines (1776 loc) · 179 KB
/
Copy pathindex.html
File metadata and controls
1900 lines (1776 loc) · 179 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modern PHP 8.x Masterclass — Complete Guide</title>
<meta name="description" content="A comprehensive, modern guide to PHP 8.x programming from core fundamentals to enterprise engineering and production deployment.">
<link rel="canonical" href="https://azhar25git.github.io/php8-tutorial/">
<link rel="icon" href="favicon.ico" type="image/x-icon">
<!-- Search engine metadata -->
<meta name="robots" content="index, follow, max-image-preview:large">
<meta name="author" content="Azhar Uddin">
<meta name="date" content="2026-06-28">
<meta name="keywords" content="PHP 8, PHP 8.x, PHP tutorial, modern PHP, PHP guide, PHP programming, PHP-FPM, Composer, PHPUnit, PDO, web development">
<meta name="theme-color" content="#4c1d95" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#1b1f24" media="(prefers-color-scheme: dark)">
<!-- Open Graph -->
<meta property="og:title" content="Modern PHP 8.x Masterclass — Complete Guide">
<meta property="og:description" content="A comprehensive, modern guide to PHP 8.x programming from core fundamentals to enterprise engineering and production deployment.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://azhar25git.github.io/php8-tutorial/">
<meta property="og:site_name" content="Modern PHP 8.x Masterclass">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://azhar25git.github.io/php8-tutorial/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Modern PHP 8.x Masterclass branding">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Modern PHP 8.x Masterclass — Complete Guide">
<meta name="twitter:description" content="A comprehensive, modern guide to PHP 8.x programming from core fundamentals to enterprise engineering and production deployment.">
<meta name="twitter:image" content="https://azhar25git.github.io/php8-tutorial/og-image.png">
<meta name="twitter:image:alt" content="Modern PHP 8.x Masterclass branding">
<!-- Structured data -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "TechArticle",
"headline": "Modern PHP 8.x Masterclass — Complete Guide",
"url": "https://azhar25git.github.io/php8-tutorial/",
"description": "A comprehensive, modern guide to PHP 8.x programming from core fundamentals to enterprise engineering and production deployment.",
"author": {
"@type": "Person",
"name": "Azhar Uddin",
"url": "https://github.com/azhar25git"
},
"datePublished": "2026-06-28",
"publisher": {
"@type": "Person",
"name": "Azhar Uddin",
"url": "https://github.com/azhar25git"
}
}
</script>
<script>
(function () {
const stored = localStorage.getItem('php-guide-dark-mode');
const dark = stored ? stored === 'dark' : window.matchMedia('(prefers-color-scheme: dark)').matches;
if (dark) document.documentElement.classList.add('dark');
})();
</script>
<script src="https://cdn.tailwindcss.com"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.3/dist/cdn.min.js"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
github: {
50: '#f6f8fa', 100: '#eaeef2', 200: '#d0d7de', 300: '#afb8c1',
400: '#8c959f', 500: '#6e7781', 600: '#57606a', 700: '#424a53',
800: '#32383f', 900: '#24292f', 950: '#1b1f24',
},
php: {
50: '#f5f3ff', 100: '#ede9fe', 200: '#ddd6fe', 300: '#c4b5fd',
400: '#a78bfa', 500: '#8b5cf6', 600: '#7c3aed', 700: '#6d28d9',
800: '#5b21b6', 900: '#4c1d95',
}
},
fontFamily: {
sans: ['-apple-system','BlinkMacSystemFont','Segoe UI','Noto Sans','Helvetica','Arial','sans-serif'],
mono: ['SFMono-Regular','Consolas','Liberation Mono','Menlo','Courier','monospace'],
}
}
}
}
</script>
<style>
[x-cloak] { display: none !important; }
@media (min-width: 1024px) { aside[x-cloak] { display: block !important; } }
html { scroll-behavior: smooth; scroll-padding-top: 5rem; }
.prose h1, .prose h2, .prose h3, .prose h4 { scroll-margin-top: 5rem; }
.code-block { counter-reset: line; }
.line { display: block; padding-left: 1rem; }
.line::before { counter-increment: line; content: counter(line); display: inline-block; width: 2rem; margin-left: -1rem; margin-right: 0.5rem; text-align: right; color: #6e7781; user-select: none; }
.custom-scroll::-webkit-scrollbar { width: 8px; }
.custom-scroll::-webkit-scrollbar-track { background: transparent; }
.custom-scroll::-webkit-scrollbar-thumb { background: #d0d7de; border-radius: 4px; }
.custom-scroll::-webkit-scrollbar-thumb:hover { background: #afb8c1; }
.dark .line::before { color: #8c959f; }
.dark ::-webkit-scrollbar-thumb { background: #424a53; }
.dark ::-webkit-scrollbar-thumb:hover { background: #57606a; }
</style>
</head>
<body class="bg-white text-github-900 antialiased transition-colors duration-200 dark:bg-github-950 dark:text-github-100" x-data="phpGuide()" x-init="init()">
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:rounded-md focus:bg-php-600 focus:px-4 focus:py-2 focus:text-white">Skip to content</a>
<header class="fixed top-0 left-0 right-0 z-50 border-b border-github-200 bg-white/95 backdrop-blur transition-colors duration-200 dark:border-github-800 dark:bg-github-900/95">
<div class="flex h-16 items-center justify-between px-4 lg:px-8">
<div class="flex items-center gap-3">
<button @click="sidebarOpen = !sidebarOpen" class="lg:hidden -ml-2 p-2 rounded-md hover:bg-github-100 dark:hover:bg-github-800" aria-label="Toggle navigation">
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/></svg>
</button>
<a href="#" class="flex items-center gap-2 text-base sm:text-lg font-semibold text-github-900 hover:text-php-600 dark:text-github-100 dark:hover:text-php-400">
<span class="flex h-7 w-7 sm:h-8 sm:w-8 items-center justify-center rounded-lg bg-php-600 text-white font-bold text-xs sm:text-sm">PHP</span>
<span class="hidden sm:inline">Modern PHP 8.x Masterclass</span>
<span class="sm:hidden">PHP Guide</span>
</a>
</div>
<div class="flex items-center gap-3 sm:gap-6 text-sm">
<div class="hidden md:flex items-center gap-4 text-github-600 dark:text-github-400">
<span class="font-mono text-xs bg-github-100 dark:bg-github-800 px-2 py-1 rounded">32 Topics</span>
<span class="font-mono text-xs bg-github-100 dark:bg-github-800 px-2 py-1 rounded">9 Modules</span>
<a href="https://www.php.net/" target="_blank" rel="noopener" class="hover:text-github-900 dark:hover:text-github-200">php.net ↗</a>
<a href="https://github.com/azhar25git/php8-tutorial" target="_blank" rel="noopener" class="inline-flex items-center">
<img src="https://img.shields.io/github/stars/azhar25git/php8-tutorial?style=social" alt="Star azhar25git/php8-tutorial on GitHub" class="h-6 w-auto">
</a>
<a href="https://hits.sh/azhar25git.github.io/php8-tutorial/" target="_blank" rel="noopener" class="inline-flex items-center">
<img src="https://hits.sh/azhar25git.github.io/php8-tutorial.svg?style=social&label=Hits" alt="Page hits" class="h-6 w-auto">
</a>
</div>
<button @click="toggleDarkMode()" class="p-2 rounded-md hover:bg-github-100 dark:hover:bg-github-800" :aria-label="darkMode ? 'Switch to light mode' : 'Switch to dark mode'">
<svg x-show="!darkMode" class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>
<svg x-show="darkMode" class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg>
</button>
</div>
</div>
</header>
<div class="flex min-h-screen pt-16">
<aside x-cloak class="fixed top-16 bottom-0 left-0 z-40 w-72 transform border-r border-github-200 bg-github-50 transition-transform duration-200 ease-in-out lg:translate-x-0 overflow-y-auto custom-scroll dark:border-github-800 dark:bg-github-900"
:class="sidebarOpen ? 'translate-x-0' : '-translate-x-full'">
<nav class="px-4 py-6" aria-label="Guide navigation">
<template x-for="(part, partIndex) in parts" :key="'part-' + partIndex">
<div class="mb-6">
<h3 class="mb-2 px-2 text-xs font-semibold uppercase tracking-wider text-github-500 dark:text-github-400" x-text="part.title"></h3>
<template x-for="(module, moduleIndex) in part.modules" :key="'module-' + module.id">
<div class="mb-3">
<button @click="toggleModule(module.id)"
class="flex w-full items-center justify-between rounded-md px-2 py-1.5 text-left text-sm font-semibold text-github-700 hover:bg-github-100 hover:text-github-900 dark:text-github-300 dark:hover:bg-github-800 dark:hover:text-github-100"
:aria-expanded="isModuleOpen(module.id)">
<span x-text="module.title"></span>
<svg class="mt-0.5 h-4 w-4 shrink-0 self-start transition-transform" :class="isModuleOpen(module.id) ? 'rotate-180' : ''" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</button>
<div x-show="isModuleOpen(module.id)" class="mt-1 space-y-0.5">
<template x-for="topic in module.topics" :key="topic.id">
<a :href="'#' + topic.id" @click.prevent="window.location.hash = topic.id; if (window.innerWidth < 1024) sidebarOpen = false"
class="block rounded-md py-1.5 pl-2 pr-3 text-sm transition-colors border-l-4"
:class="activeTopic === topic.id ? 'bg-php-100 text-php-900 font-medium border-php-600 dark:bg-php-900/30 dark:text-php-300' : 'text-github-600 hover:bg-github-100 hover:text-github-900 border-transparent dark:text-github-400 dark:hover:bg-github-800 dark:hover:text-github-200'"
:aria-current="activeTopic === topic.id ? 'page' : false"
x-text="topic.number + '. ' + topic.title"></a>
</template>
</div>
</div>
</template>
</div>
</template>
</nav>
</aside>
<div x-show="sidebarOpen" class="fixed inset-0 z-30 bg-black/30 lg:hidden" @click="sidebarOpen = false" x-transition.opacity></div>
<main id="main-content" class="flex-1 min-w-0 lg:ml-72">
<div class="mx-auto max-w-4xl px-4 py-8 sm:px-6 sm:py-10 lg:px-12">
<article class="max-w-none">
<!-- Hero shown only on first module -->
<div x-show="activeModule === 'module-1'" x-cloak class="mb-8 sm:mb-12 border-b border-github-200 pb-6 sm:pb-8 dark:border-github-800" id="guide-start">
<h1 class="text-3xl sm:text-4xl lg:text-5xl font-bold tracking-tight text-github-900 dark:text-github-100 mb-4">Modern PHP 8.x Masterclass</h1>
<p class="text-lg sm:text-xl text-github-600 dark:text-github-400 leading-relaxed">A definitive guide to PHP programming from core interpreter fundamentals to enterprise engineering and high-performance deployment. Every topic is presented through the lens of <strong>Modern PHP</strong>, with idiomatic PHP 8+ code, legacy contrast, and explicit anti-pattern corrections.</p>
<div class="mt-6 flex flex-wrap gap-2">
<span class="inline-flex items-center rounded-full bg-php-50 px-3 py-1 text-xs font-medium text-php-700 ring-1 ring-inset ring-php-700/10 dark:bg-php-900/20 dark:text-php-300 dark:ring-php-500/20">PHP 8.x</span>
<span class="inline-flex items-center rounded-full bg-github-50 px-3 py-1 text-xs font-medium text-github-600 ring-1 ring-inset ring-github-500/10 dark:bg-github-800 dark:text-github-300 dark:ring-github-500/20">PSR-12 / PER</span>
<span class="inline-flex items-center rounded-full bg-github-50 px-3 py-1 text-xs font-medium text-github-600 ring-1 ring-inset ring-github-500/10 dark:bg-github-800 dark:text-github-300 dark:ring-github-500/20">Security First</span>
<span class="inline-flex items-center rounded-full bg-github-50 px-3 py-1 text-xs font-medium text-github-600 ring-1 ring-inset ring-github-500/10 dark:bg-github-800 dark:text-github-300 dark:ring-github-500/20">Production Ready</span>
</div>
<p class="mt-5 text-sm text-github-600 dark:text-github-400">If this guide helps you, please <a href="https://github.com/azhar25git/php8-tutorial" target="_blank" rel="noopener" class="font-medium text-php-600 hover:text-php-700 dark:text-php-400 dark:hover:text-php-300 underline underline-offset-2">star the project on GitHub</a> — it helps others find it.</p>
</div>
<!-- Compact module header -->
<div class="mb-8 sm:mb-10">
<template x-for="part in parts" :key="part.title">
<div>
<template x-for="module in part.modules" :key="module.id">
<div x-show="activeModule === module.id" x-cloak>
<span class="text-xs font-bold uppercase tracking-wider text-php-600 dark:text-php-400" x-text="part.title"></span>
<h2 class="text-2xl sm:text-3xl font-bold text-github-900 dark:text-github-100 mt-1" x-text="module.title"></h2>
<p class="mt-2 text-sm text-github-500 dark:text-github-400">
<span x-text="module.topics.length"></span> topics
</p>
</div>
</template>
</div>
</template>
</div>
<section id="part-1" class="mb-16">
<div class="mb-12" id="module-1" x-show="activeModule === 'module-1'" x-cloak>
<div class="mb-10" id="topic-1">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">1</span> The Modern PHP Ecosystem</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP is no longer a simple CGI script runner. In production, it runs primarily as <strong>PHP-FPM</strong> (FastCGI Process Manager) behind a reverse proxy such as nginx or Apache. The <strong>CLI SAPI</strong> handles cron jobs, queues, migrations, and local development. PHP 8.x also ships a <strong>built-in development server</strong> (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">php -S localhost:8000</code>) which is useful only for local prototyping — never expose it to untrusted networks.</p>
<p>The Zend Engine compiles PHP source into <strong>opcodes</strong>, executes them in a request lifecycle, and destroys the request-bound state at the end of every HTTP request. This <strong>shared-nothing architecture</strong> is PHP's superpower for horizontal scaling and isolation, but it also means the developer must explicitly persist state via sessions, cookies, databases, or caches.</p>
<p>Modern <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">php.ini</code> configuration is security-critical: disable dangerous functions, set sane upload limits, enforce <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">expose_php = Off</code>, configure OPcache in production, and keep error display disabled on public-facing servers.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800">
<span class="text-github-300 font-mono text-xs">php.ini — production baseline</span>
<button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button>
</div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line">; Hide PHP version from response headers</span>
<span class="line">expose_php = Off</span>
<span class="line"></span>
<span class="line">; Do not show errors to users in production</span>
<span class="line">display_errors = Off</span>
<span class="line">log_errors = On</span>
<span class="line">error_log = /var/log/php/error.log</span>
<span class="line"></span>
<span class="line">; Sane resource limits</span>
<span class="line">memory_limit = 256M</span>
<span class="line">upload_max_filesize = 10M</span>
<span class="line">post_max_size = 12M</span>
<span class="line">max_execution_time = 30</span>
<span class="line"></span>
<span class="line">; OPcache — mandatory in production</span>
<span class="line">opcache.enable = 1</span>
<span class="line">opcache.memory_consumption = 256</span>
<span class="line">opcache.max_accelerated_files = 10000</span>
<span class="line">opcache.validate_timestamps = 0 ; Set 1 only in development</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Using the built-in server in production:</strong> It is single-threaded, has no process manager, and is trivial to crash. Use PHP-FPM behind nginx/Apache.</li>
<li><strong>Leaving <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">display_errors = On</code> in production:</strong> Stack traces leak paths and internals. Log server-side, return generic messages.</li>
<li><strong>Editing code directly on shared hosting without version control:</strong> Modern PHP projects live in Git, use Composer, and deploy through CI/CD pipelines.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-2">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">2</span> Variables, Scope, & Dynamic Typing</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP variables are declared with a leading <strong><code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$</code></strong> sigil and are dynamically typed by default. The Zend Engine stores variables as <strong>zvals</strong> — containers that hold both a value and a type tag. This allows type juggling at runtime, but it also creates entire classes of bugs when implicit conversions surprise the developer.</p>
<p>Scope is predominantly <strong>function-local</strong>. Variables created inside a function are destroyed when the function returns unless explicitly captured via <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">global</code> or closure <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">use</code>. Global scope is available but should be treated as a code smell; modern code prefers dependency injection or explicit function arguments.</p>
<p><strong>Variable variables</strong> (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$$name</code>) and <strong>variable functions</strong> remain supported, but they are rarely justified in production because they break static analysis, autocompletion, and security review.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">scope.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">$greeting = 'Hello'; // Script/global scope</span>
<span class="line"></span>
<span class="line">function createMessage(string $name): string</span>
<span class="line">{</span>
<span class="line"> // Local scope: $prefix is not visible outside</span>
<span class="line"> $prefix = 'Welcome,';</span>
<span class="line"> return "{$prefix} {$name}!";</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">// Prefer passing data explicitly instead of global</span>
<span class="line">echo createMessage('Azhar'); // Welcome, Azhar!</span>
<span class="line"></span>
<span class="line">// Variable variables exist, but avoid them in production</span>
<span class="line">$field = 'username';</span>
<span class="line">$username = 'admin';</span>
<span class="line">// echo $$field; // Works, but impossible to statically analyze</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Relying on <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">global</code> inside functions:</strong> It couples code to hidden state. Pass dependencies as parameters or inject them.</li>
<li><strong>Assuming dynamic typing means "no types":</strong> PHP 8 has first-class scalar types, union types, and return types. Use them.</li>
<li><strong>Variable variables in business logic:</strong> They make refactoring dangerous and bypass static analysis. Use arrays or objects instead.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-3">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">3</span> Data Types & Strict Types</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP provides <strong>scalar</strong> types (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">int</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">float</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">string</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">bool</code>), <strong>compound</strong> types (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">array</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">object</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">callable</code>), and <strong>special</strong> types (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">null</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">resource</code>). PHP 8.0 added <strong>union types</strong>, <strong>mixed</strong>, and <strong>static</strong> return types; PHP 8.1 added <strong>never</strong>.</p>
<p>By default, PHP <strong>coerces</strong> types when possible. A string <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">"42"</code> passed to an <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">int</code> parameter becomes <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">42</code> without error. Coercion is convenient but dangerous. Modern PHP places <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">declare(strict_types=1);</code> at the top of every file to enforce <strong>strict type checking</strong>. In strict mode, a wrong type throws a <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">TypeError</code> at the call boundary.</p>
<p>The Zend Engine performs type checks at the call boundary and, in strict mode, rejects any value that does not exactly match the declared type. This catches bugs earlier and eliminates whole categories of injection-style type confusion.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">strict_types.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">function calculateTotal(int $quantity, float $unitPrice): float</span>
<span class="line">{</span>
<span class="line"> return $quantity * $unitPrice;</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">// Strict mode rejects strings that look like numbers.</span>
<span class="line">// calculateTotal("5", "10.5"); // TypeError</span>
<span class="line"></span>
<span class="line">$total = calculateTotal(5, 10.5); // 52.5</span>
<span class="line"></span>
<span class="line">// Union types are allowed when a value legitimately varies</span>
<span class="line">function describeValue(int|string|null $value): string</span>
<span class="line">{</span>
<span class="line"> return match (true) {</span>
<span class="line"> is_int($value) => "integer: {$value}",</span>
<span class="line"> is_string($value) => "string: {$value}",</span>
<span class="line"> default => 'no value',</span>
<span class="line"> };</span>
<span class="line">}</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Omitting <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">declare(strict_types=1)</code>:</strong> Coercion hides bugs. Every file should opt into strict types.</li>
<li><strong>Using <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">mixed</code> everywhere:</strong> It is useful for generic boundaries, but it should not replace specific type hints.</li>
<li><strong>Trusting input types because a form field is numeric:</strong> Validate and type-hint at the boundary. Never trust user data.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-4">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">4</span> Output & String Manipulation</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP offers multiple output mechanisms. <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">echo</code> is a language construct that accepts comma-separated arguments and has no return value. <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">print</code> is also a construct but behaves like a function and returns <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">1</code>; it is rarely used in modern code. <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">printf()</code> provides formatted output using type specifiers and is useful for CLI tooling.</p>
<p>String interpolation allows embedding variables directly inside double-quoted strings or heredocs. Complex expressions require the <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">{$object->property}</code> syntax. <strong>Heredoc</strong> (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono"><<<LABEL</code>) behaves like double quotes but spans multiple lines. <strong>Nowdoc</strong> (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono"><<<'LABEL'</code>) behaves like single quotes and does not interpolate — ideal for SQL snippets, templates, or raw payloads.</p>
<p>Modern output is almost never raw <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">echo</code> in a web context. It is rendered through templates, JSON encoders, or view components, and is always escaped to prevent XSS.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">output.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">$name = 'Azhar';</span>
<span class="line">$score = 95;</span>
<span class="line"></span>
<span class="line">// Interpolation</span>
<span class="line">echo "Welcome, {$name}!\n";</span>
<span class="line"></span>
<span class="line">// printf formatting</span>
<span class="line">printf("Score: %d%% (%s)\n", $score, $name);</span>
<span class="line"></span>
<span class="line">// Nowdoc: no interpolation, perfect for raw SQL</span>
<span class="line">$sql = <<<'SQL'</span>
<span class="line"> SELECT id, email</span>
<span class="line"> FROM users</span>
<span class="line"> WHERE active = 1</span>
<span class="line">SQL;</span>
<span class="line"></span>
<span class="line">// Heredoc: interpolation allowed</span>
<span class="line">$html = <<<HTML</span>
<span class="line"><p>Hello, {$name}</p></span>
<span class="line">HTML;</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Echoing user input unescaped:</strong> Always escape with <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">htmlspecialchars($value, ENT_QUOTES, 'UTF-8')</code> before HTML output.</li>
<li><strong>Concatenating massive strings with <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">.</code> in loops:</strong> PHP strings are immutable; repeated concatenation reallocates memory. Build arrays and <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">implode()</code> them.</li>
<li><strong>Using heredoc for SQL with variables:</strong> That is SQL injection. Use nowdoc with prepared statements instead.</li>
</ul>
</div>
</div>
</div>
<div class="mb-12" id="module-2" x-show="activeModule === 'module-2'" x-cloak>
<div class="mb-10" id="topic-5">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">5</span> Operators & Comparisons</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP operators should be chosen deliberately. The <strong>identity operator</strong> <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">===</code> compares both value and type, while the <strong>equality operator</strong> <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">==</code> performs type juggling. Legacy PHP code is full of <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">==</code> bugs such as <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">"0e12345" == "0e67890"</code> evaluating to <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">true</code> due to numeric string coercion.</p>
<p>The <strong>spaceship operator</strong> <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono"><=></code>, introduced in PHP 7, returns <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">-1</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">0</code>, or <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">1</code> for less-than, equal-to, and greater-than comparisons. It is the canonical choice for sorting callbacks and comparison logic. The <strong>null coalescing operator</strong> <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">??</code> returns the left operand if it exists and is not <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">null</code>; otherwise it returns the right operand. PHP 7.4 added the <strong>null coalescing assignment</strong> <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">??=</code>.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">operators.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">$a = 10;</span>
<span class="line">$b = '10';</span>
<span class="line"></span>
<span class="line">// Always prefer identity comparison</span>
<span class="line">var_dump($a == $b); // true (type juggling)</span>
<span class="line">var_dump($a === $b); // false (type-safe)</span>
<span class="line"></span>
<span class="line">// Spaceship operator</span>
<span class="line">$points = [34, 12, 89, 5];</span>
<span class="line">usort($points, static fn (int $x, int $y): int => $x <=> $y);</span>
<span class="line"></span>
<span class="line">// Null coalescing</span>
<span class="line">$config = [];</span>
<span class="line">$timeout = $config['timeout'] ?? 30;</span>
<span class="line">$config['cache'] ??= true; // assign only if missing/null</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Using <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">==</code> for security checks:</strong> Use <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">===</code> everywhere, especially when comparing tokens, hashes, or identifiers.</li>
<li><strong>Confusing <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">isset()</code> with <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">??</code>:</strong> They behave similarly for null checks, but <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">??</code> is cleaner and chainable.</li>
<li><strong>Using <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono"><=></code> in boolean contexts:</strong> It returns <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">-1</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">0</code>, or <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">1</code>. All three are truthy except 0, which is a footgun if treated as boolean.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-6">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">6</span> Control Flow</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>Control flow in PHP follows familiar C-style syntax. <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">if/else</code> chains remain the workhorse for conditional logic. The <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">switch</code> statement performs loose comparisons by default and falls through cases unless <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">break</code> is used — a historically common source of bugs.</p>
<p>PHP 8 introduced the <strong><code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">match</code></strong> expression. Unlike <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">switch</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">match</code> is an expression (it returns a value), uses strict identity comparison (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">===</code>), does not fall through, and requires every branch to be exhaustive. It is the modern replacement for many <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">switch</code> use cases.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">control_flow.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">$statusCode = 404;</span>
<span class="line"></span>
<span class="line">// Modern match expression</span>
<span class="line">$message = match ($statusCode) {</span>
<span class="line"> 200 => 'OK',</span>
<span class="line"> 301, 302 => 'Redirect',</span>
<span class="line"> 401 => 'Unauthorized',</span>
<span class="line"> 403 => 'Forbidden',</span>
<span class="line"> 404 => 'Not Found',</span>
<span class="line"> default => 'Unknown Status',</span>
<span class="line">};</span>
<span class="line"></span>
<span class="line">// Match can branch on arbitrary conditions</span>
<span class="line">$score = 85;</span>
<span class="line">$grade = match (true) {</span>
<span class="line"> $score >= 90 => 'A',</span>
<span class="line"> $score >= 80 => 'B',</span>
<span class="line"> $score >= 70 => 'C',</span>
<span class="line"> default => 'F',</span>
<span class="line">};</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Missing <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">break</code> in switch:</strong> Accidental fall-through causes logic errors. Use <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">match</code> or explicitly comment intentional fall-through.</li>
<li><strong>Using <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">switch</code> with mixed types:</strong> Loose comparison leads to surprising results. Prefer <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">match</code> for type safety.</li>
<li><strong>Deeply nested if/else ladders:</strong> Flatten with early returns, guard clauses, or <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">match</code>.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-7">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">7</span> Loop Constructs</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP provides <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">for</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">while</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">do-while</code>, and <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">foreach</code>. The <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">foreach</code> loop is the canonical tool for iterating arrays and objects implementing <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">Traversable</code>. By default it iterates over the array without modifying it; use <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">foreach ($items as &$item)</code> to mutate the original array in place.</p>
<p>Modern PHP favors <strong>functional-style transformations</strong> (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">array_map</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">array_filter</code>) or generators for large datasets instead of manual loops. The Zend Engine optimizes <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">foreach</code> with copy-on-write iterators, but generators still avoid materializing entire collections in memory.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">loops.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">$users = [</span>
<span class="line"> ['id' => 1, 'name' => 'Alice'],</span>
<span class="line"> ['id' => 2, 'name' => 'Bob'],</span>
<span class="line">];</span>
<span class="line"></span>
<span class="line">// Foreach with key and value</span>
<span class="line">foreach ($users as $index => $user) {</span>
<span class="line"> echo "{$index}: {$user['name']}\n";</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">// Prefer array functions for transformations</span>
<span class="line">$names = array_map(</span>
<span class="line"> static fn (array $user): string => $user['name'],</span>
<span class="line"> $users</span>
<span class="line">);</span>
<span class="line"></span>
<span class="line">// For numeric ranges</span>
<span class="line">for ($i = 0; $i < 10; $i++) {</span>
<span class="line"> echo $i . PHP_EOL;</span>
<span class="line">}</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Modifying an array while iterating it by value:</strong> Use reference iteration or build a new array.</li>
<li><strong>Using <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">for ($i = 0; $i < count($arr); $i++)</code>:</strong> <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">count()</code> is evaluated every iteration. Cache it or use <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">foreach</code>.</li>
<li><strong>Leaving reference variables alive after foreach:</strong> Unset <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$item</code> after a by-reference loop to avoid accidental mutations later.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-8">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">8</span> Array Basics</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP arrays are ordered hash maps. An <strong>indexed array</strong> uses integer keys starting at 0, while an <strong>associative array</strong> uses string keys. Under the hood, the Zend Engine stores arrays as packed hash tables with complex collision handling and copy-on-write semantics.</p>
<p>The modern short array syntax <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">[]</code> has fully replaced the legacy <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">array()</code> keyword. PHP 7.4 introduced the <strong>spread operator</strong> <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">...</code> for arrays, allowing arrays to be unpacked inline with integer keys. String-keyed spreads arrived in PHP 8.1.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">arrays.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">// Indexed array</span>
<span class="line">$tags = ['php', 'alpine', 'tailwind'];</span>
<span class="line"></span>
<span class="line">// Associative array</span>
<span class="line">$config = [</span>
<span class="line"> 'host' => 'localhost',</span>
<span class="line"> 'port' => 3306,</span>
<span class="line"> 'ssl' => true,</span>
<span class="line">];</span>
<span class="line"></span>
<span class="line">// Array unpacking with spread operator</span>
<span class="line">$defaults = ['timeout' => 30, 'retries' => 3];</span>
<span class="line">$overrides = ['retries' => 5];</span>
<span class="line">$merged = [...$defaults, ...$overrides]; // overrides win for string keys</span>
<span class="line"></span>
<span class="line">// Destructuring</span>
<span class="line">['host' => $host, 'port' => $port] = $config;</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Using <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">array()</code> syntax:</strong> Use <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">[]</code>. It is shorter, faster to read, and the modern standard.</li>
<li><strong>Treating arrays as untyped bags:</strong> For structured data, prefer objects, DTOs, or enums over nested associative arrays.</li>
<li><strong>Assuming <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">+</code> merges arrays:</strong> It preserves keys from the left operand and ignores duplicates. Use spread or <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">array_merge()</code> depending on desired behavior.</li>
</ul>
</div>
</div>
</div>
<div class="mb-12" id="module-3" x-show="activeModule === 'module-3'" x-cloak>
<div class="mb-10" id="topic-9">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">9</span> Functions</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>Functions are the primary unit of reusable logic in PHP. Modern functions declare scalar, object, nullable, and union types for every parameter and return value. PHP 8.0 introduced <strong>named arguments</strong>, which allow callers to pass parameters by name rather than position, improving readability and enabling selective skipping of optional parameters.</p>
<p><strong>Variadic functions</strong> capture an arbitrary number of arguments using <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">...$values</code>. Combined with typed parameters and named arguments, variadics make APIs flexible without sacrificing type safety. Default parameter values must be constant expressions and should be placed after required parameters.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">functions.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">function buildUrl(</span>
<span class="line"> string $path,</span>
<span class="line"> array $query = [],</span>
<span class="line"> bool $secure = true</span>
<span class="line">): string {</span>
<span class="line"> $scheme = $secure ? 'https' : 'http';</span>
<span class="line"> $queryString = $query === [] ? '' : '?' . http_build_query($query);</span>
<span class="line"> return "{$scheme}://example.com{$path}{$queryString}";</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">// Named arguments improve clarity</span>
<span class="line">$url = buildUrl('/search', secure: false, query: ['q' => 'php']);</span>
<span class="line"></span>
<span class="line">// Variadic typed function</span>
<span class="line">function sum(int ...$numbers): int</span>
<span class="line">{</span>
<span class="line"> return array_sum($numbers);</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">echo sum(1, 2, 3, 4); // 10</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Functions with no return type:</strong> Always declare return types; use <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">void</code> for procedures.</li>
<li><strong>Default parameters before required ones:</strong> PHP 8 still requires optional parameters after required ones in many cases.</li>
<li><strong>Returning mixed/ambiguous values:</strong> A function should return one predictable type. Use null or throw exceptions for errors.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-10">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">10</span> Anonymous Functions & Closures</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p><strong>Closures</strong> in PHP are objects of the internal <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">Closure</code> class. They can capture variables from the surrounding scope using the <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">use</code> keyword. Captures are <strong>by value</strong> by default; prefixing with <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">&</code> captures by reference.</p>
<p>PHP 7.4 introduced <strong>arrow functions</strong> (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">fn ($x) => $x * 2</code>). Arrow functions capture variables from the parent scope <strong>automatically by value</strong>. They are ideal for short, single-expression callbacks but cannot contain statements or multi-line bodies.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">closures.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">$multiplier = 3;</span>
<span class="line"></span>
<span class="line">// Arrow function captures $multiplier automatically</span>
<span class="line">$scale = fn (int $value): int => $value * $multiplier;</span>
<span class="line"></span>
<span class="line">// Closure with explicit use, by reference</span>
<span class="line">$counter = 0;</span>
<span class="line">$increment = function () use (&$counter): int {</span>
<span class="line"> return ++$counter;</span>
<span class="line">};</span>
<span class="line"></span>
<span class="line">$numbers = [1, 2, 3, 4];</span>
<span class="line">$scaled = array_map($scale, $numbers); // [3, 6, 9, 12]</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Using closures for complex logic:</strong> Arrow functions are for single expressions. Use named functions or classes for complex work.</li>
<li><strong>Forgetting <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">use</code> in traditional closures:</strong> Outer variables are not automatically available inside regular closures.</li>
<li><strong>Capturing by reference unnecessarily:</strong> It can cause subtle state leaks. Capture by value unless mutation is intentional.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-11">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">11</span> Superglobals & Request Handling</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>Superglobals (<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_GET</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_POST</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_SERVER</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_FILES</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_COOKIE</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_SESSION</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_ENV</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_REQUEST</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$GLOBALS</code>) are associative arrays populated by the SAPI before user code runs. They are mutable and globally accessible, which makes them convenient and dangerous.</p>
<p><strong>Sanitization</strong> removes or neutralizes unwanted characters. <strong>Validation</strong> checks whether input meets business rules. They are not interchangeable. Sanitizing an email does not validate it; validating a string does not make it safe for HTML output. Modern PHP uses dedicated libraries (e.g., Symfony Validator, laminas-filter) or strict typed request objects instead of raw superglobals scattered through code.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">request.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">// Never trust raw input. Filter, validate, then cast.</span>
<span class="line">$rawEmail = $_POST['email'] ?? '';</span>
<span class="line">$email = filter_var($rawEmail, FILTER_VALIDATE_EMAIL);</span>
<span class="line"></span>
<span class="line">if ($email === false) {</span>
<span class="line"> http_response_code(422);</span>
<span class="line"> echo 'Invalid email address.';</span>
<span class="line"> exit;</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">// Escape before output</span>
<span class="line">$safeEmail = htmlspecialchars($email, ENT_QUOTES, 'UTF-8');</span>
<span class="line">echo "<p>Registered: {$safeEmail}</p>";</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Directly echoing <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_GET</code>/<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_POST</code> values:</strong> This is the root cause of XSS. Escape or parameterize output.</li>
<li><strong>Confusing sanitization with validation:</strong> Use validation to reject bad input, not to silently fix it.</li>
<li><strong>Using <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_REQUEST</code>:</strong> It merges GET, POST, and COOKIE in unpredictable order. Be explicit about the source.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-12">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">12</span> State Persistence</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP's shared-nothing model means no request can see another request's memory. State is persisted via <strong>sessions</strong> (server-side, identified by a session cookie) and <strong>cookies</strong> (client-side name-value pairs). <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$_SESSION</code> is populated when <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">session_start()</code> is called and serialized to a handler at the end of the request.</p>
<p>Modern session configuration must be secure: use <strong>httponly</strong>, <strong>secure</strong>, and <strong>SameSite</strong> flags; regenerate IDs on privilege escalation; store sessions in Redis or a database instead of the filesystem at scale; and never store sensitive raw data client-side in cookies.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">session.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">// Secure session cookie settings before starting</span>
<span class="line">ini_set('session.cookie_httponly', '1');</span>
<span class="line">ini_set('session.cookie_secure', '1');</span>
<span class="line">ini_set('session.cookie_samesite', 'Strict');</span>
<span class="line">ini_set('session.use_strict_mode', '1');</span>
<span class="line">ini_set('session.use_only_cookies', '1');</span>
<span class="line"></span>
<span class="line">session_start();</span>
<span class="line"></span>
<span class="line">// After verifying credentials, rotate the session ID to prevent fixation</span>
<span class="line">// authenticateUser() is your credential-checking routine (returns int|null)</span>
<span class="line">$userId = authenticateUser($_POST['email'] ?? '', $_POST['password'] ?? '');</span>
<span class="line"></span>
<span class="line">if ($userId !== null) {</span>
<span class="line"> session_regenerate_id(true);</span>
<span class="line"> $_SESSION['authenticated'] = true;</span>
<span class="line"> $_SESSION['user_id'] = $userId;</span>
<span class="line">}</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Sessions without <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">httponly</code>/<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">secure</code>/<code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">SameSite</code>:</strong> These flags prevent XSS cookie theft and CSRF in transit.</li>
<li><strong>Not regenerating session IDs after login:</strong> Session fixation attacks hijack pre-assigned IDs.</li>
<li><strong>Storing secrets or large objects in session:</strong> Sessions should contain identifiers and small, serializable state, not raw passwords or huge arrays.</li>
</ul>
</div>
</div>
</div>
</section>
<section id="part-2" class="mb-16">
<div class="mb-12" id="module-4" x-show="activeModule === 'module-4'" x-cloak>
<div class="mb-10" id="topic-13">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">13</span> Classes & Objects</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>A <strong>class</strong> is a blueprint; an <strong>object</strong> is a runtime instance. PHP classes support typed properties, methods, constants, and visibility modifiers. Visibility — <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">public</code>, <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">protected</code>, and <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">private</code> — enforces encapsulation. Modern PHP rarely exposes public properties directly; instead it uses getters, setters, or readonly properties to maintain invariants.</p>
<p>The Zend Engine stores objects as reference-counted structures. Assigning an object variable does not copy the object; it copies a handle to the same object. This is different from arrays, which are copy-on-write.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">class.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">final class User</span>
<span class="line">{</span>
<span class="line"> public function __construct(</span>
<span class="line"> private string $name,</span>
<span class="line"> private string $email,</span>
<span class="line"> ) {}</span>
<span class="line"></span>
<span class="line"> public function name(): string</span>
<span class="line"> {</span>
<span class="line"> return $this->name;</span>
<span class="line"> }</span>
<span class="line"></span>
<span class="line"> public function email(): string</span>
<span class="line"> {</span>
<span class="line"> return $this->email;</span>
<span class="line"> }</span>
<span class="line"></span>
<span class="line"> public function updateEmail(string $email): void</span>
<span class="line"> {</span>
<span class="line"> if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {</span>
<span class="line"> throw new InvalidArgumentException('Invalid email.');</span>
<span class="line"> }</span>
<span class="line"> $this->email = $email;</span>
<span class="line"> }</span>
<span class="line">}</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Public mutable properties:</strong> Break encapsulation. Use private properties with controlled methods.</li>
<li><strong>Untyped properties:</strong> PHP 7.4+ supports typed properties. Use them.</li>
<li><strong>Massive "god classes":</strong> A class should have one reason to change. Split responsibilities.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-14">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">14</span> Modern Object Construction</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP 8.0 introduced <strong>Constructor Property Promotion</strong>, allowing constructor parameters to be declared as class properties inline. This removes boilerplate and makes value objects trivial to write. PHP 8.1 added <strong>readonly properties</strong>, which can be written exactly once — typically during construction — and then become immutable.</p>
<p>Together, promotion and <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">readonly</code> make PHP's value objects (DTOs, entities, command objects) concise, type-safe, and immutable. Readonly properties can only be initialized from the declaring scope and cannot be reassigned, including via reflection after initialization.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">construction.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">final class Money</span>
<span class="line">{</span>
<span class="line"> public function __construct(</span>
<span class="line"> public readonly float $amount,</span>
<span class="line"> public readonly string $currency,</span>
<span class="line"> ) {}</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">$price = new Money(amount: 99.99, currency: 'USD');</span>
<span class="line">// $price->amount = 100.00; // Fatal Error: readonly property</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Manual constructor assignments:</strong> Use promotion to reduce noise.</li>
<li><strong>Mutable DTOs:</strong> If data should not change after creation, mark properties <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">readonly</code>.</li>
<li><strong>Initializing readonly properties outside the constructor:</strong> They must be assigned exactly once, before construction completes.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-15">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">15</span> Inheritance & Polymorphism</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p><strong>Inheritance</strong> in PHP uses the <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">extends</code> keyword. A child class inherits public and protected members from the parent. <strong>Polymorphism</strong> allows code to operate on objects of different classes through a common interface or parent type. Method overriding lets a child class replace parent behavior, but the override must be compatible with the parent's signature (covariance/contravariance rules apply).</p>
<p>The <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">final</code> keyword prevents a class from being extended or a method from being overridden. Modern PHP uses <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">final</code> aggressively on classes that are not designed for inheritance, because inheritance is a fragile extension mechanism compared to composition.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">inheritance.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">abstract class Notification</span>
<span class="line">{</span>
<span class="line"> abstract public function send(string $message): void;</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">final class EmailNotification extends Notification</span>
<span class="line">{</span>
<span class="line"> public function send(string $message): void</span>
<span class="line"> {</span>
<span class="line"> echo "Sending email: {$message}\n";</span>
<span class="line"> }</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">final class SmsNotification extends Notification</span>
<span class="line">{</span>
<span class="line"> public function send(string $message): void</span>
<span class="line"> {</span>
<span class="line"> echo "Sending SMS: {$message}\n";</span>
<span class="line"> }</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">function notifyUser(Notification $notification, string $message): void</span>
<span class="line">{</span>
<span class="line"> $notification->send($message); // polymorphic dispatch</span>
<span class="line">}</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Deep inheritance hierarchies:</strong> Prefer composition. Deep trees are hard to test and refactor.</li>
<li><strong>Non-final concrete classes without intent:</strong> If a class is not explicitly designed for extension, mark it <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">final</code>.</li>
<li><strong>Breaking Liskov Substitution:</strong> Overrides should not strengthen preconditions or weaken postconditions.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-16">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">16</span> Abstraction & Interfaces</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p><strong>Abstract classes</strong> provide a partial implementation and cannot be instantiated. They are useful when related classes share common state or concrete behavior. <strong>Interfaces</strong> define a pure contract — a set of methods that implementing classes must provide. A class can implement multiple interfaces but extend only one class.</p>
<p>Modern PHP uses interfaces to decouple code from concrete implementations. Type-hinting against interfaces allows dependency injection, mocking in tests, and swapping implementations without changing callers. PHP 8.0+ added <strong>static</strong> return types and constructor signature enforcement through interfaces; interface inheritance has been supported since PHP 5.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">interfaces.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">interface Cache</span>
<span class="line">{</span>
<span class="line"> public function get(string $key): ?string;</span>
<span class="line"> public function set(string $key, string $value, int $ttl): void;</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">final class InMemoryCache implements Cache</span>
<span class="line">{</span>
<span class="line"> /** @var array<string, array{value: string, expiresAt: int}> */</span>
<span class="line"> private array $storage = [];</span>
<span class="line"></span>
<span class="line"> public function get(string $key): ?string</span>
<span class="line"> {</span>
<span class="line"> $entry = $this->storage[$key] ?? null;</span>
<span class="line"> if ($entry === null || $entry['expiresAt'] < time()) {</span>
<span class="line"> return null;</span>
<span class="line"> }</span>
<span class="line"> return $entry['value'];</span>
<span class="line"> }</span>
<span class="line"></span>
<span class="line"> public function set(string $key, string $value, int $ttl): void</span>
<span class="line"> {</span>
<span class="line"> $this->storage[$key] = ['value' => $value, 'expiresAt' => time() + $ttl];</span>
<span class="line"> }</span>
<span class="line">}</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Type-hinting concrete classes everywhere:</strong> Depend on interfaces, not implementations.</li>
<li><strong>Fat interfaces:</strong> An interface should be small and focused. Split bloated contracts.</li>
<li><strong>Using abstract classes for pure contracts:</strong> If there is no shared implementation, use an interface.</li>
</ul>
</div>
</div>
<div class="mb-10" id="topic-17">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">17</span> Traits & Code Reuse</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p><strong>Traits</strong> provide horizontal code reuse. Unlike inheritance, which is vertical, a trait is a group of methods that can be inserted into multiple unrelated classes. Traits are compiled into the using class at runtime; they do not create a new type and cannot be instantiated or type-hinted.</p>
<p>Traits are useful for cross-cutting concerns such as logging, event dispatching, or timestampable behavior. However, they can introduce naming conflicts when two traits provide the same method. PHP resolves this with <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">insteadof</code> and <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">as</code> operators.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">traits.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">trait Timestampable</span>
<span class="line">{</span>
<span class="line"> private readonly DateTimeImmutable $createdAt;</span>
<span class="line"></span>
<span class="line"> public function __construct()</span>
<span class="line"> {</span>
<span class="line"> $this->createdAt = new DateTimeImmutable();</span>
<span class="line"> }</span>
<span class="line"></span>
<span class="line"> public function createdAt(): DateTimeImmutable</span>
<span class="line"> {</span>
<span class="line"> return $this->createdAt;</span>
<span class="line"> }</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">final class Article</span>
<span class="line">{</span>
<span class="line"> use Timestampable;</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">final class Comment</span>
<span class="line">{</span>
<span class="line"> use Timestampable;</span>
<span class="line">}</span></code></pre>
</div>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Common Anti-Patterns & Mistakes</h5>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Traits as a substitute for composition:</strong> If a class needs behavior, inject a collaborator instead of copy-pasting methods.</li>
<li><strong>Traits with hidden dependencies:</strong> A trait that expects certain properties or methods on the using class is fragile and hard to trace.</li>
<li><strong>Ignoring trait conflicts:</strong> Always resolve method collisions explicitly with <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">insteadof</code>.</li>
</ul>
</div>
</div>
</div>
<div class="mb-12" id="module-5" x-show="activeModule === 'module-5'" x-cloak>
<div class="mb-10" id="topic-18">
<h4 class="text-xl font-bold text-github-900 dark:text-github-100 flex items-center gap-3"><span class="flex h-8 w-8 items-center justify-center rounded-full bg-php-100 text-php-700 text-sm font-bold dark:bg-php-900/30 dark:text-php-300">18</span> Defensive Programming</h4>
<div class="mt-4 space-y-4 text-github-700 dark:text-github-300 leading-relaxed">
<h5 class="font-semibold text-github-900 dark:text-github-100">Conceptual Explanation</h5>
<p>PHP errors have evolved from silent failures and legacy error levels to a robust <strong>exception</strong> model. Modern PHP code throws exceptions for exceptional conditions and catches them at appropriate boundaries. <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">try/catch/finally</code> blocks isolate failure handling, and <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">finally</code> guarantees cleanup regardless of success or failure.</p>
<p><strong>Custom exceptions</strong> extend <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">\Exception</code> or <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">\RuntimeException</code> and communicate domain-specific failures. They should be named after the problem they represent, not the layer that throws them. PHP 8.0 made the throw statement an expression, allowing constructs like <code class="bg-github-100 dark:bg-github-800 dark:text-github-200 px-1 py-0.5 rounded text-sm font-mono">$value ?? throw new InvalidArgumentException()</code>.</p>
<h5 class="font-semibold text-github-900 dark:text-github-100 pt-4">Idiomatic Code Example</h5>
<div class="rounded-lg bg-github-900 overflow-hidden text-sm my-4">
<div class="flex items-center justify-between px-4 py-2 bg-github-800"><span class="text-github-300 font-mono text-xs">exceptions.php</span><button @click="copyCode($el)" class="text-xs text-github-200 hover:text-white">Copy</button></div>
<pre class="code-block p-4 font-mono text-github-100 overflow-x-auto"><code class="block"><span class="line"><?php</span>
<span class="line"></span>
<span class="line">declare(strict_types=1);</span>
<span class="line"></span>
<span class="line">final class PaymentFailedException extends RuntimeException</span>
<span class="line">{</span>
<span class="line"> public static function forInsufficientFunds(): self</span>
<span class="line"> {</span>
<span class="line"> return new self('Payment declined: insufficient funds.');</span>
<span class="line"> }</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">function auditLog(string $event): void</span>
<span class="line">{</span>
<span class="line"> // Production: write to immutable audit store</span>