You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 Father class didn't return instances from its setter methods, breaking chained calls entirely.
  • Static properties in Father caused 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 from Father).
  • 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 a Father object (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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:28:28