1

I'm tryin to get a list of controller files

$files = scandir(APP_DIR . '/Controller/');

...but I get this error:

Warning (2): scandir(src/Controller/): failed to open dir: No such file or directory [APP/Controller/HomeController.php, line 13]

... when i try to remove some file names from the list: $files = array_diff( $files, array('.','..','Component','AppController.php','HomeController.php'));

... i get this error:

Warning (2): array_diff() [function.array-diff]: Argument #1 is not an array [APP/Controller/HomeController.php, line 23]

my entire class looks this:

<?php
namespace App\Controller;
use ReflectionClass;
use ReflectionMethod;

class HomeController extends AppController{
    public function index(){

        /**
         * http://stackoverflow.com/questions/20963786/how-do-i-get-a-list-of-all-functions-inside-a-controller-in-cakephp
         * http://stackoverflow.com/questions/25892594/list-all-controllers-actions-in-cakephp-3
         */

        $files = scandir(APP_DIR . '/Controller/');
        $controllers = [];
        $ignoreFilesList = [
            '.',
            '..',
            'Component',
            'AppController.php',
            'HomeController.php'
        ];

        $files = array_diff( $files, array('.','..','Component','AppController.php','HomeController.php'));
        $className = '';
        $class = null;
        $ignoreList2 = ['beforeFilter', 'afterFilter', 'initialize', 'delete'];


        echo is_array ( (array)$files );// returns 0 without cast

        foreach( (array)$files as $file){

                $controller = str_replace('Controller', '', explode('.', $file)[0]);
                array_push($controllers, $controller); //str_replace('Controller', '', $controller));

                //dump( $controller );

                /* controller methods */
                $this->$className = 'App\\Controller\\'.$controller.'Controller';
                $this->$class = new ReflectionClass($this->$className);
                $methods = $this->$class->getMethods(ReflectionMethod::IS_PUBLIC);

                echo "<ul><li>$controller</li>";
                echo "<ol>";

                foreach($methods as $method){

                    if ( isset( $method->name )){

                        if($method->class == $className && !in_array($method->name, $ignoreList2))
                        {
                            $controllers[$controller][]= $method->name;
                            echo "<li>$method->name</li>";
                        }
                    }
                }
                echo "</ol>";
                echo "</ul>";

        }

        $this->set('allControllers', $controllers );
    }
}

enter image description here

Tony Chiboucas
  • 5,505
  • 1
  • 29
  • 37
vector
  • 7,334
  • 8
  • 52
  • 80
  • Looks like you're running into a config issue. What is the full path to `HomeController.php`? – Tony Chiboucas Dec 27 '17 at 20:24
  • @TonyChiboucas, relative to the other controllers? It's in that same directory as the others. They sit in /src/Controller/ Added screenshot of the dir layout – vector Dec 27 '17 at 20:31
  • Why didn't I see this sooner, scandir doesn't play nice with relative paths. Try `$path = $_SERVER['DOCUMENT_ROOT'] . '/'. APP_DIR .'/Controller/'; $files = scandir($path);` or some variation thereof. You'll have better results defining a root path for scandir. – Tony Chiboucas Dec 27 '17 at 20:42
  • 1
    @TonyChiboucas - spot on :-) I'll gladly accept it as an answer. – vector Dec 27 '17 at 21:05
  • 2
    The proper path constant to use is `APP`, which contains an asbolute path that points to the `src` folder. – ndm Dec 28 '17 at 12:31

1 Answers1

2

Only use PHP: scandir with a full path.

While the PHP documentation says nothing about it, scandir generally does not play nice with relative paths. (Though there are cases where relative paths can work perfectly fine.)

Path arg is a relative path here

As APP_DIR stores a single directory name, and not a path, scandir will attempt to access src/Controller/, which may not relative to the script currently running.

$files = scandir(APP_DIR . '/Controller/');

Solution 1: Use CakePhp: constant APP to build the full path

Thanks to ndm for reminding us of the APP constant in his comment on the OP. APP stores an absolute path to your application directory, including a trailing slash.

$path = APP .'Controller/';
$files = scandir($path);

Solution 2: Use PHP: $_SERVER['DOCUMENT_ROOT'] to build a full path.

$path = $_SERVER['DOCUMENT_ROOT'] . '/'. APP_DIR .'/Controller/';
$files = scandir($path);

Alternatively, you may be able to use PHP: Realpath to retrieve the full path. *reminder: working directory will vary depending on the script running.

Tony Chiboucas
  • 5,505
  • 1
  • 29
  • 37