PHP语法错误排查及Person/Father类合规设计求助
Fixed Solution with Validation & Chained Calls
Let's fix your code to meet all the required validation rules and support proper chained method calls. The original code has several critical issues with structure, validation logic, and chained call functionality—here's a complete corrected version with explanations:
Original Code Issues
- The
Fatherclass didn't return instances from its setter methods, breaking chained calls entirely. - Static properties in
Fathercaused shared data across instances (a big problem if you create multiple father objects). - Validation logic was broken and scattered, with incorrect syntax that didn't properly assign or validate data.
- No proper error handling for invalid input, so bad data could silently fail or corrupt the output.
- Incorrect cross-class method calls (like trying to call
Person::age()statically fromFather). - Missing checks for the father-child age difference and matching last names.
Corrected Code
<?php class InvalidPersonDataException extends Exception {} class Father { private $firstName; private $lastName; private $age; private function __construct() {} public static function firstName(string $name): self { // Validate first name: 3-15 chars, no digits if (strlen($name) < 3 || strlen($name) > 15 || preg_match('/\d/u', $name)) { throw new InvalidPersonDataException("Father first name must be 3-15 characters, no digits allowed"); } $instance = new self(); $instance->firstName = $name; return $instance; } public function lastName(string $name): self { if (strlen($name) < 3 || strlen($name) > 15 || preg_match('/\d/u', $name)) { throw new InvalidPersonDataException("Father last name must be 3-15 characters, no digits allowed"); } $this->lastName = $name; return $this; } public function age(int $age): self { if ($age < 18 || $age > 130) { throw new InvalidPersonDataException("Father age must be between 18 and 130"); } $this->age = $age; return $this; } public function getLastName(): string { if (!isset($this->lastName)) { throw new InvalidPersonDataException("Father last name is not set"); } return $this->lastName; } public function getAge(): int { if (!isset($this->age)) { throw new InvalidPersonDataException("Father age is not set"); } return $this->age; } public function toArray(): array { if (!isset($this->firstName, $this->lastName, $this->age)) { throw new InvalidPersonDataException("Father has missing required properties"); } return [ 'firstName' => $this->firstName, 'lastName' => $this->lastName, 'age' => $this->age ]; } } class Person { private $firstName; private $lastName; private $age; private $father; private function __construct() {} public static function firstName(string $name): self { if (strlen($name) < 3 || strlen($name) > 15 || preg_match('/\d/u', $name)) { throw new InvalidPersonDataException("Person first name must be 3-15 characters, no digits allowed"); } $instance = new self(); $instance->firstName = $name; return $instance; } public function lastName(string $name): self { if (strlen($name) < 3 || strlen($name) > 15 || preg_match('/\d/u', $name)) { throw new InvalidPersonDataException("Person last name must be 3-15 characters, no digits allowed"); } $this->lastName = $name; return $this; } public function age(int $age): self { if ($age < 1 || $age > 130) { throw new InvalidPersonDataException("Person age must be between 1 and 130"); } $this->age = $age; return $this; } public function setFather(Father $father): self { // Ensure person has last name set first if (!isset($this->lastName)) { throw new InvalidPersonDataException("Set person's last name before assigning a father"); } // Validate matching last names if ($this->lastName !== $father->getLastName()) { throw new InvalidPersonDataException("Person's last name must match father's last name"); } // Ensure person has age set first if (!isset($this->age)) { throw new InvalidPersonDataException("Set person's age before assigning a father"); } // Validate father is at least 18 years older if ($father->getAge() < $this->age + 18) { throw new InvalidPersonDataException("Father must be at least 18 years older than the person"); } $this->father = $father; return $this; } public function toArray(): array { if (!isset($this->firstName, $this->lastName, $this->age)) { throw new InvalidPersonDataException("Person has missing required properties"); } $result = [ 'firstName' => $this->firstName, 'lastName' => $this->lastName, 'age' => $this->age ]; if (isset($this->father)) { $result['father'] = $this->father->toArray(); } return $result; } } // Test your example try { $father = Father::firstName('Esaaro')->lastName('Ozaaraa')->age(42); $personData = Person::firstName("Soobaasaa")->lastName("Ozaaraa")->age(17)->setFather($father)->toArray(); print_r($personData); } catch (InvalidPersonDataException $e) { echo "Error: " . $e->getMessage(); }
What This Fixes
1. Chained Call Support
Every setter method returns $this, so you can chain calls exactly like your example:
$father = Father::firstName('Esaaro')->lastName('Ozaaraa')->age(42); Person::firstName("Soobaasaa")->lastName("Ozaaraa")->age(17)->setFather($father)->toArray();
2. All Validation Rules Enforced
- Names: 3-15 characters, no digits (supports Unicode names like your examples)
- Ages:
- Person: 1-130 (integer only)
- Father: 18-130 (integer only)
- Father-Person Checks:
setFather()only accepts aFatherobject (enforced via type hinting)- Father is at least 18 years older than the person
- Father and person share the same last name
3. Proper Error Handling
The custom InvalidPersonDataException throws clear, specific errors whenever validation fails, so you know exactly what's wrong (e.g., "Father must be at least 18 years older than the person").
4. Correct Array Output
For your test case, the output will be:
Array ( [firstName] => Soobaasaa [lastName] => Ozaaraa [age] => 17 [father] => Array ( [firstName] => Esaaro [lastName] => Ozaaraa [age] => 42 ) )
内容的提问来源于stack exchange,提问作者Mehdi Jalali
相关产品推荐
相关产品推荐

