Skip to content

Latest commit

 

History

History
332 lines (276 loc) · 13.5 KB

PHP-development.md

File metadata and controls

332 lines (276 loc) · 13.5 KB

PHP development notes

How to move fast while keeping the codebase clean?

See an article on Moving Fast With High Code Quality and clearPHP rules

Forces influencing development

  • First an foremost keeping the codebase clean to avoid rewrites in long term
  • Make profit!
  • Other's interest in integration with your project (API)
  • Move fast with development, don't use a tool if it slows down development
  • Keep developer morale high
  • Have a fixed time frame for paying back technical debt
  • Think about the far future when making decisions today

High level overview

  • Software architecture ☀️ ☀️ ☀️
  • Documented code design ☀️ ☀️
  • Implementation (source code writing) ☀️
  • Automatic and manual testing
  • Periodic code review, security audit

Editor settings

Bits and bytes.

  • Execute bit off
  • Consistent indentation
  • LF lineends
  • UTF-8 encoding without BOM
  • Trim trailing whitespaces
  • Insert final newlines
  • Non-ASCII characters (emoji, accented letter, signs) LC_ALL=C grep -P '[\x80-\xFF]'

EditorConfig, PSR12 ruleset

Use others' work ❗

  • Declare class, method and variable naming, consider PSRs
  • Frameworks/CMS-s
  • Packages/Libraries
  • SaaS (Loco, Paperplane)
  • Unified email, calendar, contacts API (Nylas)
  • Development tools (Vagrant, Laragon)
  • Testing tools (CI)
  • Build and deployment tools (CD)
  • Changelog (Headway)
  • Application performance and error monitoring (Checkly)

Workflow in git :octocat:

  • New feature or fix is ready and "works for me" → PR (new branch)
  • → CI all green → dev branch
  • → Previous feature approved → staging branch + deploy to staging server 🚢
  • → Testing folks approve it → master branch
  • → Wait for release → tag and deploy to production server 🚢

Commit checklist: code, tests, changelog, commit message with emojis 🐛, issue link, watch CI (PULL_REQUEST_TEMPLATE.md)

Release checklist: tag, build, deploy, announce (blog, email, Wiki)

Hotfix flow 💥

  • Catastrophe → hotfix branch + deploy to production server 🚢
  • Alert (email, chat, SMS)
  • Watch logs
  • Merge changes to dev branch

CI outside tests 🔍

What to include in continuous integration with 0% code coverage? (no unit tests, no functional test)

Use Docker containers for testing.

  • Modern task runner (composer:scripts, consolidation/robo, npm:scripts, grunt, gulp)
  • Parallel package installation (hirak/prestissimo)
  • Git hook integration (phpro/grumphp)
  • Parallel syntax check (php-parallel-lint)
  • PSR-12-based coding style (phpcs)
  • Warn on TODO and FIXME: "Move it into issues!" (phpcs)
  • PHP Compatibility check (phpcompatibility/php-compatibility)
  • PHPDoc checker
  • Static analysis (phpstan, larastan, psalm, phan)
  • Mess Detector (phpmd) rules: clean code, code size, controversial, design, naming, unused code
  • Critical vulnerabilities in dependencies (sensiolabs/security-checker, roave/security-advisories, dependencies.io)
  • Build assets (webpack)
  • Metrics (phpmetrics, phploc, laravel-stats)

CI with tests 🔎

  • PHPUnit
  • Measure code coverage
  • Codeception, Behat, KantuX
  • Packaging
  • Test deploy

Try Scrutinizer or Exakat on Debian

Testing tools ⛏️

Tips for developing your application 💡

PSR-1: Basic Coding Standard

A file SHOULD declare new symbols (classes, functions, constants, etc.) and cause no other side effects,
or it SHOULD execute logic with side effects,
but SHOULD NOT do both.

  • Separate frontend, backend, API, CLI, cron/queue
  • Make your frontend a UI for your API ⭐
  • Comment your source code like a travel guide!
  • The less indentation the better code
  • Leave environment settings to the server, and check environment (php-env-check.php)
  • Move resource-intensive tasks to cron jobs/queues
  • Store and calculate dates, times in UTC and display it in the user's timezone
  • Develop simple maintenance tools (e.g. deploy, import, export) for the command line

Parts of an application

  • Autoloading (composer)
  • DI containers
  • Exception handling
  • Logging
  • ORM
  • Database migration
  • Application caching aka. object cache (PSR-6)
  • HTTP communication (request, response, routes) and security (URL structure, WAF)
  • Session handling (very long sessions, CSRF, session expiration UX: timer, warning, redirect, password input)
  • Form handling, input validation, sanitization (UserFrontValidate->Request->BackendValidate->BusinessLogic->Response)
  • Escaping (SQL, HTML, URL, JavaScript)
  • Internationalization and localization (PHP, JavaScript, language, time zone, calendar, number formats and units, string collation), string translation (gettext, pseudo English)
  • Content management: large pieces of markup, reusable content blocks
  • Templating
  • Authentication (Web Authentication API, client certificate, 2FA, password security, lock session to IP address, stronger authentication for admins)
  • Ability of matching an event (uncaught exception) to a user ID or session
  • User roles and capabilities
  • Email addresses, composing and sending (maximum length, obfuscate email addresses, hidden field in form, mailcheck.js, plain text version, NeverBounce)
  • Document generation (CSV, PDF, Excel, image)
  • Image management (Cloudinary, https://blurha.sh/ )
  • Maintenance mode switch and placeholder page (HTTP/503)
  • Static asset management (building, versioning) and loading
  • Search experience
  • Keep A Changelog
  • Analytics, visitor tracking (HEAP, Hotjar, Smartlook, Clicktale)
  • Performance (application monitoring, New Relic)
  • Error tracking: JavaScript, PHP, queue, cron (no overlapping)

Application environment

  • Document everything in hosting.yml
  • Declare PHP version, extensions, directives, functions and test them in php-env-check, run in composer.json:pre-install-cmd, PHP version and extensions also in composer.json:require
  • Have an update policy for PHP, framework, packages
  • Set environment variables (PHP-FPM pool, .env)
  • Publish Dockerfile of CI (GitLab Container Registry, Docker Hub)
  • Build and deploy script (file permissions)
  • Cron jobs and queues (check periodically, email sending and time consuming tasks, catch SIGTERM on system shutdown pcntl_signal(SIGTERM, 'signal_handler');)
  • Generate sitemaps
  • File change notification: siteprotection.sh
  • Manage and monitor application/config/route/view cache and sessions
  • Run git status hourly
  • Report application log extract hourly (recipients)
  • Rotate application log
  • Move per-directory webserver configuration to vhost configuration
  • Redirect removed routes, substitute missing images (URL-s)
  • Use queuing MTA for fast email delivery (external SMTP is slow), bounce handling
  • Include firewall/Fail2ban triggers at least for: 404-s, failed login attempts, hidden form fields (WAF)
  • Host a honey pot
  • Register to webmaster tools (Google, Bing, Yandex)
  • Match production/staging/development/local environments (Docker, php-env-check)

Differences of production and non-production environments ⚙️

  • Environment examples: development, staging, beta, demo
  • Different domain name (SLD)
  • Disallowing robots.txt
  • Different Apache configuration
  • Different PHP extensions and directives (opcache.validate_timestamps)
  • Alternative email delivery
  • Modified application configuration (environment name, debug logging)
  • Change crypto salts, regenerate password hashes
  • Disable/use another CDN
  • Disable/switch to sandbox mode in 3rd party integrations (analytics, chat, performance monitoring, payment gateway)
  • Disable automatic updates
  • Stop cron jobs
  • Visually distinguish non-production sites

Visual signals of a non-production environments

  • Change favicon to an animated GIF image
  • Tag page title <title>[STAGING] $page_title</title>
  • Add a flashy line #MainMavigation { border-top: 3px dashed magenta; }
  • Surround/invert the company logo #BrandLogo { outline: 3px dotted magenta; }
  • Change background color of WordPress admin bar

Login and Sign up page features 🚪

  • Logo and title
  • Language selector
  • News or marketing message
  • "Remember me" checkbox
  • "Forgot password" link
  • Login and Sign up page linking each other
  • Direct registration on login page: email field and signup button
  • SSO
  • Privacy Policy and Terms of Service links
  • Support email and chat/open ticket
  • Marketing message on "logged out" pages

Authentication 🔑

  • Analyze HTTP headers
  • Browser check with JavaScript (proof-of-work)
  • Client-side email address check
  • Suspicious email address:
    • company domain
    • blocked domain (e.g. example.com, *.test)
    • disposable address
    • non-existent domain
    • missing MX
    • unresolvable MX
  • Blocked usernames
  • Force strong passwords:
    • previously used
    • on most common passwords list
    • similarity to name, username or other user details
    • length
    • complexity
    • xkcd password strength
    • pwned password
  • Provide 2FA (TOTP, SMS, email), encourage users to use KeePass
  • Use Argon2 hashing password_hash($pwd, PASSWORD_ARGON2I)
  • Wipe the plaintext password from memory
  • Login security: lock sessions to, and allow login from
    • 1 IP address (IPv4, IPv6)
    • In an IP range (e.g. a /24 network)
    • Within 1 AS (autonomous system) thus inside an ISP
    • Within multiple AS-es (mobile roaming)
    • Within a country
    • Within a region/timezone (multiple countries)
    • Within a continent
    • Same user agent strings
    • Same device (user agent strings) with upgrades (device, OS, browser)
    • Allow/deny multiple (how many?) sessions
    • Session timeout
    • Authorize IP address procedure
    • Login notification
    • New device notification
    • Login logging or last successful login logging
  • Inactive accounts
  • Authentication as a Service
  • Authentication system
  • If you choose an identity provider search the web for its name plus "breach" "exploit" "security"

Email address lifecycle

  • form analyze HTTP request
  • form hidden field in form
  • input maximum length
  • input mailcheck.js
  • input Suspicious email address
  • input NeverBounce
  • output obfuscate email addresses
  • delivery prevent automatic responses
  • delivery detect bounce -> take action (stop sending, notify user or user's team)

User support, user feedback

List: https://www.g2.com/categories/help-desk

Multilingual support.

Login problems

  • Password reminder
  • Ask for a new password
  • Get help (see Logged in section)
  • Suggest a password manager (avoid saving passwords to browser)
  • Short video about password and cybersecurity
  • Signing in on an old login page (reopened by the browser) with expired cookies
  • Login to a specific page (inside the application) through the login page
  • Custom messages on each failed login attempt, automatic redirect to password reminder page

Logged in

Maintenance 🔧

Have me on board: viktor@szepe.net

These lists are theory-free! All of them were real-life problems.