Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Backport Laravel Package

dansan/php-backport

Dev tool to backport PHP source code for older runtimes (e.g., PHP 7.2+ features down to PHP 7.0). Configure directories to port, run a script on a *_bp branch, commit/push, then require the backported dev branch in Composer.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require dansan/php-backport --dev
    

    Add to composer.json under require-dev (not require) since this is a dev tool.

  2. Create backport.php: Place this in your project root (e.g., bin/backport.php):

    <?php
    require __DIR__.'/../vendor/autoload.php';
    
    $client = new \BackPort\Client();
    $client
        ->setDirsToPort([__DIR__.'/../src'])
        ->execute();
    
  3. First Run:

    • Create a backport branch (e.g., master_bp):
      git checkout -b master_bp
      
    • Execute the script:
      php bin/backport.php
      
    • Commit and push the changes.

First Use Case

Scenario: Your Laravel app (Alpha) depends on a package (Beta) that uses PHP 7.2+ features, but Alpha is locked to PHP 7.0. Solution:

  1. Fork Beta and create a master_bp branch.
  2. Run backport.php to transform Beta's code to PHP 7.0-compatible syntax.
  3. Update Alpha's composer.json to require Beta from dev-master_bp@dev.
  4. Test thoroughly in a PHP 7.0 environment.

Implementation Patterns

Workflow Integration

  1. Branch Strategy:

    • Maintain dual branches:
      • master: Latest PHP 7.2+ features (default for most projects).
      • master_bp: Backported PHP 7.0-compatible version (for legacy projects like Alpha).
    • Merge master into master_bp regularly, resolve conflicts by accepting master's changes (since backported code is derived).
  2. Automated Backporting:

    • Extend backport.php to handle project-specific needs:
      $client
          ->setDirsToPort([__DIR__.'/../src', __DIR__.'/../tests'])
          ->addComposerJsonReplacement(
              '/"vendor\/package": "[^"]+"/',
              '"vendor/package": "dev-backport-branch@dev"'
          )
          ->execute();
      
    • Key Methods:
      • setDirsToPort(): Specify directories to backport (e.g., src, tests).
      • addComposerJsonReplacement(): Update dependencies in composer.json (e.g., switch Gamma to its backport branch).
      • execute(): Run the backport process.
  3. CI/CD Pipeline:

    • Add a step to run backport.php on master_bp after merging master.
    • Example GitHub Actions workflow:
      jobs:
        backport:
          runs-on: ubuntu-latest
          steps:
            - uses: actions/checkout@v3
              with:
                ref: master_bp
            - run: composer install
            - run: php bin/backport.php
            - run: composer update
            - run: ./vendor/bin/phpunit
      
  4. Laravel-Specific Patterns:

    • Service Providers: If Beta is a Laravel package, ensure its master_bp version:
      • Uses PHP 7.0-compatible syntax (e.g., replace arrow functions with function() use(...)).
      • Avoids PHP 7.2+ features like array_key_first() (use reset(array_keys($array)) instead).
    • Configuration: Update config/ files to handle PHP 7.0 limitations (e.g., no typed properties).
  5. Testing:

    • Run tests in both PHP 7.0 and 7.2+ environments:
      # Test backported version
      docker run --rm -v $(pwd):/app -w /app composer/php:7.0-cli composer install
      docker run --rm -v $(pwd):/app -w /app composer/php:7.0-cli vendor/bin/phpunit
      
      # Test latest version
      docker run --rm -v $(pwd):/app -w /app composer/php:8.1-cli vendor/bin/phpunit
      

Gotchas and Tips

Pitfalls

  1. Branch Management:

    • Accidental Overwrites: Running backport.php on master or a feature branch will overwrite files. The script checks for _bp suffix but verify manually.
    • Conflict Resolution: Always accept master's changes during merge (backported code is a derivative). Use:
      git checkout master_bp
      git merge master --strategy-option=ours  # Then run backport.php
      
    • Orphaned Branches: Delete and recreate master_bp if corruption is suspected:
      git checkout master
      git branch -D master_bp
      git push origin -d master_bp
      git checkout -b master_bp
      
  2. PHP Syntax Limitations:

    • Arrow Functions: Replace fn($x) => $x with function($x) { return $x; }.
    • Null Coalescing Assignment: Replace $x ??= $y with $x = $x ?? $y.
    • Typed Properties: Remove types (PHP 7.0 doesn’t support them):
      // Before (PHP 7.2+)
      private ?string $name;
      
      // After (PHP 7.0)
      private $name;
      
    • Spaceship Operator: Replace <=> with manual comparison logic.
  3. Composer Dependencies:

    • Circular Dependencies: If Beta backports Gamma, ensure Gamma's master_bp is updated first.
    • Version Conflicts: Use exact versions in master_bp's composer.json to avoid unexpected updates:
      "require": {
          "acme/gamma": "dev-master_bp#1.2.3"
      }
      
  4. Testing Quirks:

    • Environment Mismatch: Tests may pass in PHP 7.2+ but fail in 7.0 due to:
      • Undefined constants (e.g., PHP_VERSION_ID changes).
      • Missing functions (e.g., array_column() requires PHP 5.5+; use array_map fallback).
    • Mocking: Use Mockery or PHPUnit’s mocks (PHP 7.0-compatible).
  5. Performance:

    • Backporting adds overhead. Cache the AST parsing results if running frequently:
      $client->setCacheDir(__DIR__.'/../var/backport_cache');
      

Debugging Tips

  1. Inspect AST Changes:

    • Enable verbose output in backport.php:
      $client->setVerbose(true);
      
    • Check the nikic/php-parser documentation for custom visitor logic.
  2. Log Conflicts:

    • Add a pre-backport check to log conflicts:
      $client->setConflictLogger(function($file, $conflict) {
          file_put_contents('backport_conflicts.log', $file . "\n" . $conflict . "\n\n", FILE_APPEND);
      });
      
  3. Dry Runs:

    • Test changes without committing:
      git stash
      php bin/backport.php
      git diff  # Review changes
      git stash pop
      

Extension Points

  1. Custom Visitors:

    • Extend the backport logic by adding custom visitors to the parser. Example:
      use PhpParser\NodeVisitorAbstract;
      
      $client->addVisitor(new class extends NodeVisitorAbstract {
          public function enterNode(\PhpParser\Node $node) {
              if ($node instanceof \PhpParser\Node\Expr\ArrowFunction) {
                  // Transform arrow function to anonymous function
                  return new \PhpParser\Node\Expr\Closure(
                      [$node->getParams()],
                      $node->getStmts()
                  );
              }
              return null;
          }
      });
      
  2. Pre/Post Hooks:

    • Run scripts before/after backporting:
      $client->setPreBackportHook(function() {
          // Example: Run PHPStan to catch issues before backporting
          shell_exec('vendor/bin/phpstan analyse --level=5 src');
      });
      
  3. Selective Backporting:

    • Exclude files/directories:
      $client->setDirsToPort([__DIR__.'/../src'])
             ->setExcludedFiles(['src/DeprecatedClass.php']);
      
  4. PHP Version Targeting:

    • Target PHP 5.6 instead of 7.0 by modifying the visitor rules (requires customization of the underlying parser logic).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
craftcms/url-validator
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony