Luyện Phỏng Vấn IT — 2000+ Câu Hỏi Phỏng Vấn IT Có Đáp Án 2026
PHP
PHP viết tắt của Hypertext Preprocessor, là ngôn ngữ lập trình phía server dùng để tạo trang web động.
- Khi người dùng truy cập một trang PHP, server sẽ thực thi mã PHP rồi trả về HTML cho trình duyệt.
- Khác với JavaScript chạy trên trình duyệt, PHP chạy hoàn toàn trên server trước khi gửi kết quả về cho client.
- PHP là mã nguồn mở, đa nền tảng và tích hợp tốt với các cơ sở dữ liệu như MySQL, PostgreSQL.
Superglobal là các biến được PHP định nghĩa sẵn, có thể truy cập ở bất kỳ đâu trong script mà không cần khai báo global.
- Các superglobal quan trọng:
$_GET(dữ liệu gửi qua URL),$_POST(dữ liệu gửi ẩn qua form),$_SERVER(thông tin server),$_FILES(file được upload),$_COOKIE(dữ liệu cookie),$_SESSION(lưu trữ session),$GLOBALS(chứa tất cả biến toàn cục). - PHP tự động gán giá trị cho các biến này và có thể dùng trong mọi hàm hay phạm vi.
Cả hai đều thu thập dữ liệu từ form nhưng khác nhau về tính bảo mật và giới hạn dữ liệu. $_GET đính kèm dữ liệu vào URL (dễ nhìn thấy), giới hạn khoảng 2KB và không an toàn cho dữ liệu nhạy cảm. $_POST gửi dữ liệu trong body của request (ẩn với URL), có giới hạn dung lượng lớn hơn nhiều (do post_max_size trong php.ini, mặc định ~8MB) và an toàn hơn cho mật khẩu hay thông tin cá nhân.
Dùng $_GET khi lọc/tìm kiếm và muốn bookmark URL, dùng $_POST cho các form nhập dữ liệu nhạy cảm.
PHP có 8 kiểu dữ liệu cơ bản: String (chuỗi như "Hello"), Integer (số nguyên), Float (số thập phân), Boolean (true/false), Array (tập hợp giá trị), Object (thực thể của lớp), NULL (không có giá trị), và Resource (tham chiếu tài nguyên bên ngoài).
- Bốn kiểu đầu là scalar (kiểu đơn giản), Array và Object là kiểu phức hợp, NULL là kiểu đặc biệt, còn Resource dùng cho kết nối database hay file handle.
- PHP 8.1+ bổ sung Enum như là first-class type với type safety đầy đủ, cùng với union types (8.0:
int|string), intersection types (8.1:A&B), và never type (8.1).
== kiểm tra giá trị có bằng nhau không nhưng cho phép chuyển đổi kiểu dữ liệu.
Ví dụ "5" == 5 trả về true vì PHP tự đổi chuỗi thành số.
- Trong khi
===(so sánh nghiêm ngặt) kiểm tra cả giá trị lẫn kiểu dữ liệu, nên"5" === 5trả vềfalse. - Luôn dùng
===trong code thực tế để tránh lỗi do PHP tự động ép kiểu và giúp code rõ ràng hơn.
- PHP có ba loại mảng: Indexed array (truy cập theo vị trí:
$fruits[0]), Associative array (truy cập theo key:$person["name"]), và Multidimensional array (mảng chứa mảng khác). - Tạo mảng indexed:
$arr = ["apple", "banana"], mảng associative:$arr = ["name" => "John", "age" => 30]. - Các hàm thông dụng:
count()đếm phần tử,array_push()thêm phần tử,array_merge()gộp mảng,in_array()kiểm tra tồn tại,array_keys()vàarray_values()lấy key hoặc value.
Các hàm chuỗi quan trọng gồm: strlen() (lấy độ dài), strpos() (tìm vị trí chuỗi con), str_replace() (thay thế text), substr() (cắt chuỗi), strtolower() và strtoupper() (đổi chữ hoa/thường), trim() (xóa khoảng trắng đầu cuối), explode() (tách chuỗi thành mảng), implode() (ghép mảng thành chuỗi), htmlspecialchars() (escape HTML để bảo mật).
Ví dụ: explode(",", "apple,banana,orange") tạo ra ["apple", "banana", "orange"].
Cả hai đều nhúng file PHP bên ngoài, nhưng khác nhau ở cách xử lý lỗi. include chỉ cảnh báo (E_WARNING) nếu file không tồn tại và tiếp tục chạy, còn require báo lỗi nghiêm trọng (E_ERROR) và dừng thực thi ngay. include_once và require_once chỉ nhúng file một lần duy nhất trong cùng script.
Dùng require cho các file thiết yếu (như kết nối database) và include cho các thành phần không bắt buộc (như sidebar template).
Truy cập dữ liệu form qua superglobal: method GET dùng $_GET["fieldname"], POST dùng $_POST["fieldname"]. Luôn validate và sanitize: kiểm tra tồn tại với isset($_POST["email"]), validate định dạng với filter_var(), escape output với htmlspecialchars() để ngăn XSS.
Ví dụ: $email = htmlspecialchars($_POST["email"]); if(filter_var($email, FILTER_VALIDATE_EMAIL)) { // hợp lệ }. Không bao giờ tin tưởng dữ liệu từ người dùng—luôn validate trước khi sử dụng.
PHP có ba loại lỗi truyền thống: Notice (không nghiêm trọng, không dừng script như truy cập biến chưa định nghĩa), Warning (nghiêm trọng hơn nhưng script vẫn chạy như mở file không hợp lệ), và Fatal error (nghiêm trọng, dừng thực thi như gọi hàm chưa định nghĩa).
- PHP 7+ bổ sung hệ thống Error class:
ErrorvàExceptionđều implementThrowable, bao gồmTypeError,ValueError,ParseError. - Xử lý lỗi bằng:
error_reporting(E_ALL)hiển thị mọi lỗi,set_error_handler()xử lý tùy chỉnh, hoặc dùng try-catch cho Throwable. - Trên môi trường production, ghi lỗi vào file log thay vì hiển thị cho người dùng.
Định nghĩa hằng số bằng define("CONSTANT_NAME", value) hoặc const CONSTANT_NAME = value;.
- Hằng số không có dấu
$, không thể thay đổi sau khi định nghĩa, là global mà không cần dùng từ khóaglobal. - Từ PHP 8.0, hằng số luôn case-sensitive (tham số
$case_insensitivecủadefine()đã bị xóa). - Dùng hằng cho giá trị cấu hình:
define("DB_HOST", "localhost"); echo DB_HOST;. - Nên dùng hằng thay biến cho các giá trị không bao giờ thay đổi trong quá trình thực thi.
Class là bản thiết kế (blueprint) định nghĩa thuộc tính và phương thức, còn Object là một thực thể cụ thể được tạo ra từ class đó.
- Hãy nghĩ class như khuôn bánh và object như những chiếc bánh thực sự.
- Khai báo class:
class User { public $name; public function getName() { return $this->name; } }. - Tạo object:
$user = new User();. - Mỗi object có bản sao thuộc tính riêng nhưng chia sẻ chung phần code của phương thức.
Kế thừa cho phép class con kế thừa thuộc tính và phương thức từ class cha, giúp tái sử dụng code. Dùng class Student extends User để kế thừa. Class con có thể truy cập các thành phần public và protected của cha, override phương thức cha, và thêm chức năng mới. Gọi phương thức cha bằng parent::methodName().
Ví dụ: class Admin extends User nghĩa là Admin có tất cả thuộc tính của User nhưng bổ sung thêm các phương thức đặc thù của admin. Giúp giảm trùng lặp code và tạo ra cấu trúc phân cấp hợp lý.
PHP không hỗ trợ đa kế thừa (một class chỉ có thể extends một class cha). Thay vào đó, dùng interface: một class có thể implement nhiều interface.
Ví dụ: class Employee implements Payable, Manageable trong đó cả hai interface đều định nghĩa contract mà class phải thực hiện. Ngoài ra còn có trait để tái sử dụng code: trait Logger { public function log() {} } rồi class User { use Logger; } để chia sẻ phương thức giữa các class không liên quan mà không cần kế thừa.
Interface định nghĩa một hợp đồng (contract)—tập hợp các phương thức mà class implement bắt buộc phải có. Khai báo: interface UserRepository { public function find($id); public function save($user); }. Bất kỳ class nào implement interface này đều phải triển khai tất cả phương thức đó.
Lợi ích: đảm bảo tính nhất quán giữa các implementations, cho phép polymorphism, dễ viết test với mock. Dùng interface khi cần đảm bảo các phương thức nhất định tồn tại bất kể cách implement cụ thể là gì.
Trait cho phép tái sử dụng phương thức trong nhiều class không liên quan mà không cần kế thừa.
- Khai báo:
trait Logger { public function log($msg) { echo $msg; } }. - Dùng trong bất kỳ class nào:
class User { use Logger; }vàclass Product { use Logger; }thì cả hai đều có phương thức log. - Trait giải quyết vấn đề trùng lặp code khi nhiều class cần chức năng giống nhau nhưng không chia sẻ class cha.
- Chúng giống như tái sử dụng "ngang" trong khi kế thừa là tái sử dụng "dọc".
Magic methods là các phương thức đặc biệt tự động được gọi khi có hành động tương ứng xảy ra. Các magic method quan trọng: __construct() (chạy khi tạo object), __destruct() (chạy khi hủy object), __get() (truy cập thuộc tính không tồn tại), __set() (gán thuộc tính không tồn tại), __call() (gọi phương thức không tồn tại), __toString() (khi object được in như chuỗi).
Ví dụ: truy cập $user->email private sẽ kích hoạt __get("email") để kiểm soát quyền truy cập. Hầu hết magic method phải là public; __construct có thể là protected hoặc private khi dùng cho singleton pattern.
Instance method thuộc về object và truy cập dữ liệu riêng của object qua $this. Gọi bằng $object->method(). Static method thuộc về chính class, không phải instance, và không thể truy cập $this. Khai báo với static function và gọi bằng ClassName::method().
Ví dụ: User::count() (static, đếm tổng user) vs $user->getName() (instance, lấy tên user cụ thể). Static method hữu ích cho utility functions, factory methods, hoặc theo dõi dữ liệu cấp class.
Access modifier kiểm soát khả năng hiển thị của thuộc tính và phương thức: public truy cập được từ mọi nơi (trong/ngoài class và subclass), private chỉ truy cập được bên trong class đó (không phải subclass), protected truy cập được trong class và subclass nhưng không từ bên ngoài.
Ví dụ: private $password ngăn truy cập trực tiếp như $user->password = "hacked", buộc phải dùng setter method để kiểm tra. Dùng private cho dữ liệu nội bộ, protected để subclass dùng, public cho giao diện ra bên ngoài.
Typed class constants cho phép khai báo kiểu dữ liệu cho hằng số trong class, tương tự typed properties.
Ví dụ: public const int MAX_USERS = 1000; hoặc public const string API_KEY = "secret";.
Lợi ích: tăng type safety, IDE autocomplete chính xác hơn, ngăn nhầm kiểu dữ liệu vô tình, tự document code. Kiểu phải khớp với giá trị gán tại thời điểm khai báo—PHP sẽ báo lỗi nếu không khớp. Đây là tính năng nhỏ nhưng quan trọng giúp codebase PHP lớn dễ bảo trì hơn.
Readonly classes ngăn sửa đổi các public property sau khi khởi tạo. Ràng buộc cụ thể: mọi property phải có kiểu (không được khai báo untyped), không thể có static property, không dùng được #[AllowDynamicProperties], và mỗi property phải được gán giá trị trong constructor.
Ví dụ: readonly class Address { public function __construct(public string $street, public string $city) {} }. Rất phù hợp để xây dựng Value Object và DTO bất biến.
Ràng buộc kế thừa: readonly class không thể được extend bởi non-readonly class. Child class bắt buộc phải cũng là readonly — đây là ràng buộc của PHP 8.2.
Enums định nghĩa tập hợp giá trị cố định, hợp lệ với type safety đầy đủ.
Ví dụ: enum OrderStatus { case PENDING; case SHIPPED; case DELIVERED; } rồi $order->status = OrderStatus::PENDING;. Hơn constants ở điểm: type-checked (không thể gán giá trị tùy ý), hỗ trợ method bên trong enum, tích hợp với Eloquent qua cast. Backed enum có value: enum Status: string { case ACTIVE = 'active'; case INACTIVE = 'inactive'; } lưu vào DB dễ dàng. Dùng cho: trạng thái đơn hàng, vai trò người dùng, phương thức thanh toán—bất kỳ tập giá trị có hạn nào cần type safety.
PDO (PHP Data Objects) là lớp trừu tượng cung cấp giao diện nhất quán để truy cập database.
- Phòng chống SQL injection bằng prepared statements: thay vì
"SELECT FROM users WHERE id=$id", dùng$stmt = $pdo->prepare("SELECT FROM users WHERE id=?"); $stmt->execute([$id]);. - Placeholder
?đảm bảo input của người dùng được xử lý như dữ liệu, không phải code thực thi. - Named placeholder cũng tương tự:
"... WHERE id=:id"rồiexecute([":id" => $id]). - Database engine sẽ không bao giờ parse tham số như SQL code.
Session lưu dữ liệu người dùng trên server để duy trì trạng thái giữa các request.
- Bắt đầu bằng
session_start(), rồi truy cập qua$_SESSION["key"] = value. - Dữ liệu ở trên server, chỉ gửi session ID về trình duyệt qua cookie.
- Cookie lưu dữ liệu trên client, gửi kèm mọi request, giới hạn ~4KB, và người dùng có thể sửa đổi.
- Session an toàn hơn vì dữ liệu ẩn với client, phù hợp cho dữ liệu nhạy cảm.
- Dùng
session_destroy()để kết thúc session,unset($_SESSION["key"])để xóa dữ liệu cụ thể.
Namespace tổ chức code và tránh xung đột tên. Khai báo với namespace MyApp\Models; ở đầu file. Nhiều class có thể cùng tên nếu ở namespace khác nhau: MyApp\Models\User và Admin\Models\User. Import bằng use MyApp\Models\User as MyUser;.
Lợi ích: tổ chức codebase lớn một cách logic, ngăn ô nhiễm global namespace, cho phép autoloading theo chuẩn PSR, cải thiện khả năng bảo trì. Nếu không có namespace, toàn bộ code cạnh tranh trong global namespace gây ra xung đột.
Autoloading tự động tải file class mà không cần require thủ công. Dùng spl_autoload_register() để định nghĩa autoloader tùy chỉnh, hoặc tốt hơn là dùng autoloader của Composer theo chuẩn PSR-4. Với Composer, chỉ cần khai báo namespace và đường dẫn file trong composer.json, sau đó require "vendor/autoload.php" tải mọi thứ.
Ví dụ: namespace App\Models\User tự động tải từ app/Models/User.php. Autoloading cải thiện tổ chức code và mở rộng tốt hơn so với require thủ công.
Generator là hàm dùng yield để trả về nhiều giá trị từng cái một mà không cần tải tất cả vào bộ nhớ.
- Khai báo:
function numbers() { yield 1; yield 2; yield 3; }rồi lặp vớiforeach(numbers() as $num). - Tiết kiệm bộ nhớ cho dataset lớn: xử lý file với
yieldđọc từng dòng thay vì tải toàn bộ file. - Dùng
yield $key => $valuecho cặp key-value. - Generator chậm hơn cho dataset nhỏ nhưng không thể thiếu khi xử lý file lớn, streams hay chuỗi vô hạn.
unset() và unlink() là gì?unset() xóa biến khỏi bộ nhớ, giải phóng giá trị của nó nhưng không xóa file nếu biến đó chứa tên file.
- Dùng để dọn dẹp:
unset($tempVar).unlink()xóa file khỏi hệ thống:unlink("oldfile.txt")xóa vĩnh viễn file đó. - Lỗi phổ biến là dùng
unset()nghĩ rằng nó xóa file—luôn dùngunlink()để xóa file. - Trong ngữ cảnh database,
unset($result)chỉ xóa biến kết quả còn kết nối vẫn tồn tại.
Tấn công XSS chèn script độc hại qua input của người dùng. Phòng chống bằng:
- Luôn escape output với
htmlspecialchars()chuyển đổi<script>thành<script> - Validate và sanitize input với
filter_var() - Thiết lập Content Security Policy header:
header("Content-Security-Policy: default-src 'self'") - Không bao giờ in trực tiếp dữ liệu người dùng
Ví dụ: echo htmlspecialchars($_GET["search"], ENT_QUOTES, "UTF-8"); hiển thị an toàn. Nguyên tắc vàng: không tin bất cứ gì từ người dùng, escape mọi thứ trước khi hiển thị.
Dùng khối try-catch-finally: try { code có thể lỗi; } catch(Exception $e) { xử lý lỗi; } finally { code dọn dẹp; }. Ném ngoại lệ tùy chỉnh: throw new Exception("Không tìm thấy user");. Tạo class exception riêng bằng cách extends Exception để phân loại lỗi cụ thể. Khối finally luôn chạy dù có exception hay không.
Lưu ý quan trọng: fopen() không throw Exception—nó trả về false hoặc phát sinh Warning. Để bắt lỗi fopen như exception, cần dùng custom error handler hoặc gói ErrorException.
Ví dụ đúng: throw new RuntimeException("Không tìm thấy file missing.txt"); khi cần exception thực sự. Xử lý exception đúng cách ngăn crash và cung cấp thông tin lỗi có ý nghĩa.
Type hinting chỉ định kiểu dữ liệu kỳ vọng của tham số và kiểu trả về: function getUserById(int $id): User { ... }.
Lợi ích: phát hiện lỗi sớm (truyền string thay vì int sẽ báo lỗi ngay), cải thiện khả năng đọc code, hỗ trợ IDE autocomplete, và đóng vai trò tài liệu. Kiểu scalar: int, string, float, bool. Kiểu object: tên class. Nullable: ?int cho phép int hoặc null. PHP 8.0+ bổ sung union types (int|string), PHP 8.1 thêm intersection types (A&B) và never type, PHP 8.2 thêm DNF types ((A&B)|null). Type hint không bắt buộc nhưng rất khuyến nghị cho code dễ bảo trì.
Abstract class là class không đầy đủ, không thể khởi tạo trực tiếp—chỉ có thể kế thừa.
- Dùng
abstract class Animal { abstract public function sound(); }. - Subclass bắt buộc phải triển khai abstract method:
class Dog extends Animal { public function sound() { return "Woof"; } }. - Abstract class có thể có method cụ thể và thuộc tính, khác với interface.
- Dùng khi muốn áp đặt cấu trúc nhưng có sẵn một số implementation mặc định: interface chỉ cho contracts thuần túy, abstract class cho chức năng cơ sở được chia sẻ.
Fibers là các luồng nhẹ (lightweight) ở user-space, cho phép tạm dừng và tiếp tục thực thi code mà không cần đa luồng OS.
Ví dụ: $fiber = new Fiber(function() { $value = Fiber::suspend("hello"); echo $value; }); $fiber->start(); $fiber->resume("world");. Khác với threads: Fibers không tạo tiến trình OS riêng, tiêu tốn ít bộ nhớ hơn, không cần lock/mutex. Ứng dụng: xử lý nhiều I/O đồng thời (API call, query DB) trong một request. Các thư viện như Amp và ReactPHP dùng Fibers để xây dựng server phi đồng bộ hiệu năng cao.
Value Objects là các object bất biến đại diện cho khái niệm nghiệp vụ (Money, Email, Address) thay vì dùng kiểu nguyên thủy dễ sai.
Ví dụ: thay $price = 99.99 (float dễ lỗi làm tròn), dùng new Money(9999, 'VND') với validation trong constructor.
Lợi ích: type safety, ngôn ngữ domain rõ ràng, đóng gói logic validation, ngăn trạng thái không hợp lệ. new Email('user@example.com') sẽ throw exception nếu format sai ngay khi tạo object. Laravel Casts có thể tự hydrate Value Object từ DB. Áp dụng sớm để bắt bug tại compile-time thay vì runtime.