← Назад к вопросам

Приведи пример использования рефлексии в бизнес-логике

2.0 Middle🔥 121 комментариев
#PHP Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Reflection u PHP - Prakticki primjeri

Reflection (Refleksija) je mehanizam koji omogucava inspektovanje klasa, metoda, svojstava i parametara tokom izvrsavanja programa. Veoma je mocan u rjesavanju realnih problema.

Primjer 1: Serializer/Deserializer

class JsonSerializer {
    public function serialize(object $obj): string {
        $reflection = new ReflectionClass($obj);
        $data = [];
        
        foreach ($reflection->getProperties(ReflectionProperty::IS_PUBLIC) as $prop) {
            $data[$prop->getName()] = $prop->getValue($obj);
        }
        
        return json_encode($data);
    }
    
    public function deserialize(string $json, string $className): object {
        $data = json_decode($json, true);
        $reflection = new ReflectionClass($className);
        $obj = $reflection->newInstanceWithoutConstructor();
        
        foreach ($data as $key => $value) {
            $prop = $reflection->getProperty($key);
            $prop->setAccessible(true);
            $prop->setValue($obj, $value);
        }
        
        return $obj;
    }
}

// Upotreba
class User {
    public string $name;
    public string $email;
}

$user = new User();
$user->name = 'John';
$user->email = 'john@example.com';

$serializer = new JsonSerializer();
$json = $serializer->serialize($user);
echo $json; // {"name":"John","email":"john@example.com"}

$restored = $serializer->deserialize($json, User::class);
echo $restored->name; // John

Primjer 2: ORM - Mapiranje baze na objekte

class ORM {
    public function mapResultToObject(array $row, string $className): object {
        $reflection = new ReflectionClass($className);
        $instance = new $className();
        
        foreach ($reflection->getProperties() as $property) {
            $propertyName = $property->getName();
            
            if (isset($row[$propertyName])) {
                $property->setAccessible(true);
                $type = $property->getType();
                $value = $row[$propertyName];
                
                // Kastovanje tipa
                if ($type && $type->getName() === 'int') {
                    $value = (int)$value;
                } elseif ($type && $type->getName() === 'float') {
                    $value = (float)$value;
                }
                
                $property->setValue($instance, $value);
            }
        }
        
        return $instance;
    }
}

class Product {
    public int $id;
    public string $name;
    public float $price;
}

$orm = new ORM();
$row = ['id' => 1, 'name' => 'Laptop', 'price' => 999.99];
$product = $orm->mapResultToObject($row, Product::class);
echo $product->price; // 999.99 (float)

Primjer 3: Validator sa Atributima

#[Attribute]
class Required {}

#[Attribute]
class Email {}

#[Attribute]
class MinLength {
    public function __construct(public int $length) {}
}

class Validator {
    public function validate(object $obj): array {
        $errors = [];
        $reflection = new ReflectionClass($obj);
        
        foreach ($reflection->getProperties() as $property) {
            $value = $property->getValue($obj);
            $attributes = $property->getAttributes();
            
            foreach ($attributes as $attr) {
                $attrInstance = $attr->newInstance();
                
                if ($attrInstance instanceof Required && empty($value)) {
                    $errors[] = $property->getName() . ' je obavezno';
                }
                
                if ($attrInstance instanceof Email && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
                    $errors[] = $property->getName() . ' nije validan email';
                }
                
                if ($attrInstance instanceof MinLength && strlen($value) < $attrInstance->length) {
                    $errors[] = $property->getName() . ' mora biti duzi od ' . $attrInstance->length;
                }
            }
        }
        
        return $errors;
    }
}

class UserForm {
    #[Required]
    #[Email]
    public string $email;
    
    #[Required]
    #[MinLength(8)]
    public string $password;
}

$form = new UserForm();
$form->email = 'invalid';
$form->password = '123';

$validator = new Validator();
$errors = $validator->validate($form);
print_r($errors);
// Ispisuje sve greske: email nije validan, password je prekratak

Primjer 4: Dependency Injection Container

class DIContainer {
    private array $services = [];
    
    public function register(string $serviceName, string $className): void {
        $this->services[$serviceName] = $className;
    }
    
    public function get(string $serviceName): object {
        $className = $this->services[$serviceName];
        $reflection = new ReflectionClass($className);
        
        // Pronalazi konstruktor
        $constructor = $reflection->getConstructor();
        
        if ($constructor === null) {
            return new $className();
        }
        
        // Dobija parametre konstruktora
        $params = [];
        foreach ($constructor->getParameters() as $param) {
            $paramType = $param->getType();
            
            if ($paramType && !$paramType->isBuiltin()) {
                // Rekurzivno resava zavisnosti
                $depClassName = $paramType->getName();
                $params[] = $this->get($depClassName);
            }
        }
        
        return $reflection->newInstanceArgs($params);
    }
}

interface LoggerInterface {}
class Logger implements LoggerInterface {}
class UserService {
    public function __construct(private LoggerInterface $logger) {}
}

$container = new DIContainer();
$container->register(LoggerInterface::class, Logger::class);
$container->register(UserService::class, UserService::class);

$userService = $container->get(UserService::class);
// UserService je automatski instanciran sa Logger zavisnoscu

Primjer 5: Docblock Parser

class DocBlockParser {
    public function getMethodDocumentation(string $className, string $methodName): ?string {
        $reflection = new ReflectionMethod($className, $methodName);
        return $reflection->getDocComment();
    }
    
    public function getParamDescription(string $className, string $methodName, string $paramName): ?string {
        $reflection = new ReflectionMethod($className, $methodName);
        $docComment = $reflection->getDocComment();
        
        if (preg_match("/@param\s+\S+\s+\$" . $paramName . "\s+(.+)/", $docComment, $matches)) {
            return $matches[1];
        }
        
        return null;
    }
}

class PaymentService {
    /**
     * Procesa plaćanje
     * @param float $amount Iznos koji se plaća
     */
    public function process(float $amount): void {}
}

$parser = new DocBlockParser();
echo $parser->getParamDescription(PaymentService::class, 'process', 'amount');
// Ispisuje: Iznos koji se plaća

Prednosti Refleksije

  • Automatizacija - ORM, validatori, serializers
  • Fleksibilnost - dinamicko ponasanje bez hardkoda
  • Framework mogucnosti - Dependency injection, atributi
  • Introspection - Analiza koda tokom izvrsavanja

Nedostaci

  • Performanse - Refleksija je spora, cachaj gdje god je moguce
  • Type Safety - Runtime problemi, greske tek pri izvrsavanju
  • Citljivost - Magicni kod, teze za debugging

Best Practices

// Cachuj reflection objekti
class CachedReflection {
    private static array $cache = [];
    
    public static function getClass(string $className): ReflectionClass {
        if (!isset(self::$cache[$className])) {
            self::$cache[$className] = new ReflectionClass($className);
        }
        return self::$cache[$className];
    }
}

Zakljucak: Reflection je mocan alat za pisanje fleksibilnog i generalnog koda koji se automatski prilagodava razlicitim klasama i strukturama.