PHP 8.3+ Modernization
This fork leverages PHP 8.3+ features for improved type safety, performance, and developer experience.
PHP 8.3+ Features Used
Enumerations (Enums)
Replace magic strings with type-safe enums:
use RenokiCo\PhpK8s\Enums\PodPhase;
use RenokiCo\PhpK8s\Enums\ServiceType;
use RenokiCo\PhpK8s\Enums\RestartPolicy;
// Before (strings)
if ($pod->getStatus()['phase'] === 'Running') { }
// After (enums)
if ($pod->getPodPhase() === PodPhase::RUNNING) { }Readonly Properties
Immutable class properties:
class K8sResource
{
public readonly string $apiVersion;
public readonly string $kind;
}Match Expressions
Cleaner conditional logic:
$action = match ($pod->getPodPhase()) {
PodPhase::RUNNING => 'monitor',
PodPhase::PENDING => 'wait',
PodPhase::FAILED => 'alert',
PodPhase::SUCCEEDED => 'cleanup',
default => 'investigate',
};Typed Class Constants (PHP 8.3)
PHP 8.3 adds support for typed constants in classes and interfaces:
class K8sResource
{
public const string DEFAULT_NAMESPACE = 'default';
public const int DEFAULT_REPLICAS = 1;
}#[\Override] Attribute (PHP 8.3)
Explicitly mark methods that override a parent method, catching typos at compile time:
class K8sPod extends K8sResource
{
#[\Override]
public function toArray(): array
{
// ...
}
}json_validate() (PHP 8.3)
Validate JSON without decoding it:
// Before
$decoded = json_decode($json);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \InvalidArgumentException('Invalid JSON');
}
// After (PHP 8.3)
if (! json_validate($json)) {
throw new \InvalidArgumentException('Invalid JSON');
}Nullable Types & Union Types
Better type safety:
function getPod(string $name, ?string $namespace = null): ?K8sPod
{
// ...
}
function handleResult(K8sPod|array $result): void
{
// ...
}Available Enums
PodPhase
namespace RenokiCo\PhpK8s\Enums;
enum PodPhase: string
{
case PENDING = 'Pending';
case RUNNING = 'Running';
case SUCCEEDED = 'Succeeded';
case FAILED = 'Failed';
case UNKNOWN = 'Unknown';
}Usage:
$phase = $pod->getPodPhase();
if ($phase === PodPhase::RUNNING) {
echo "Pod is active";
}
// Get string value
echo $phase->value; // "Running"ServiceType
enum ServiceType: string
{
case CLUSTER_IP = 'ClusterIP';
case NODE_PORT = 'NodePort';
case LOAD_BALANCER = 'LoadBalancer';
case EXTERNAL_NAME = 'ExternalName';
}RestartPolicy
enum RestartPolicy: string
{
case ALWAYS = 'Always';
case ON_FAILURE = 'OnFailure';
case NEVER = 'Never';
}Protocol
enum Protocol: string
{
case TCP = 'TCP';
case UDP = 'UDP';
case SCTP = 'SCTP';
}PullPolicy
enum PullPolicy: string
{
case ALWAYS = 'Always';
case IF_NOT_PRESENT = 'IfNotPresent';
case NEVER = 'Never';
}ContainerState
enum ContainerState: string
{
case WAITING = 'waiting';
case RUNNING = 'running';
case TERMINATED = 'terminated';
}EventType
enum EventType: string
{
case NORMAL = 'Normal';
case WARNING = 'Warning';
}WatchEventType
enum WatchEventType: string
{
case ADDED = 'ADDED';
case MODIFIED = 'MODIFIED';
case DELETED = 'DELETED';
}Migration Examples
Pod Status Checking
// Before
function isPodReady($pod): bool
{
return $pod->getStatus()['phase'] === 'Running';
}
// After
use RenokiCo\PhpK8s\Enums\PodPhase;
function isPodReady(K8sPod $pod): bool
{
return $pod->getPodPhase() === PodPhase::RUNNING;
}Service Type Handling
// Before
function getServiceUrl($service): ?string
{
if ($service->getType() === 'LoadBalancer') {
return $service->getLoadBalancerIp();
}
return null;
}
// After
use RenokiCo\PhpK8s\Enums\ServiceType;
function getServiceUrl(K8sService $service): ?string
{
return match ($service->getType()) {
ServiceType::LOAD_BALANCER => $service->getLoadBalancerIp(),
ServiceType::NODE_PORT => $service->getNodePortUrl(),
default => null,
};
}Watch Event Processing
// Before
$cluster->pod()->watchAll(function ($type, $pod) {
if ($type === 'ADDED') {
echo "New pod created";
} elseif ($type === 'MODIFIED') {
echo "Pod updated";
} elseif ($type === 'DELETED') {
echo "Pod deleted";
}
});
// After
use RenokiCo\PhpK8s\Enums\WatchEventType;
$cluster->pod()->watchAll(function ($type, $pod) {
match ($type) {
WatchEventType::ADDED->value => print("New pod created"),
WatchEventType::MODIFIED->value => print("Pod updated"),
WatchEventType::DELETED->value => print("Pod deleted"),
};
});Type Hints and Return Types
All methods now have proper type hints:
// Before
public function setReplicas($replicas)
{
return $this->setAttribute('spec.replicas', $replicas);
}
// After
public function setReplicas(int $replicas): self
{
return $this->setAttribute('spec.replicas', $replicas);
}Benefits
1. IDE Support
Better autocomplete and type checking:
$pod->getPodPhase()-> // IDE shows enum methods and cases2. Compile-Time Errors
Catch mistakes early:
// This won't work (caught by IDE/static analysis)
if ($pod->getPodPhase() === 'Running') { // Type mismatch
// ...
}
// Correct
if ($pod->getPodPhase() === PodPhase::RUNNING) { // ✓
// ...
}3. Refactoring Safety
Renaming becomes safer:
// All usages of PodPhase::RUNNING can be found and updated
// String 'Running' could be anywhere in the codebase4. Performance
Enums are more performant than strings for comparisons.
Backward Compatibility
Getting String Values
If you need the string value:
$phase = $pod->getPodPhase();
$phaseString = $phase->value; // "Running"
// Or inline
$phaseString = $pod->getPodPhase()->value;Working with Legacy Code
If integrating with code expecting strings:
function legacyFunction(string $phase): void
{
// Expects string
}
// Convert enum to string
legacyFunction($pod->getPodPhase()->value);Static Analysis
Run Psalm to catch type errors:
vendor/bin/psalmExample output:
ERROR: InvalidArgument - Expected PodPhase, string provided
if ($pod->getPodPhase() === 'Running') {Recommended Practices
Import enums at the top of your files:
phpuse RenokiCo\PhpK8s\Enums\{PodPhase, ServiceType, RestartPolicy};Use match expressions for complex conditions:
php$action = match ($pod->getPodPhase()) { PodPhase::RUNNING => 'monitor', PodPhase::FAILED => 'alert', default => 'wait', };Add type hints to your functions:
phpfunction deployPod(KubernetesCluster $cluster, string $name): K8sPod { // ... }Use readonly for immutable data:
phpreadonly class DeploymentConfig { public function __construct( public string $name, public int $replicas, public string $image, ) {} }Use typed class constants (PHP 8.3):
phpclass ApiVersions { public const string APPS = 'apps/v1'; public const string CORE = 'v1'; public const string NETWORKING = 'networking.k8s.io/v1'; }
See Also
- Upstream to Fork Migration - Migrating from upstream
- Fork Differences - All differences explained
- Examples - See modern PHP in action
PHP 8.3+ modernization guide for cuppett/php-k8s fork