A summary of small things a php programmer can do to improve the code and the readability of code.
There are so brilliant programming concepts and paradigms in the PHP community. I don't want to chew them again and again. But I think everybody needs some easy small things we can improve in our everyday's work. There are so many books, conferences, videos and so on, where you can learn great new or old architectures. But most of the time you have to start from scratch or read thick books before you can start. That is fine, but IMO there are so many small things you can improve and start now. I saw many developer doing great work in general, but no one understands the goal of their software or the way to the goal. There will be the day they dont support their fancy tools any more. And a new developer starts from scratch, because he or she do not understands the code at all. Everybody can produce legacy code. (legacy code is code that works) So IMO the best code is code that everybody can understand by reading it. This repository should help to see, that there are so many small things we can improve from now on.
I am convinced that in a complex situation the small things makes the difference.
- PHP programming
- Learning the basics
- Blogs
- Tools
- IDE
- Important composer packages
- Code reviews
- Documentation
Every thesis can be advice.
- Every advice has its own context, and context beats any advice.
- Use common sense for every advice; these are not rules.
- Skip any advice that doesn't bring a benefit.
- Avoid subjective perspectives in advice.
- Advice should have a real, tangible benefit.
- Advice should generally apply broadly.
- You don't have to follow all advice, but you should know they exist.
- Comment: Don't miss any advice without understanding the reason.
These are some theses I have developed in almost 20 years of programming in teams. It is just a numbered list to discuss it. New theses will be listed at the end of the list, feel free to add some. The given list is far from complete, but I have raised these points too many times and they may help others too. My context has always been the development of products that need to be adapted and expanded over a longer period of time. It was never a question of whether a line of code would be adapted, but when. Defects in these products lead to direct financial losses or a work blocker for teams.
-
What cannot be tested should not be programmed.
- Comment: Start with PHPUnit.
- Example: Implementing unit tests for all public methods ensures that each function performs as expected.
-
Use type declarations for all properties, functions (return types and parameters), and variables.
- Comment: They exist for a reason.
- Reference: PHP Type Declarations
-
Immutability is king.
- Comment: Know the advantages.
- Example: Using immutable objects can prevent accidental changes to data.
final class ImmutableUser { public function __construct(private readonly string $name) { } public function getName(): string { return $this->name; } }
-
Always check clauses with the most accurate possible value.
- Comment: Return types can change, but the clause should not.
- Example:
if (true === $user->isActive())
is preferred overif ($user->isActive())
.
-
Avoid else statements and use early returns.
- Comment: Reasons.
- Example:
function example(bool $value): void { if (false === $value) { return; } // Rest of the code }
-
Do not use arrays across class or function boundaries.
- Comment: They are not typed.
- Example: Use value objects or DTOs instead of arrays.
final class UserDTO { public function __construct(public readonly string $name, public readonly string $email) { } } function createUser(UserDTO $userDTO) { // Use $userDTO }
-
String concatenation should always use
sprintf
.- Comment: It is safer, easier to extend and it prevents magic. It is slower than normal concatenation.
- Example:
$name = "John"; $greeting = sprintf("Hello, %s!", $name);
-
Use Yoda conditions.
- Comment: prevents accidental assignment and let your eye quicker find the info.
- Example:
if ( 'no' === $answer || 'yes' === $answer ) { // Do nothing } if (42 === $answer) { // Do something }
- Reference: To Yoda or Not to Yoda
-
Use
declare(strict_types=1);
at the top of every PHP script.- Comment: Explanation.
- Example: Ensures that all type declarations are strictly enforced.
declare(strict_types=1); function add(int $a, int $b): int { return $a + $b; }
- Reference: Strict Types in PHP
-
Use
final
for your objects.- Comment: Inheritance is complex to manage.
- Example:
final class User { // Class implementation }
- Reference: Final Keyword in PHP
-
Default visibility for properties and functions should be
private
.- Comment: Treat public functions/properties as public APIs.
- Example:
final class User { public function __construct(private string $name) {} public function getName(): string { return $this->name; } }
- Reference: Visibility in PHP
-
Use annotations sparingly and only when necessary.
- Comment: Prefer PHP8 attributes, return types and property types.
- Example:
#[PHPUnit\Framework\Attributes\DataProvider('provideNotAllowedKeys')] public function testShowErrorWithNotAllowedKeys(string $key)
- Reference: PHP8 Attributes
-
Do not use full namespaces in the code; use
use
statements.- Comment: Highlights external dependencies.
- Example:
use Vendor\Package\Class; $object = new Class();
- Reference: Namespaces in PHP
-
Traits should never use traits.
- Comment: Avoid complex inheritance.
- Example: Avoid nested traits to reduce complexity.
- Reference: Traits in PHP
-
Strings should be constants.
- Comment: Reduces errors and increases reusability.
- Example:
public const string STATUS_ACTIVE = 'active';
- Reference: Constants in PHP
-
Do not check in commented or unused code.
- Comment: Use version control.
- Example: Clean up code before committing.
- Reference: Best Practices for Version Control
-
Avoid abbreviations in the code.
- Comment: Leverage IDE features.
- Example: Use
description
instead ofdesc
. - Reference: Clean Code Practices
-
Use PHAR files for dev-dependency tools.
- Comment: Reduces conflicts and speeds up requirements.
- Example: Use
phpunit.phar
for PHPUnit. - Reference: PHP Archive (PHAR)
-
Do not use asynchronous techniques in a synchronous language.
- Comment: Different paradigms can lead to complexity.
- Example: Avoid mixing async JS techniques in PHP.
This is just a small snapshot I can recommend. (If you buy books please think about second hand books. The given links are more for information. Think twice before you order it.)
- Principles of object oriented design (web)
- The clean coder (book | web)
- Extremely defensive PHP (video | slides)
- Design pattern (web)
- PHP standards recommendations PSR
- Semantic versioning (web)
- Refactoring (book)
- Principles of package design (book)
- A philosophy of software design (book)
- Pro git (ebook)
- The mythical man-month (book)
There are many more interesting blogs, but these selection cross up my way multiple times. It could be beneficial to look also through old articles.
- https://blog.jetbrains.com/phpstorm/
- https://blog.cleancoder.com/
- https://matthiasnoback.nl/
- https://ocramius.github.io/
- https://www.sitepoint.com/php/
- https://www.zend.com/blog
- https://localheinz.com/articles/
- https://stitcher.io/
- use package managers for your local requirements
- for example in MacOS install brew
- install php over brew on MacOS
- comment: the big advantage is to have multiple versions linked by brew directly from the cellar
- install git over brew on MacOS
- install Oh My Zsh bash on MacOS
- install composer globally for dependency management in PHP
- install xdebug for debugging, tracing, profiling and the codecoverage
- use a automation server like jenkins for continuous integration, continuous deployment or any other automation
- use a remote repository server like gitlab or bitbucket or at least github
- use a private package repository like satis
- use a error tracker like sentry
- if you need regex, than use this page
- you want to schedule a cronjob, than look at this page
- you are not sure with your version constraint, than look at this page
- communication is the key, use showcode for better presentations
- use an IDE for example PHPStorm
- set PHPStorm up (jetbrains documentation) correctly
- use inspections
- use one of the default codestyles in PHPStorm for example PSR-12
- use xdebug in PHPStorm (documentation)
- take a look at PHPStorm features like ai testing, testing, database, deployment, version control, ... tutorials
- use plugins of PHPStorm:
- github-copilot
- .env
- php annotations
- select a plugin for framework support like symfony
The list of packages is not complete, but you can start projects from this stack.
- Composer package to handle Security advisories.
- Do not commit secrets and use .env's instead.
- The testing framework PHPUnit.
- If you reached nearly 100% of code coverage than you can go further with infection.
- Static code analyses with PHPStan or Psalm.
- PHP Codesniffer with PHPCS and PHPCBF.
- Dependency injection container PHP-DI
- PHP library to generate UUIDs or use ULIDs.
- Simple composer PHAR file handling with tooly.
Start making code reviews. If you dont know how? Read this article
You are not your Code!
- code reviewer do not comment on you, they comment your code
If you find code you do not understand, ask.
- It is not the question if you should know, but when.
I only saw one approach, which seems to be suitable for software projects and this is arc42.
For further diagrams or graphs you can use draw.io.
"Definition of 'estimate' according to Duden: (without exact measurement, based only on experience) to determine approximately" → We do not expect these to be exact and always correct, but they should get better.
You have to learn how to approach it. Estimate before you start the task, then track the time and compare at the end what influenced you.
Maybe start by using PERT �result = (best case estimation + 4 * normal estimation + worst case estimation) / 6
- Use composer
- Use composer scripts for automation
- I have good experience with providing a static code analysis and tests with composer scripts in combination with bash scripts
- Use composer scripts for automation
- Use githooks like here to prevent commit cascade with fix tests, static code analysis, and code style
- Use openapi for API documentation
- Adopt dependency injection
- Use value objects for domain logic
- Do not use external class directly, use a wrapper
- Use database migrations for example with phinx
- Use a logger like monolog
- Use timestamp as exception code
- use the current timestamp as exception code while creating the exception
- it is better testable and the error log directly leads to the code
- Use design patterns if you have their usecases
- Use a factory for object creation
- Use a repository for database access
- You can mock them in tests
- You know where to find the database access
- Use
filter_input
to validate user input - Do not reinvent the wheel
- Each repository should have a readme and the readme should be updated regularly
- Use final interfaces to collect typed constants
- So you can bundle up contents like API date formats or other stuff.
- Know the packages of php-fig
- Look through the packages of phpleague
- If you deal with money look at moneyphp
- Use flysystem or vfsStream to test file handling
- Use symfony intl for internationalization
- Use symfony console for console applications
- Most reason why I could not write tests is because I could not mock core functions but you can example-test-php-core-methods
- Working in teams is about working with API contracts. The smallest API contract are the public methods in a class.