Modern WordPress development relies heavily on modern PHP features. These questions test a candidate's ability to write clean, object-oriented code within the WordPress ecosystem.
1. Explain the difference between `require`, `include`, `require_once`, and `include_once`. When would you use each?
Answer:
- `require`: Includes a file; throws a fatal error (E_COMPILE_ERROR) and stops script execution if the file is missing.
- `include`: Includes a file; emits a warning (E_WARNING) but continues script execution if the file is missing.
- `_once` variants: Check if the file has already been included. If so, they do not include it again.
Best Practice: In modern WordPress (Bedrock/Composer), we rarely use these manually for classes (due to autoloading). However, for template partials or config files, `require_once` is safest for critical dependencies, while `include` is acceptable for optional templates.
2. How does PSR-4 Autoloading work, and how do you implement it in a WordPress plugin?
Answer: PSR-4 maps namespaces to file paths. It allows classes to be loaded automatically without manual `require` statements.
Implementation:
- Define the mapping in `composer.json`:
{
"autoload": {
"psr-4": {
"MyPlugin\\": "src/"
}
}
}
- Run
composer dump-autoload. - Include
require_once __DIR__ . '/vendor/autoload.php';in your main plugin file.
3. Traits vs. Interfaces vs. Abstract Classes
Question: When would you use a Trait over an Interface or Abstract Class in a WordPress context?
- Interface: Defines a contract (e.g.,
Renderable). Use when different classes must share a method signature but implementation varies. - Abstract Class: Provides a base implementation (e.g.,
BaseWidget). Use when classes share a common "is-a" relationship and shared logic. - Trait: Horizontal code reuse (e.g.,
HasSettings). Use when unrelated classes need the same functionality (like logging or singleton behavior) without inheritance.
4. Dependency Injection (DI) in WordPress
Question: WordPress relies heavily on global state (hooks). How do you implement DI to make code testable?
Instead of instantiating dependencies inside a class, pass them via the constructor.
// Bad (Hard to test)
class OrderService {
public function process() {
$db = new Database(); // Hard dependency
$db->save();
}
}
// Good (DI)
class OrderService {
protected $db;
public function __construct(DatabaseInterface $db) {
$this->db = $db;
}
}
In WordPress, we often use a Container (like PHP-DI) or a simple service provider pattern to wire these up in the main plugin file.
5. Late Static Binding
Question: What is Late Static Binding and what keyword is used?
Answer: It allows referenced static methods or properties to be resolved at runtime (late) rather than compile time. It uses the `static` keyword instead of `self`.
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who(); // Outputs 'A'
static::who(); // Outputs 'B' (when called from B)
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
6. What are Generators in PHP?
Answer: Generators provide an easy way to implement simple iterators without the overhead or complexity of implementing a class that implements the Iterator interface.
A generator allows you to write code that uses `foreach` to iterate over a set of data without needing to build an array in memory, which may cause you to exceed a memory limit.
function getLines($file) {
$f = fopen($file, 'r');
while ($line = fgets($f)) {
yield $line;
}
fclose($f);
}
7. Explain Anonymous Classes.
Answer: Anonymous classes are useful for simple, one-off objects. They can pass arguments to their constructors, extend other classes, implement interfaces, and use traits just like a normal class.
$logger = new class {
public function log($msg) {
echo $msg;
}
};
$logger->log('Hello World');
8. What is the Null Coalescing Operator?
Answer: The null coalescing operator (`??`) is syntactic sugar for the common case of needing to use a ternary in conjunction with `isset()`. It returns its first operand if it exists and is not null; otherwise it returns its second operand.
// Old way
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// New way
$username = $_GET['user'] ?? 'nobody';
9. What are Attributes (Annotations) in PHP 8?
Answer: Attributes allow you to add structured, machine-readable metadata information on declarations in your code: classes, methods, functions, parameters, properties and class constants.
They replace the old PHPDoc-style annotations (e.g., `@Route`).
#[Route("/api/posts", methods: ["GET"])]
public function index() { ... }
10. Explain WeakMaps.
Answer: A WeakMap is a collection of objects (keys) and values where the keys are weakly referenced. This means that if the object key is no longer referenced anywhere else in the application, it will be garbage collected, and the entry will be removed from the WeakMap automatically. This prevents memory leaks in long-running processes.