How can nested sets be utilized in PHP to store and retrieve hierarchical data efficiently?

Nested sets can be utilized in PHP to store hierarchical data efficiently by assigning each node in the hierarchy two additional attributes: `left` and `right`. These attributes represent the range of nodes that are descendants of a particular node. By using nested sets, querying for all descendants of a node or determining the depth of a node becomes more efficient compared to using adjacency lists.

// Example implementation of nested sets in PHP

class NestedSet {
    private $db;

    public function __construct($db) {
        $this->db = $db;
    }

    public function getDescendants($nodeId) {
        $query = "SELECT * FROM nodes WHERE left >= (SELECT left FROM nodes WHERE id = :nodeId) AND right <= (SELECT right FROM nodes WHERE id = :nodeId)";
        $stmt = $this->db->prepare($query);
        $stmt->bindParam(':nodeId', $nodeId);
        $stmt->execute();
        return $stmt->fetchAll();
    }

    public function getNodeDepth($nodeId) {
        $query = "SELECT COUNT(*) AS depth FROM nodes WHERE left < (SELECT left FROM nodes WHERE id = :nodeId) AND right > (SELECT right FROM nodes WHERE id = :nodeId)";
        $stmt = $this->db->prepare($query);
        $stmt->bindParam(':nodeId', $nodeId);
        $stmt->execute();
        $result = $stmt->fetch();
        return $result['depth'];
    }
}

// Usage
$db = new PDO('mysql:host=localhost;dbname=mydatabase', 'username', 'password');
$nestedSet = new NestedSet($db);

// Get all descendants of node with id 1
$descendants = $nestedSet->getDescendants(1);

// Get the depth of node with id 1
$depth = $nestedSet->getNodeDepth(1);