3

I have a composer package that is used in internal projects. Historically all classes in this package were autoloaded via "autoload": { "classmap": ... } and have not been structured.

Now I want to migrate to PSR-4. I reordered all files and directories according to class namespaces. Namespaces or class names were not changed, only file locations/names were.

How do I validate my new file/class structure to ensure it conforms to PSR-4 and all classes are loadable via "autoload": { "psr-4": ... }? I've made a google search but did not find any tool for that.

cronfy
  • 1,001
  • 1
  • 15
  • 32

2 Answers2

3

I was able to solve my problem using hints from Jakub Zalas's answer (option 2).

The idea is to:

  1. Copy composer's working autoload_classmap.php to autoload_classmap-orig.php.
  2. Rearrange classes/change composer.json as required.
  3. Test new autoload against orig classmap.

To avoid situation when including one class' source file automaticaly defines another class (i. e. more than one class is defined in one file), each class should be loaded in clean php environment (separate php-cli run).

I used 2 scripts for that:

Class autoload checker (check.php):

<?php

// test if a class, mentioned in autoload_classmap-orig.php at line $num,
// can be autoloaded. Exit status: 0 - ok, 4 - failed to autoload,
// 3 - no more classes in autoload_classmap-orig.php

error_reporting(0);
require_once(__DIR__ . "/vendor/autoload.php");

$num = $argv[1];

$classes = array_keys(include('autoload_classmap-orig.php'));

if (!isset($classes[$num])) {
        exit(3);
}

$current_class = $classes[$num];
echo $current_class;
if (!class_exists($current_class)) {
        exit(4);
}

exit(0);

Iterator (check.sh)

#!/usr/bin/env bash

# call ./check.php until all classes are checked or max number
# of checks reached.

max=500
num=0

while true ; do
    php ./check.php $num 
    status=$?
    case $status in
        0) echo " - OK" ;;
        3) echo "\nFinished." ; break ;;
        4) echo " - CAN NOT BE AUTOLOADED" ;;
        *) echo " - UNKNOWN ERROR $status" ;;
    esac

    num=$(($num + 1))
    if [ "$num" -gt "$max" ] ; then
        echo "\nMax number of classes reached."
        break
    fi
done
cronfy
  • 1,001
  • 1
  • 15
  • 32
1

Option 1

Run your tests.

Whenever they're automated or manual, they'll reveal any classes that are not possible to autoload.

Option 2

Write a simple script that would:

  • list all PHP classes (FQCNs)
  • include the composer autoloader (with psr4 configured)
  • for each class try to call class_exists (which will trigger autoloading)

If the class_exists fail for a given class, it means its namespace is not properly configured.

Jakub Zalas
  • 35,761
  • 9
  • 93
  • 125
  • Thank you for a hint! How would I list all PHP classes (FQCNs)? Is there any tool for that (I could write some grep/sed/awk, but if there is a tool it would be more reliable). – cronfy Oct 21 '16 at 10:45