Supercharge Your PHP Enums with cerbero90/enum

Enums in PHP are like the unsung heroes of your code—they quietly make your life easier, offering a clean way to define a fixed set of values. Introduced in PHP 8.1, native enums already streamlined a lot of workflows, but you know how it goes: there’s always room for improvement. That’s where the cerbero90/enum package comes in. Think of it as PHP enums on steroids—more powerful, more flexible, and surprisingly easy to use.

Why Bother with Enums Anyway?

Before we dive into the good stuff, let’s answer the obvious question: why should you care about enums? Well, imagine managing user roles across an app. You could use strings like ‘admin’, ‘editor’, ‘user’ scattered everywhere, but that’s a recipe for typos and bugs. Enums give you a type-safe way to handle these values. Clean, consistent, and no more mysterious bugs from misspelled roles. Nice, right?

Enter cerbero90/enum: The Power Boost You Didn’t Know You Needed

The cerbero90/enum package takes PHP enums and cranks them up a notch. It adds methods and features that make working with enums more intuitive and, dare I say, enjoyable.

First things first, installation is a breeze:

composer require cerbero/enum

No fuss, no mess.

Real-World Example: Handling Order Statuses

Let’s say you’re building an e-commerce app. Orders can be ‘Pending’, ‘Shipped’, ‘Delivered’, or ‘Cancelled’. With cerbero90/enum, defining this looks clean and readable:

use Cerbero\Enum\Concerns\Enumerates;

enum OrderStatus
{
    use Enumerates;

    case Pending;
    case Shipped;
    case Delivered;
    case Cancelled;
}

Looks familiar, right? But here’s where it gets interesting.

Checking If a Status Exists

Want to check if a status exists? Simple:

OrderStatus::has('Pending'); // true
OrderStatus::has('Refunded'); // false

No more clunky in_array() checks or custom validation logic.

Comparing Values Like a Pro

Let’s say you’re processing orders and need to check statuses. Here’s how effortless it is:

$status = OrderStatus::Shipped;

if ($status->is('Shipped')) {
    // Notify customer
}

if ($status->isNot('Cancelled')) {
    // Proceed with delivery
}

Feels almost too easy, doesn’t it?

Add Context with Metadata

Sometimes a simple label doesn’t cut it. Maybe you want to attach descriptions or codes. cerbero90/enum has you covered with the Meta attribute.

use Cerbero\Enum\Attributes\Meta;

enum OrderStatus
{
    use Enumerates;

    #[Meta(description: 'Order is waiting to be processed')]
    case Pending;

    #[Meta(description: 'Order has been shipped to customer')]
    case Shipped;

    #[Meta(description: 'Order delivered successfully')]
    case Delivered;

    #[Meta(description: 'Order was cancelled by user or admin')]
    case Cancelled;
}

Retrieving that metadata? Easy:

echo OrderStatus::Pending->description(); // 'Order is waiting to be processed'

Filter and Retrieve Like a Boss

Need to work with specific sets of statuses? You can filter them effortlessly:

$activeStatuses = OrderStatus::except('Cancelled');
$shippingStatuses = OrderStatus::only('Pending', 'Shipped');

Suddenly, your code is more readable and maintainable.

Magic Methods—Because Why Not?

This package even throws in some magic methods. Want to get the value of a case?

OrderStatus::Pending(); // 'Pending'

It’s the small conveniences that make a big difference.

So, Is cerbero90/enum Worth It?

Honestly? If you’re serious about clean, maintainable PHP code, it’s a no-brainer. This package takes enums from good to great. Whether you’re managing order statuses, user roles, or any fixed set of values, cerbero90/enum saves time and headaches.

Why settle for basic when you can build smarter? Give it a shot, and your future self will thank you.

Ready to level up your enums?

Happy coding!

white and tan english bulldog lying on black rug

Lazy Objects in PHP 8.4: Revolutionizing Performance and Code Maintainability

With the release of PHP 8.4, developers are introduced to Lazy Objects, a feature designed to enhance performance and streamline codebases. In this article, we’ll explore what lazy objects are, how to use them, and how they can aid in refactoring your code for better efficiency and maintainability.

What Are Lazy Objects?

Lazy objects are a mechanism in PHP 8.4 that allows objects to defer their initialization until they are actually used. Instead of instantiating an object and loading all its properties immediately, the object remains in a “lazy” state, initializing itself only when a method or property is accessed.

This is particularly beneficial for objects that are resource-intensive to initialize, such as those relying on large datasets, external APIs, or complex computations. By deferring initialization, applications can save memory and reduce startup times.


How to Use Lazy Objects in PHP 8.4

Using lazy objects in PHP 8.4 is straightforward, thanks to the new LazyObject class provided by the SPL (Standard PHP Library). Here’s a step-by-step guide:

1. Create a Lazy Object

To create a lazy object, use the LazyObject wrapper around an existing class.

use LazyObject\LazyObject;

class ExpensiveClass {
    public function __construct() {
        echo "Initializing ExpensiveClass...\n";
        // Simulate heavy initialization
        sleep(2);
    }

    public function getData(): string {
        return "Here is some data!";
    }
}

// Create a lazy version of ExpensiveClass
$lazyObject = new LazyObject(ExpensiveClass::class);

// The object is not initialized yet.
echo "LazyObject created!\n";

// Accessing a method triggers initialization.
echo $lazyObject->getData(); // Outputs: Initializing ExpensiveClass...
                              //         Here is some data!

2. Customize Initialization Logic

You can control how the underlying object is instantiated by passing a callable to LazyObject.

$lazyObject = new LazyObject(
    ExpensiveClass::class,
    fn() => new ExpensiveClass('custom argument')
);

Refactoring Your Code with Lazy Objects

Lazy objects can be a powerful tool for refactoring, especially in codebases with performance bottlenecks or heavy reliance on resource-intensive objects. Here’s how to approach refactoring:

1. Identify Candidates for Laziness

  • Look for objects that are instantiated but not always used.
  • Consider objects with heavy initialization logic or those that rely on large datasets.

2. Replace Eager Initialization

  • Replace direct instantiation with lazy objects, ensuring they are only initialized when accessed.
// Before
$expensiveObject = new ExpensiveClass();

if ($condition) {
    $result = $expensiveObject->process();
}

// After
$expensiveObject = new LazyObject(ExpensiveClass::class);

if ($condition) {
    $result = $expensiveObject->process(); // Initialized only when needed
}

3. Decouple Dependencies

  • Lazy objects work well with dependency injection. Replace tightly coupled dependencies with lazy-loaded ones to improve modularity.

Benefits of Lazy Objects

1. Improved Performance

  • By deferring initialization, lazy objects reduce memory usage and speed up application startup times, especially in large applications.

2. Better Resource Management

  • Lazy initialization ensures that resources are allocated only when necessary, preventing unnecessary overhead in cases where certain objects are not used during execution.

3. Easier Refactoring

  • Lazy objects encourage cleaner and more modular code by decoupling object initialization from application logic.

4. Enhanced Testability

  • With lazy objects, testing becomes easier since you can mock or substitute objects without triggering expensive initialization logic.

When to Avoid Lazy Objects

While lazy objects offer numerous benefits, they may not always be the right choice:

  • Simplicity over Laziness: For lightweight objects with minimal initialization, the overhead of adding laziness may outweigh the benefits.
  • Predictable Initialization: In cases where deterministic initialization is critical, lazy objects may introduce complexity.

Conclusion

Lazy objects in PHP 8.4 are a game-changer for performance optimization and maintainable code. By deferring initialization to the moment of use, they enable developers to create more efficient, modular, and testable applications. As you explore this feature, consider its potential to refactor heavy codebases and tackle performance challenges head-on.

Adopting lazy objects will not only improve your code’s efficiency but also set the stage for a cleaner and more scalable application architecture.

Using empty() for Cleaner PHP Conditions

When writing conditional statements in PHP, especially with multiple conditions, readability is key to creating maintainable code. PHP provides functions like empty() to simplify checks for variables that might have a null, false, empty string, or zero value. For instance, instead of checking if a variable is null or not set with multiple conditions, empty() handles this in a single call. This function is helpful when you want to verify that a value is essentially “empty” without having to specify each potential case. In the example above, empty($verificationStatus) evaluates as true if $verificationStatus is null, an empty string, or 0, making the condition straightforward and less error-prone.

if ($verificationStatus !== null && $verificationStatus !== '' && $verificationStatus !== false && $verificationStatus !== '0' && $paymentFlag !== '0') {
    // Perform some action
}

VS

if (empty($verificationStatus) && $paymentFlag !== '0') {
    // Perform some action
}

Using empty() in combination with other conditions can enhance the logic of your statements. In cases where you need a specific check, such as $paymentFlag !== '0', combining empty() with a precise condition gives you both clarity and control. This approach also helps avoid unexpected behavior, especially with falsy values like ‘0’, which might pass an empty() check but are still valid values. By thoughtfully combining empty() with explicit conditions, you can keep your code both readable and reliable, ensuring each condition behaves exactly as intended.

PHP[tek] 2023 slides

Did you miss PHP[tek] 2023 last week. Well, you can catch up and checkout what you missed through the joind.in list of slides! also, checkout https://phptek.tv/ for all the talks!

php 8.2

PHP 8.2: null, false, and true as stand-alone types

PHP 8.2 introduces a new feature that allows null, false, and true to be treated as stand-alone types. This means that these values can now be used as the types for function arguments and return values, rather than just being reserved for use as boolean values.

To use this feature, you can simply declare a function argument or return type as “null”, “false”, or “true”. For example:

function example(null $value) : false {
  return $value === null ? false : true;
}

In this example, the function example takes a single argument of type null and returns a value of type false. If the value of $value is null, the function returns false, otherwise it returns true.

One potential use case for this feature is to provide more explicit type hints for functions that are intended to work with these special values. For example, consider the following function:

function getErrorStatus(int $code) : ?string {
  if ($code === 404) {
    return null;
  } else {
    return 'Unknown error';
  }
}

In this example, the function getErrorStatus takes an integer $code and returns a string or null, depending on the value of $code. Prior to PHP 8.2, the return type of this function would have to be declared as ?string, which can be somewhat ambiguous. With the new stand-alone types feature, we can be more explicit and declare the return type as null, like so:

function getErrorStatus(int $code) : null {
  if ($code === 404) {
    return null;
  } else {
    return 'Unknown error';
  }
}

This makes it clear to anyone reading the code that the function is intended to return a value of type null in certain circumstances.

Another potential use case is for functions that are intended to return only true or false. For example:

function isValidEmail(string $email) : true {
  return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

In this example, the function isValidEmail takes a string $email and returns a value of type true if the string is a valid email address, or false otherwise. With the stand-alone types feature, we can declare the return type as true, which makes it clear that the function is intended to return only true or false.

Overall, the stand-alone types feature in PHP 8.2 provides a useful new way to specify the types of function arguments and return values, especially when working with special values like null, true, and false. It can help make your code more explicit and easier to understand for other developers.

php 8.2

PHP 8.2 : Disjunctive Normal Form (DNF) Types

PHP 8.2 introduces a new feature called Disjunctive Normal Form (DNF) Types, which allow developers to specify complex type constraints using logical OR and AND operators. This can be useful in cases where a variable may need to satisfy multiple type constraints at once.

To use DNF Types, developers can use the | operator to specify that a variable must satisfy at least one of multiple type constraints, and the & operator to specify that a variable must satisfy all of multiple type constraints.

For example, consider the following code:

function process_data(int | string | array $data) {
// code to process data
}process_data(123); // valid
process_data(“hello”); // valid
process_data([“a”, “b”, “c”]); // valid
process_data(true); // invalid

In this case, the process_data function is expecting a variable that is either an integer, a string, or an array. This allows the function to handle different types of data without requiring multiple versions of the function for each type.

We can also use the & operator to specify that a variable must satisfy multiple type constraints at once. For example:

function process_data(array & string $data) {
// code to process data
}process_data(123); // invalid
process_data(“hello”); // valid

In this case, the process_data function is expecting a variable that is both an integer and a string. This would be a rare case, but it illustrates how the & operator can be used to specify complex type constraints.

It’s important to note that DNF Types are not the same as union types. Union types allow you to specify multiple possible types for a single variable, while DNF Types allow you to specify complex type constraints using logical operators.

Overall, DNF Types provide a convenient way for developers to specify complex type constraints using logical OR and AND operators, making it easier to ensure that data is being passed correctly throughout the code.

PHP tempfile function

PHP’s tempfile() function is a useful tool for creating temporary files that are automatically deleted when the PHP script finishes executing. This can be useful in cases where you need to store data temporarily, such as when processing a large amount of data that cannot fit in memory.

To create a temporary file, you can use the tempfile() function like this:

$temp_file = tempfile();

This will create a new temporary file and return a file handle that you can use to read from or write to the file. You can also specify a custom directory for the temporary file by passing it as an argument to the function:

$temp_file = tempfile("/path/to/custom/directory");

Once you are finished using the temporary file, you can close the file handle like this:

fclose($temp_file);

This will close the file and delete it from the system.

It’s important to note that the tempfile() function creates files with a randomly generated name, so it’s not possible to predict the exact file name beforehand. This can make it difficult to access the file if you need to pass its name to other functions or scripts.

One way to work around this limitation is to use the tempnam() function, which allows you to specify a custom prefix for the file name. For example:

$temp_file = tempnam("/path/to/custom/directory", "myprefix_");

This will create a temporary file with a name like “myprefix_abcdefg”, where “abcdefg” is a randomly generated string.

Overall, the tempfile() function is a useful tool for creating temporary files that are automatically deleted when the PHP script finishes executing. It can be used in conjunction with other functions like tempnam() to give you more control over the file names.

php 8.2

PHP 8.2 : Readonly Classes

PHP 8.2 introduces a new feature called readonly classes, which allow developers to mark certain class properties as read-only. This means that once a property has been set, it cannot be changed by any code within the class or its descendants.

To mark a property as read-only, developers can use the readonly keyword in the class definition. For example:

class User {
public readonly int $id;
public string $username;

public function __construct(int $id, string $username) {
$this->id = $id;
$this->username = $username;
}
}

In this case, the $id property is marked as read-only, while the $username property can be changed.

Readonly classes can be useful in cases where certain data should not be modified after it is set. For example, if a user’s ID is set when they are created and should never be changed, marking the $id property as read-only can help prevent any accidental changes.

Another benefit of readonly classes is that they can help improve the performance of certain operations. Because the PHP interpreter knows that a read-only property cannot be changed, it can optimize the code accordingly. This can lead to faster execution times in some cases.

It’s important to note that readonly classes are not a replacement for immutability. While read-only properties cannot be changed, they can still be accessed and their values can be used in calculations or other operations. If you need to ensure that a class and its properties are completely immutable, you should use an immutable class instead.

Overall, readonly classes provide a useful way for developers to mark certain class properties as unchangeable, helping to prevent accidental changes and improve performance in some cases.

php 8.2

PHP 8.2 : Union Types

PHP 8.2 introduces a new feature called union types, which allows developers to specify multiple types for a single variable. This can be useful in cases where a variable may hold different types of data at different points in the code.

For example, consider the following code:

Copy codefunction get_username(int $user_id) : string {
  // code to retrieve username from database
  return $username;
}

$username = get_username(123);

In this case, we are expecting the get_username function to return a string containing the username of the user with the given ID. However, if the ID is not found in the database, the function may return null instead. To account for this possibility, we can use union types to specify that the return type of the function can be either a string or null. The revised function would look like this:

Copy codefunction get_username(int $user_id) : ?string {
  // code to retrieve username from database
  return $username;
}

Now, the function is explicitly telling the PHP interpreter that it may return either a string or null, and the interpreter will not throw an error if null is returned.

Union types can also be used in function arguments. For example, consider the following code:

Copy codefunction log_message(string | array $message) {
  // code to log message to a file
}

log_message("Error occurred");
log_message(["Error", "File not found"]);

In this case, the log_message function is expecting either a string or an array as its argument. This allows the function to handle different types of messages without requiring multiple versions of the function for each type.

Overall, union types provide a convenient way for developers to specify multiple types for a single variable, making it easier to ensure that data is being passed correctly throughout the code.

Top 5 php 8.2 features

  1. Union Types: This feature allows developers to specify multiple types for a single variable, making it easier to ensure that data is being passed correctly throughout the code.
  2. Nullsafe Operator: This operator allows developers to chain method calls without worrying about null references, which can cause errors in the code.
  3. Improved Constructor Property Promotion: This feature allows developers to reduce the amount of code needed when defining class properties and their corresponding constructor arguments.
  4. Just-In-Time Compilation: PHP 8.2 includes a just-in-time (JIT) compiler, which improves the performance of certain operations by compiling them ahead of time.
  5. Weak Map: This data structure allows developers to store key-value pairs where the keys are objects and the values can be any type. It is useful for storing data that is only relevant within a specific context.

In summary, PHP 8.2 introduces several new features that aim to improve the efficiency and reliability of code. Union types and the nullsafe operator make it easier to ensure data is being passed correctly, while constructor property promotion and the weak map data structure reduce the amount of code needed. The inclusion of a JIT compiler also improves the performance of certain operations.