Reducing Bugs With Static
Code Analysis
Scott Keck-Warren
php tek 2025
https://scott.keck-warren.com/
https://tinyurl.com/sca-php-tek-2025
How We Fixed Bugs (Don’t Do This)
1. Duplicate the bug
2. Fix it
3. Open SFTP connection to production
4. Manually edit the file
5. Cross our fingers nothing broke
Parse error: syntax error, unexpected identifier "privte",
expecting "function" or "const"
Fatal error: Uncaught Error:
Call to undefined method User::getId()
What Happened?
• Type errors
• Left over `echo` debug statements
• `exit` in unexpected spot
What’s the Fix?
What’s the Fix?
Production
Change
What’s the Fix?
Production
Change
?
What’s the Fix?
Production
Change
Reducing Bugs With Static
Code Analysis
Scott Keck-Warren
php[tek] 2025
https://scott.keck-warren.com/
ScottKeckWarren
class ScottKeckWarren
{
}
use PsrHugHuggable; // PSR-8
class ScottKeckWarren implements Huggable
{
public function hug(Huggable $h)
{
// only if asked
}
}
use PsrHugHuggable; // PSR-8
class ScottKeckWarren implements Huggable
{
use Partner;
public function hug(Huggable $h)
{
// only if asked
}
}
use PsrHugHuggable; // PSR-8
class ScottKeckWarren implements Huggable
{
use Partner;
use BestDadEver;
public function hug(Huggable $h)
{
// only if asked
}
}
use PsrHugHuggable; // PSR-8
class ScottKeckWarren implements Huggable
{
use Partner;
use BestDadEver;
public function hug(Huggable $h)
{
// only if asked
}
}
use PsrHugHuggable; // PSR-8
class ScottKeckWarren implements Huggable
{
use Partner;
use BestDadEver;
use PhpDeveloper;
public function hug(Huggable $h)
{
// only if asked
}
public function getTitle(): string
{
return "Senior Software Engineer";
}
}
use PsrHugHuggable; // PSR-8
class ScottKeckWarren implements Huggable
{
use Partner;
use BestDadEver;
use PhpDeveloper;
use ContentCreator
public function hug(Huggable $h)
{
// only if asked
}
public function getTitle(): string
{
return "Senior Software Engineer";
}
}
scott.keck-warren.com
scott.keck-warren.com
Agenda
1. What is Static Code Analysis?
2. Where Do We Perform Static Code Analysis?
3. Tools For Static Code Analysis
What is Static Code Analysis?
What is Static Code Analysis?
Two Ways to Analyze Code
1. Dynamic Code Analysis
2. Static Code Analysis
What is Static Code Analysis?
Dynamic Code Analysis
• Run code (manually or automatically)
• Manual: slow and expensive
• Automated: slow to create but infinitely repeatable
What is Static Code Analysis?
Static Code Analysis
• Analyze our source code without actually executing
• Slow onboarding (maybe) on brownfield applications
• Infinitely repeatable
• Can be faster than dynamic tests
What is Static Code Analysis?
What specifically can we do with Static Code Analysis?
• Find errors
• Adhere to standards
• Automatically refactor our code
What is Static Code Analysis?
• Teams size is not a limiting factor to using SCA
• Compute/cost can be
Where Do We Perform Static
Code Analysis?
Feedback Loops
Feedback Loops
Process
Feedback Loops
Process
Input(s)
Feedback Loops
Process
Input(s) Output(s)
Feedback Loops
Process
Input(s) Output(s)
Feedback Loops
Process
Input(s) Output(s)
Coding
Requested Change(s) Finished Code
Refinement/Fixes
Feedback Loops:Worst Case
Process
Input(s
)
Output(s
)
Feedback Loops:Worst Case
• Change is made
• Change is pushed to production
• Problem found in the near or far future
• Problem is completely divorced from
original change
• Leads to Confusion
• What caused this?
Process
Input(s
)
Output(s
)
Feedback Loops:Okay Case
• Change is made on own branch
• Change is heavily tested on testing
server
• Problem found during testing
• Problem solved quickly because change
is still fresh in our mind
Process
Input(s
)
Output(s
)
Feedback Loops:Better Case
• Change is made on own branch
• Change is heavily tested locally
• Problem found before code leaves our
computer
• Problem solved quicker but still delayed
Process
Input(s
)
Output(s
)
Feedback Loops:Best Case
• Change is made on a file
• Changes are tested as we save/type
• Problem found immediately
• Problem solved immediately
Process
Input(s
)
Output(s
)
Where Do We Run Static Code Analysis?
Best
Okay
Better
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Where Do We Run Static Code Analysis?
Best
Test Server
Better
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Test Server
Test Server
• Goal: Going to give us secure base
• Can’t be skipped or ignored
• All tools run
• All files
• Slow
Best
Test Server
Better
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Test Server
• Lots of options for this
• Quickly talk about GitHub Actions
• Quick to setup
• “Infinitely” scaleable
Best
Test Server
Better
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Test Server
• Several Ways to Configure
• One Job For All Tools
• Tools Run In Series
• Multiple Jobs/Actions For Each Tool
• Tools Run in Parallel
• Setup Dependencies Between Jobs
Best
Test Server
Better
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Large Project Actions
Production
Change
Large Project Actions
Production
Change
Dynamic
Automated
Tests
Large Project Actions
Production
Change
Dynamic
Automated
Tests
Static
Large Project Actions
Production
Change
Dynamic
Slowest
Static
Fast
Slower
Slower
Still
Slower
Still
Slower
Large Project Actions
Production
Change
Dynamic
Slowest
Static
Lint
Slower PHPStan
Slower
Still
Slower
Where Do We Run Static Code Analysis?
Best
Test Server
Better
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Where Do We Run Static Code Analysis?
Best
Test Server
Pre-Commit
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Before Commit Is Created
Before Commit Is Created
• Build off secure base
• Balance of tools
• Changed files only
• Faster
Best
Test Server
Pre-Commit
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Before Commit Is Created: How?
• Run files manually
• Copy and paste each file
• Skip this step SO fast
Best
Test Server
Pre-Commit
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Before Commit Is Created: How?
• Run files automatically
• Use pre-commit functionality
Best
Test Server
Pre-Commit
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Pre-Commit Script
commit-msg
pre-push
pre-commit
Pre-Commit Script
git add .
git commit -m “changes”
Commit Created
Pre-Commit Script
git add .
git commit -m “changes”
Commit Created
Pre-
commit
Denied
Pre-Commit Script
• Located at “.git/hooks/pre-commit”
• NOT part of repo so not kept up to date
• Can be skipped (using “-n” or by deleting the file)
• That’s why we have a secure test server base
Pre-Commit Script
• Make a minimal “pre-commit” script that calls `make pre-commit`
• Keep copy in “scripts” directory
• Use composer to install the “pre-commit” script
• See https://github.com/warren5236/ScottsValueObjects
make
Makefile
make pre-commit
Pre-Commit Script
Our Pre-commit script’s goals:
1. Give us fast feedback loop
2. Only run on files we changed
3. Run as many tools as possible
Only run on files we changed?
git diff 
—diff-filter=AM 
—name-only 
—cached 
app tests | grep ".php$"
Makefile
## PreCommit Section
pre-commit:
Makefile
## PreCommit Section
CHANGED_PHP_FILES = git diff --diff-filter=AM --staged --name-only src tests | grep ".php"
pre-commit:
Makefile
## PreCommit Section
CHANGED_PHP_FILES = git diff --diff-filter=AM --staged --name-only src tests | grep ".php"
pre-commit: phpcs_changed
phpcs_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpcs --standard=phpcs.xml
Makefile
## PreCommit Section
CHANGED_PHP_FILES = git diff --diff-filter=AM --staged --name-only src tests | grep ".php"
pre-commit: phpcs_changed phpstan_changed
phpcs_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpcs --standard=phpcs.xml
phpstan_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpstan analyze --memory-limit 1G
## PreCommit Section
CHANGED_PHP_FILES = git diff --diff-filter=AM --staged --name-only src tests scripts | grep ".php"
pre-commit: lint_changed phpcs_changed phpstan_changed rector_changed
lint_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/parallel-lint
phpcs_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpcs --standard=phpcs.xml
phpstan_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpstan analyze --memory-limit 1G
rector_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/rector process --dry-run
## Full Static Code Analysis Section
phpcbf:
vendor/bin/phpcbf --standard=phpcs.xml src tests scripts
phpstan:
vendor/bin/phpstan analyze --memory-limit 1G -l9 src tests
## PreCommit Section
CHANGED_PHP_FILES = git diff --diff-filter=AM --staged --name-only src tests scripts | grep ".php"
pre-commit: lint_changed phpcs_changed phpstan_changed rector_changed
lint_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/parallel-lint
phpcs_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpcs --standard=phpcs.xml
phpstan_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpstan analyze --memory-limit 1G
rector_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/rector process --dry-run
## Full Static Code Analysis Section
phpcbf:
vendor/bin/phpcbf --standard=phpcs.xml src tests scripts
phpstan:
vendor/bin/phpstan analyze --memory-limit 1G -l9 src tests
## PreCommit Section
CHANGED_PHP_FILES = git diff --diff-filter=AM --staged --name-only src tests scripts | grep ".php"
pre-commit: lint_changed phpcs_changed phpstan_changed rector_changed
lint_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/parallel-lint
phpcs_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpcs --standard=phpcs.xml
phpstan_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/phpstan analyze --memory-limit 1G
rector_changed:
${CHANGED_PHP_FILES} | xargs vendor/bin/rector process --dry-run
## Full Static Code Analysis Section
phpcbf:
vendor/bin/phpcbf --standard=phpcs.xml src tests scripts
phpstan:
vendor/bin/phpstan analyze --memory-limit 1G -l9 src tests
--colors
Where Do We Run Static Code Analysis?
Best
Test Server
Pre-Commit
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Where Do We Run Static Code Analysis?
IDE
Test Server
Pre-Commit
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
IDE
• Build off secure base
• Smaller Number of tools
• Changed files
• Immediate feedback
IDE
Test Server
Pre-Commit
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
IDE: Top Suggestions
• Errors in your face
• Don’t ignore them
• Look for integrations/extensions
Where Do We Run Static Code Analysis?
IDE
Test Server
Pre-Commit
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
Tools
https://github.com/exakat/php-static-analysis-tools
Types of SCA Tools
1. Bug Reduction
2. Rule Validation
3. Code Analysis
Types of SCA Tools
1. Bug Reduction
2. Rule Validation
3. Code Analysis
Focus: Scott’s Favorites
1. Free
2. Easy to use
3. Command line based
Linting
Is Our Code Valid?
php -l src/path/to/file.php
find -L src tests -name '*.php' -print0
| xargs -0 -n 1 -P 4 php -l
Linting
• src/Location/City.php
• src/Name/FirstName.php
• src/Name/LastName.php
php-parallel-lint/php-parallel-lint
./vendor/bin/parallel-lint src tests
Linting
Production
Change
Dynamic
Automated
Tests
Static
Lint
Grep Command Line
Grep
• Debugging only functions
• var_dump()
• exit
• dd()
Grep
• In most Unix environments by default
• grep -R “thing we don’t want” src tests
Grep
Production
Change
Dynamic
Automated
Tests
Static
Lint
Grep
Coding Standard
Coding Standard
if ($value) {
thing1();
}
if ($value2)
{
thing2();
}
if ($scott)
lookMomNoBraces();
PHP_CodeSniffer
• phpcs -> validates code
• phpcbf -> fixes code (when possible)
PHP_CodeSniffer
1. Existing coding standards: PSR12, Pear, Zend, etc
2. Create from scratch
3. Existing + Extras
phpcs.xml v 1.0
<?xml version="1.0"?>
<ruleset name="Super PSR12">
<description>PSR12 + Types</description>
<rule ref="PSR12" />
</ruleset>
phpcs.xml v 1.0
./vendor/bin/phpcbf --standard=phpcs.xml src tests
phpcs.xml v 1.0
if ($value) {
thing1();
}
if ($value2)
{
thing2();
}
if ($scott)
lookMomNoBraces();
if ($value) {
thing1();
}
if ($value2) {
thing2();
}
if ($scott) {
lookMomNoBraces();
}
–You (Maybe)
“How does this prevent bugs?”
Example
function add(int $a, int $b) {
return $a + $b;
}
// later
var_dump(add(1.25, 2.75)); // expect 4.00
int(3)
Type Juggling
1.25 + 2.75
(int)1.25 + (int)2.75
1 + 2
3
Fix
declare(strict_types=1);
function add(int $a, int $b) {
return $a + $b;
}
// later
var_dump(add(1.25, 2.75)); // expect 4.00
RequireStrictTypes
Fatal error: Uncaught TypeError: add(): Argument #1 ($a)
must be of type int, float given, called in
/home/user/scripts/code.php on line 9 and defined in
/home/user/scripts/code.php:5
phpcs.xml v 2.0
<?xml version="1.0"?>
<ruleset name=“Super PSR+12">
<description> PSR12 + Types</description>
<rule ref=“PSR12" />
<rule ref="Generic.PHP.RequireStrictTypes" />
</ruleset>
phpcs.xml v 2.0
1 | ERROR | Missing required strict_types declaration
Slevomat Coding Standard
• Slevomat Coding Standard library
• composer require --dev "slevomat/coding-standard"
phpcs.xml v 2.0
<?xml version="1.0"?>
<ruleset name=“Super PSR+12">
<description> PSR12 + Types</description>
<rule ref=“PSR12" />
<rule ref="Generic.PHP.RequireStrictTypes" />
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint" />
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint" />
<rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint" />
</ruleset>
-Chris Tankersley
"Consistency provides comfortability"
Pipeline Review
Production
Change
Dynamic
Automated
Tests
Static
Lint
grep
phpcs
Bug Finders
// User.php
class User
{
public int $id = 1;
}
// other.php
$user = new User();
echo $user->id;
// User.php
class User
{
private int $id = 1;
}
// other.php
$user = new User();
echo $user->id;
Fatal error: Uncaught Error: Cannot access private
property User::$id
PHPStan
• Finds bugs in our code
• “Oops you made a mistake here”
• Check “correctness” of each line
PHPStan: Setup
vendor/bin/phpstan analyse -l <number> src tests
PHPStan: Rule Levels
• Specify level of strictness using -l|--level parameter
• 0 -> Lowest Strictness
• 10 -> Highest Strictness
PHPStan: Getting Started
parameters:
ignoreErrors:
-
message: "#^Access to private property …::$id.$#”
count: 1
path: src/Location/User.php
PHPStan: Getting Started
1. Generate baseline at level 0
2. Fix all errors at current level
3. Increase level
4. Repeat until desired level
PHPStan
Production
Change
Dynamic
Automated
Tests
Static
Lint
phpcs
grep
PHPStan
Automating Refactoring
PHP 7.4 To 8.0 Was
Challenging
Automating Refactoring
• Create a branch with PHP 8 installed
• Run through our tests
• Have someone manually fix the error
What if We Automate This?
PHPStan: Setup
./vendor/bin/rector -dry-run
PHPStan: Setup
./vendor/bin/rector
Rector:rector.php
<?php
declare(strict_types=1);
use RectorConfigRectorConfig;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/scripts',
__DIR__ . '/src',
__DIR__ . '/tests',
])
// uncomment to reach your current PHP version
// ->withPhpSets()
->withTypeCoverageLevel(0)
->withDeadCodeLevel(0)
->withCodeQualityLevel(0);
Rector:rector.php
<?php
declare(strict_types=1);
use RectorConfigRectorConfig;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/scripts',
__DIR__ . '/src',
__DIR__ . '/tests',
])
// uncomment to reach your current PHP version
->withPhpSets()
->withTypeCoverageLevel(0)
->withDeadCodeLevel(0)
->withCodeQualityLevel(0);
Rector: example
Fatal error: Uncaught Error: Call to undefined function create_function()
Rector: example
vendor/bin/rector —dry-run
Rector: example
vendor/bin/rector
Rector:rector.php
<?php
declare(strict_types=1);
use RectorConfigRectorConfig;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/scripts',
__DIR__ . '/src',
__DIR__ . '/tests',
])
// uncomment to reach your current PHP version
->withPhpSets()
->withTypeCoverageLevel(0)
->withDeadCodeLevel(0)
->withCodeQualityLevel(0);
Rector:rector.php
<?php
declare(strict_types=1);
use RectorConfigRectorConfig;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/scripts',
__DIR__ . '/src',
__DIR__ . '/tests',
])
// uncomment to reach your current PHP version
->withPhpSets()
->withTypeCoverageLevel(1)
->withDeadCodeLevel(1)
->withCodeQualityLevel(1);
<?php
use RectorConfigRectorConfig;
use RectorRenamingRectorClassConstFetchRenameClassConstFetchRector;
use RectorRenamingValueObjectRenameClassConstFetch;
return RectorConfig::configure()
->withConfiguredRule(RenameClassConstFetchRector::class, [
new RenameClassConstFetch(
‘DateTimeImmutable',
'NUMBER_OF_SECNDS_IN_AN_HOUR‘,
‘NUMBER_OF_SECONDS_IN_AN_HOUR'
),
]);
Production
Part 3: Code
Readability/Maintainability
Change
Dynamic
Automated
Tests
Static
Lint
phpcs PHPStan
grep Rector
What You Need to Know
What You Need to Know
Static Code Analysis allows us to analyze our code without running it
What You Need to Know
Process
Input(s) Output(s)
What You Need to Know
IDE
Test Server
Pre-Commit
F
a
s
t
e
r
F
e
e
d
b
a
c
k
M
o
r
e
S
a
f
e
t
y
What You Need to Know
• PHP Parallel Lint
• Grep
• PHP_CodeSniffer
• PHPStan
• Rector
Thank The Organizers
Thank The Speakers
Questions?
• Scott Keck-Warren
• Resources:
• https://tinyurl.com/sca-php-tek-2025

Reducing Bugs With Static Code Analysis php tek 2025

Editor's Notes

  • #1 Ask people for photos Note: add QR code to slides/resources Note: QR code/link brings you to resources about this talk and slides Hello Developers,
  • #2 Story time Want to tell you about some of the trauma I had inflicted on me Hopefully prevent you from having the same
  • #3 First job as a professional developer Small SaaS 3 developers No source control to speak of
  • #4 Bugs in productions were fixed like this Go through steps <click for each> Last part was important because we would occasionally find <next slide>
  • #5 Chrome with white screen Sometimes 1 page some times the whole site
  • #6 Generally results in angry person on phone Asking “what happened?” SSH into the server to check error logs
  • #7 Miscopied our results
  • #8 Copied changes to one file but not another
  • #9 Other things Happened at least once a week sometimes multiple times a day
  • #11 Graphic: Change -> Production directly So close together barely and space between them Need to add some space <click>
  • #12 Change -> ? -> Production When what do we fill the space with? Change -> Checks -> Production
  • #13 Better still will use several different checks of each type Let’s talk about one of the major types today … <click>
  • #14 static code analysis Specifically: How we can reduce bugs with SCA
  • #34 I’m a huge fan of both
  • #36 I’m a huge fan of both See my other talk on how to get more DCA
  • #37 Lots of things we’ll do with static code analysis Read list
  • #38 <bp1> Currently have a team of 1 using it (me) Have had teams of 8 using it <bp2> In the past Have run into situations where our team has been waiting for their tests to run So easy today to spin up containers no longer a problem
  • #39 <slide> But Before we talk about that we need to talk about …
  • #40 <slide>
  • #41 Start with a process Could be anything writing a class, sending an email, checking your email
  • #42 Process has one or more inputs
  • #43 Process happens and we get one or outputs
  • #44 In a feedback loop the outputs become part of the import loop
  • #45 Developers Are Driven By Feedback Loops Make a change, see what happens, if, fix the problem, repeat Want these to be short -> We can affect the length
  • #46 First case is “Worst Case”
  • #47 In this <read slide> I’m lucky if I remember what I did yesterday Note lack of testing
  • #48 Next option okay case <read slide> Less of a difference between change and problem being found
  • #50 Next best case <read slide> I like to call this an immediate feedback cycle Provides feedback immediately so we can resolve problems immediately This is the ultimate goal for static code analysis
  • #51 I’m a belt and suspenders kind of person Want to have multiple levels of protection from myself and others
  • #52 Using these feedback levels to build three tiers of static code analysis <click for each piece> At the bottom…<click>
  • #53 is running the SCA tools using a test server
  • #55 <Read slide> Slow is fine here my day job takes 30 minutes to run all static and dynamic analysis Fine with that because not watching
  • #56 Have video php arch channel on how to setup
  • #58 Graph from before showing us change to production I like 1 action with a lot of small steps in four stages
  • #59 1 dynamic stage where I run automated tests
  • #60 3 static stages Quick and easy first to fail fast in first stages Slow in final stages Saves some money and failing items in earlier phase generally cause failures in later stages
  • #61 Quick and easy first to fail fast in first stages Slow in final stages Saves some money and failing items in earlier phase generally cause failures in later stages
  • #62 For example Tool
  • #63 Return to our chart See what’s next
  • #67 Two ways to do this First <slide>
  • #69 Inside our .git directory then hooks Session on this if you’re interesting we’re doing the quick-quick version
  • #70 -> Inspect the commit message
  • #71 -> before we push
  • #72 -> before commit is created
  • #73 This is normally how we create commit
  • #74 Pre-commit adds a conditional check Is this good yes or no -> no we can’t create the commit
  • #75 Still can be bypassed Which is why we have secure base at the test server
  • #76 Makefile can change depending on the project branch
  • #77 Generally, the `make` command line tool is used to determine what portions of programs need to be recompiled so developers don't need to recompile the whole source tree for every change. `make` is generally used for any development environment where you have a "complex" local build, test, and install process.
  • #78 The `make` command line tool consumes Makefiles which are used to create links between target files and their inputs which the `make` command line tool then uses to determine if and what files it needs to build.
  • #79 Our pre-commit file
  • #80 Might be wondering how ..
  • #82 1. `git diff` -> Runs the git diff command which shows us changes in our repository 2. `--diff-filter=AM` -> filters out files to only show us modifications and additions 3. `--name-only` -> returns just the name of the file and not the contents 4. `--cached` -> returns changes that have been staged for the next commit and not every changed file 5. `app tests` -> limit our results to files in the app and tests directories 6. `| grep ".php$"` -> Limit our results to just `.php` files
  • #86 <slide> don’t freak out about the next slide It’s a lot
  • #87 Generally think: runs right to left in series
  • #88 Generally think: runs right to left in series
  • #89 Generally think: runs right to left in series
  • #98 VS Code example of syntax error: Missing “use” statement Not native but with error lens plugin Love these which is why I need to restart VScode so frequently
  • #100 Here’s where it get good Too many PHP SCA tools to review them all here
  • #101  Show graphic of git repo with list of SCA tools https://github.com/exakat/php-static-analysis-tools
  • #102 Bug Reduction -> things that might break code Rule Validation -> things that don’t meet our standards Code Analysis -> What’s code like
  • #103 Focus on first two here Third one is something I do occasionally to see our code health but not automatically in 3-tiers
  • #104 Free Easy to use Everything is command line based so it runs at pre-commit and test server
  • #105 The most important SCA tool
  • #106 Linting answers the most important question about our code
  • #107 Built in linting mode 1 file at a time “slow” because of that
  • #108 Have to run it through additional tools
  • #109 Also only finds one problem at a time So error in city and last name Only show error in city Fix and repeat to find second
  • #110 https://packagist.org/packages/php-parallel-lint/php-parallel-lint php-parallel-lint/php-parallel-lint
  • #112 Example running parrellel lint
  • #113 Graphics here Like to make this my first check If it fails others will fail as well
  • #114 Another basic check “free”
  • #115 Pushing these to production causes weird output Can and does break site Don’t want it that
  • #116 Pushing these to production causes weird output Can and does break site Don’t want it that
  • #117 Where in graphic
  • #119 Teams are comprised of people with lots of life experience and traumas That affects how they type each character
  • #120 Having a coding standard makes code easier to read Without a coding standard can have chaos How do we fix this? Better how do we fix this automatically
  • #121 PHP_CodeSniffer library allows us to define standard, enforce it, and fix it
  • #122 PHP_CodeSniffer library has two command line scripts PHP CodeSniffer PHP Code Block Fixer
  • #123 We need tell php_codesniffer what rules to use <slide> I like third option PSR12 as a base PSR family of standards is used by a lot of frameworks so it’s helpful
  • #124 Created at root of project
  • #126 If we run phpcbf on code this is what we get Better right or at least consistent
  • #127 <Read slide> Let’s take a slight detour for another example
  • #128 Function that adds two numbers Use it to add 1.25 and 2.75 Does anyone know what the output of this is?
  • #129 That seems like a bug to me what about you?
  • #130 This is due to something that PHP does called type juggling Because dynamic language it automatically converts types Add function wanted int so add function received ins Mostly great but sometimes weird bugs
  • #131 <click> have our two numbers <click> We specified int parameters to our function php said I’m going to make these integers <click> PHP converts number to integers and in this case strips out the fractions <click> 3
  • #132 December 2015 PHP 7 added this declare function - Prevents this kind of bug 7 years ago If we run our code again <next slide>
  • #133 We get type error I constantly forget to add strict_types to my code Need a little help PHP_Codesniffer provides that
  • #135 Doesn’t work by magic also need to make sure parameter types No support out of box for this
  • #136 To do that we need to look for more rules (or sniffs as code sniffer calls them) <Read slide>
  • #137 Next require parameter types hints Without parameter types strict types doesn’t help us completely Return and property types aid in us making these kinds of mistakes (also helps other tools)
  • #139 Let’s review where we’re at Still have a space need to discuss and that’s
  • #140 Help us find fatal errors due to changes in our code or mistakes
  • #141 Have a very basic user class Somewhere in my code I need the ID
  • #142 Have a very basic user class Somewhere in my code I need the ID
  • #147 10 just added in PHPstan 2 release
  • #152 Running first time on brownfield application Potentially lots of “problems”
  • #153 Run with —generate-baseline Only need to worry about changes
  • #159 Have a pipeline now This works and works because we
  • #160 Graphic
  • #161 At least of some of us Took weeks Might still have projects running on 7.4 because can’t justify upgrade
  • #162 Took FOREVER Full of potential errors because shortcuts were made Didn’t even get to implement the new features in 8.0 like Constructor Property Promotion Upgrade to point release have been easier
  • #163 Lot’s of manual work
  • #164 PHPstan says “Oops you made a mistake here” Rector says “Oops you made a mistake here and I can fix it”
  • #176 Stole this from their website
  • #177 With the —dry-run Because it can cause
  • #180 Keep your feedback loop SHORT Immediately if possible
  • #181  Run tools In IDE Pre-commit Test Server
  • #182 Lots of options for tools My favorites:
  • #186 My name again Thanks to the sponsors, Eric and John put an insane amount of work into them thank them QR code and link are resources for this talk including slides, CTA: Liked this? Please review this on joind.in helps me be able to do this more Also, follow the YouTube channel and me one social media. YouTube isn’t whole of my output so see what else I do