Detecting Bugs in PHP Code with PHPStan: A Static Analysis Tool

Learn how to detect bugs early in your PHP codebase using PHPStan, a powerful static analyzer. Improve code quality with practical tips and examples.

Writing clean, bug-free code is a goal for every developer — but manual testing and reviews aren’t always enough. That’s where static analysis tools like PHPStan come in. PHPStan helps you catch bugs in your PHP code without executing it. By analyzing your source files, it detects potential issues before they ever become runtime errors.

In this article, we’ll explore what PHPStan is, how it works, and how you can integrate it into your PHP projects to improve code quality.

What is PHPStan?

PHPStan is a static analysis tool specifically designed for PHP. It scans your codebase and finds problems such as:

  • Type mismatches
  • Undefined variables or methods
  • Dead or unreachable code
  • Incorrect method calls

Unlike traditional debuggers, PHPStan doesn’t execute your code — it reads and analyzes your PHP files directly, looking for structural or logical inconsistencies based on static rules.

Why Use PHPStan?

Here are a few reasons to integrate PHPStan into your development workflow:

  • Early bug detection: Spot bugs before running the code.
  • Improved code quality: Enforce strict typing and coding standards.
  • Reduced runtime errors: Catch potential issues during development.
  • Better refactoring: Safely restructure code with confidence.

PHPStan becomes especially powerful when used alongside modern PHP features like type hints, union types, and generics.

Getting Started with PHPStan

Installing PHPStan is very easy. You can install it in your project through composer:

$ composer require --dev phpstan/phpstan

This installs PHPStan as a development dependency.

Running PHPStan

We can now run PHPStan from the base directory of our project. To analyze your code, use the following command:

$ vendor/bin/phpstan analyze src

Replace src with the directory containing your PHP files.

A breakdown of this command:

  • vendor/bin/phpstan is the executable
  • analyze tells PHPStan to analyze all files in the given directories
  • src is the directory we want to analyse

Try running this in your own project and see what kind of potential errors are living in your codebase.

By default, PHPStan analyzes the code with a conservative level of strictness. However, you can make it more strict using levels from 0 (lenient) to 8 (strictest):

vendor/bin/phpstan analyse src --level=5

Configuration with phpstan.neon

For more control, you can create a phpstan.neon configuration file in your project root:

parameters:
    level: 5
    paths:
        - src
        - app
    ignoreErrors:
        - '#Call to an undefined method.*#'

This allows you to customize which folders to analyze, define rules to ignore, and adjust the strictness level.

Common Issues Caught by PHPStan

PHPStan can detect a wide range of issues:

  • Calling methods or accessing properties that don’t exist.
  • Passing the wrong type of arguments to a function or method.
  • Returning values of the wrong type.
  • Forgetting to return a value in non-void functions.
  • Using undefined variables.

These issues often lead to hard-to-find bugs in production. Catching them early saves time and effort.

Integrating PHPStan into CI

To make PHPStan even more effective, integrate it into your CI/CD pipeline. This ensures code is analyzed automatically on every push or pull request, helping maintain a high standard across your team.

For most of my personal projects, I use TravisCI. Since we’ve included PHPStan as a dev-dependency in our composer.json file we just have to add the PHPStan executable to the scripts that the CI-software needs to run.

For TravisCI, this means just changing the default script in a .travis.yml like this:

language: php
php:
  - '8.0'
install: composer install

# Simply add these lines
script:
    - vendor/bin/phpunit
    - vendor/bin/phpstan analyse src tests --level=5

The default script that TravisCI runs for PHP projects is phpunit. Now we’ve added PHPStan to it. If PHPStan finds any errors within your project, the build will fail.

Similarly, in GitHub Actions:

- name: Run PHPStan
  run: vendor/bin/phpstan analyse --level=5

Conclusion

PHPStan is a must-have tool for modern PHP development. It helps you catch bugs early, write cleaner code, and reduce technical debt over time. Whether you’re maintaining a legacy project or starting a new one, integrating PHPStan into your workflow is a smart move.

Beginner’s Guide to Error Handling in PHP – Part 1

Learn the basics of error handling in PHP. Understand production safety and developer insights with logging errors using error_reporting.

Effective error handling in PHP is essential for developers—it helps identify issues while keeping your production environment secure and user-friendly.

Balancing Error Display vs. Security

On a production server, showing PHP errors directly on the screen poses security risks, as they may reveal sensitive file paths or internal logic. Hence, many developers suppress error display using:

ini_set('error_reporting', 0);
error_reporting(0);

ini_set('display_errors', FALSE);

However, completely hiding errors without logging them makes debugging nearly impossible.

Capturing and Logging Errors Safely

A more practical approach is to keep errors hidden from users but log them for developers to review, like below:

ini_set('error_reporting', E_ALL);
error_reporting(E_ALL);

ini_set('log_errors', TRUE);
ini_set('html_errors', FALSE);
ini_set('error_log', LOG_PATH.'error.log');

ini_set('display_errors', FALSE);

Explanation:

  • Enable reporting for all errors (E_ALL), ensuring nothing is missed.
  • Direct errors to logs, turning off HTML formatting (html_errors = FALSE) for cleaner log formatting.
  • Specify a custom log file path (via LOG_PATH . 'error.log'), enabling modular logging for different parts of your application.
  • Disable display of errors to protect end users from seeing raw error output.

Benefits of This Approach

  • Production safety: Users can’t see system internals or error details.
  • Developer insight: All error information will be logged in centralized log files.
  • Modular logging: You can segregate logs per module for quicker diagnostics.

Would you like to learn advanced error handling techniques in PHP like exceptions, custom handlers, or reading log files? Just let me know—happy to continue!

Get Last Executed Query in CodeIgniter PHP

Learn how to retrieve the last executed query in CodeIgniter’s built-in query methods developed in PHP. Helpful for debugging and query optimization.

When developing applications with CodeIgniter, retrieving the last executed SQL query becomes the most useful features for debugging and performance tuning. Whether you’re trying to diagnose a bug, optimize performance, or log queries for later review, CodeIgniter makes it easy to access the most recent database query.

In this article, we’ll explore how to get the last executed query in both CodeIgniter 3 and CodeIgniter 4, with examples.

Why Retrieve the Last Executed Query?

Here are a few scenarios where getting the last executed query is helpful:

  • Debugging incorrect or unexpected results.
  • Profiling SQL performance issues.
  • Logging queries for auditing purposes.
  • Building custom query logs for admin or developer panels.

CodeIgniter 3: Getting the Last Query

CodeIgniter 3 provides a simple method from the database class:

$this->db->last_query();

For Example:

public function getUser($id)
{
    $query = $this->db->get_where('users', ['id' => $id]);
    echo $this->db->last_query(); // Outputs the SQL query
    return $query->row();
}

Output:

SELECT * FROM `users` WHERE `id` = '1'

You can also store it in a variable to use it for logging:

$last_query = $this->db->last_query();
log_message('debug', 'Last Query: ' . $last_query);

CodeIgniter 4: Getting the Last Query

In CodeIgniter 4, the approach is slightly different. You can use the getLastQuery() method from the Query Builder object.

Example:

$db = \Config\Database::connect();
$builder = $db->table('users');

$query = $builder->where('id', 1)->get();
echo $db->getLastQuery(); // Outputs the last SQL query

Output:

SELECT * FROM `users` WHERE `id` = 1

getLastQuery() returns a CodeIgniter\Database\Query object, so you can also format it if needed:

echo $db->getLastQuery()->getQuery(); // returns query string

Pro Tips

  • Use this feature only in development mode or behind admin-only views.
  • Avoid exposing raw SQL queries in production environments for security reasons.
  • Combine it with CodeIgniter\Debug\Toolbar for enhanced SQL visibility in CI4.

Logging All Queries in CodeIgniter

You can also log all database queries automatically:

CodeIgniter 3:

In application/config/database.php, set:

$db['default']['save_queries'] = TRUE;

Then access them:

print_r($this->db->queries); // array of all executed queries

CodeIgniter 4:

Use the Debug Toolbar, or manually:

$db = \Config\Database::connect();
$queries = $db->getQueries(); //returns an array of all queries

Conclusion

Accessing the last executed SQL query is a powerful feature that can significantly speed up debugging and development. Whether you’re using CodeIgniter 3 or 4, the framework provides convenient tools to track your database interactions.

Make sure to leverage this feature wisely, especially when you’re optimizing queries or tracking down elusive bugs.

Do you use query logging in your CodeIgniter project? Share your tips or challenges in the comments below!

Best Alternative to Set a PostgreSQL Schema Using PHP PDO

Discover an effective way to set PostgreSQL schemas using PHP PDO when the SET search_path approach fails. Learn best practices for schema-based architecture.

To set the PostgreSQL DB connection, schema parameter is not to be included

$Conn = new PDO('pgsql:host=localhost;port=5432;dbname=db', 'user', 'pass');
$result = $Conn->exec('SET search_path TO accountschema');
if ( ! $result) {
die('Failed to set schema: ' . $Conn->errorMsg());
}

Is this a good practice? Is there a better way to do this?

In order to specify the default schema you should set the search_path instead.

$Conn->exec('SET search_path TO accountschema');

You can also set the default search_path per database user and in that case the above statement becomes redundant.

ALTER USER user SET search_path TO accountschema;

Alternative of PHP Excel for Excel Reading and Writing

Explore modern, efficient PHP libraries to read and write Excel files as alternatives to the deprecated PHP_Excel. Supports .xls, .xlsx, CSV, and more.

Working with Excel files is a common requirement in many PHP applications, especially for tasks like data import/export, reporting, and analysis. In the past, the go-to library for handling Excel files was PHPExcel, but it has since been deprecated and replaced by more efficient and actively maintained alternatives.

Whether you’re looking to read data from .xls or .xlsx files, write spreadsheet data, or handle both tasks seamlessly, this guide explores a wide range of libraries that offer reliable and modern solutions for Excel file manipulation.

Writing Excel using PHP

Reading Excel

Reading and Writing Excel

  • Ilia Alshanetsky’s Excel extension now on github (xls and xlsx, and requires business libXL segment)
  • spout OfficeOpenXML (xlsx) and CSV
  • PHP’s COM extension (requires a COM empowered spreadsheet program, for example, MS Excel or OpenOffice Calc running on the server)
  • SimpleExcel Claims to read and compose MS Excel XML/CSV/TSV/HTML/JSON/and so forth arranges

Another C++ Excel expansion for PHP, however you’ll have to manufacture it yourself, and the docs are really meager with regards to attempting to discover what usefulness (I can’t discover from the site what groups it bolsters, or whether it peruses or composes or both…. I’m speculating both) it offers is phpexcellib from SIMITGROUP.

All case to be quicker than PHPExcel from codeplex or from github, however (except for COM, PUNO Ilia’s wrapper around libXl and spout) they don’t offer both perusing and composing, or both xls and xlsx; might never again be upheld; and (while I haven’t tried Ilia’s expansion) just COM and PUNO offers the same level of control over the made exercise manual.

Source: http://stackoverflow.com/questions/3930975/alternative-for-php-excel