- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
PHP 8.4 Features You'll Actually Use (and One Deprecation That Will Find You)
About Post
Every PHP release comes with a changelog long enough to scroll for a while. Most of it is important to someone. Very little of it changes the code you write on a normal Tuesday.
PHP 8.4, released in November 2024, is different. A few of its features genuinely change how you design everyday classes, and they've had a few months to settle in now. Here are the ones I think you'll actually use, plus one deprecation that's going to find you whether you go looking for it or not.
1. Property hooks: goodbye, boilerplate getters and setters
For years, PHP gave you two choices for a class field. Make it public and accept that anyone can put anything in it, or make it private and write a getEmail() and setEmail() pair just to add one line of logic.
Property hooks let you attach that logic directly to the field:
class Tenant
{
public string $email {
set => strtolower(trim($value));
}
public int $rentCents {
set(int $value) {
if ($value < 0) {
throw new InvalidArgumentException('Rent cannot be negative.');
}
$this->rentCents = $value;
}
}
}
$tenant = new Tenant();
$tenant->email = ' [email protected] ';
echo $tenant->email; // [email protected]
The short form set => expression; stores whatever the expression returns. The long form gives you a full block. Callers just read and write $tenant->email, with no method calls, and you can add a hook later without changing a single caller. That last point is the real win: you can start with a plain public field and add rules only when you need them.
You can also create virtual fields that are computed on read and have no stored value at all:
class Person
{
public function __construct(
public string $first,
public string $last,
) {}
public string $fullName {
get => "{$this->first} {$this->last}";
}
}
And interfaces can now declare that a field must exist and be readable (public string $fullName { get; }), which was impossible before.
A few rules to know: hooks can't be combined with readonly, a set hook's parameter type must be compatible with the field's type, and a virtual field with only a get hook can't be written to.
2. Asymmetric visibility: public to read, private to write
This is the one I expect to use most. How often have you written a private field plus a public getter, purely so outsiders can read a value but not change it?
class Contract
{
public private(set) string $status = 'draft';
public function sign(): void
{
// business rules here...
$this->status = 'signed';
}
}
$contract = new Contract();
echo $contract->status; // fine: 'draft'
$contract->status = 'signed'; // Error: cannot modify private(set) field from outside
Anyone can read $contract->status, but only the class itself can change it, so the only way to sign a contract is through sign(), where your rules live. There's also protected(set) if child classes need to write it, and it works with constructor promotion too: public function __construct(public private(set) string $id) {}.
How is that different from readonly? A readonly field can be set exactly once and never again, even by the class itself. Asymmetric visibility allows the class to change it as often as it needs, which is what you want for state like a status.
3. array_find, array_any, array_all
Four small functions that remove a surprising amount of loop code:
$firstOverdue = array_find($invoices, fn (Invoice $i) => $i->isOverdue());
$overdueKey = array_find_key($invoices, fn (Invoice $i) => $i->isOverdue());
$hasDraft = array_any($contracts, fn (Contract $c) => $c->status === 'draft');
$allPaid = array_all($invoices, fn (Invoice $i) => $i->isPaid());
Before 8.4 you'd write a foreach with an early return, or abuse array_filter() and take the first element (which processes the whole array). These stop at the first match. The callback receives the value and the key, in that order.
The gotcha: array_all() on an empty array returns true, and array_any() returns false. That's mathematically correct, and it will still surprise you the day "all invoices are paid" is true for a tenant who has no invoices at all. If an empty list should mean something else, check for it first.
If you're in Laravel, Collections have had first(), contains() and every() for years. These are the plain-array equivalents, useful in packages, small scripts and anywhere you don't want to wrap an array in a collection.
4. new without the extra brackets
A small one, but you'll feel it every day:
// Before 8.4
$nextMonth = (new DateTimeImmutable('2025-03-30'))->modify('+1 month');
// PHP 8.4
$nextMonth = new DateTimeImmutable('2025-03-30')->modify('+1 month');
You can now call a method, read a field or access a constant directly on a new instance. The brackets after the class name are still required: new Foo()->bar() works, new Foo->bar() doesn't.
5. #[\Deprecated] for your own code
PHP's own functions could always emit deprecation notices. Now yours can too:
class RentCalculator
{
#[\Deprecated(message: 'use LateFee::forRent() instead', since: '2.3')]
public function lateFee(int $rentCents, int $daysLate): int
{
return (new LateFee())->forRent($rentCents, $daysLate);
}
}
Calling it triggers a real E_USER_DEPRECATED notice with your message, so it shows up in logs, test output and static analysis. It works on functions, methods and class constants. It's a much clearer migration path than a @deprecated docblock that only IDEs notice.
Where to start: pick one class with a getter-and-setter pair that only exists to protect a single field. Replace it with public private(set) or a set hook. It's the quickest way to feel why this release matters.
The deprecation that will find you
PHP 8.4 deprecates implicitly nullable parameter types. This very common old pattern now triggers a deprecation notice:
function notify(User $user = null) { /* ... */ } // deprecated in 8.4
function notify(?User $user = null) { /* ... */ } // explicit, correct
It still works for now, but your logs and test output will fill up with notices, especially from older packages. Static analysis tools and automated refactoring tools like Rector can fix these across a codebase quickly. Do it before you upgrade production, not after.
Can you use all this today?
In your own application, yes, as long as every environment runs PHP 8.4: local, CI and production. Laravel 12 supports it. Check your Docker images, your server packages and your CI config before using the new syntax, because property hooks on an 8.3 server are a parse error, not a warning.
If you maintain a package, be more careful. Laravel 12 itself still supports PHP 8.2 and up, so a package that uses 8.4 syntax forces every user onto 8.4.
The official PHP 8.4 release page has the full list, including lazy objects, the new HTML5-capable DOM API and multibyte mb_trim().
Which PHP 8.4 feature has made it into your real code so far? I'm betting on asymmetric visibility, but property hooks might surprise me.

Be first to comment it...