За последние 24 часа нас посетили 22669 программистов и 1059 роботов. Сейчас ищут 739 программистов ...

Вызвать функции из папки

Тема в разделе "PHP для новичков", создана пользователем Danil005, 22 авг 2019.

  1. Danil005

    Danil005 Активный пользователь

    С нами с:
    2 янв 2015
    Сообщения:
    528
    Симпатии:
    30
    Как вызвать функции из папки по очереди?
    PHP:
    1. class CommandsController
    2. {
    3.     private static $dir = 'src/Commands';
    4.  
    5.     public static function execute(array $object)
    6.     {
    7.         $files = scandir(self::$dir, 0);
    8.         $count_files = count($files);
    9.         for($i = 2; $i < $count_files; $i++) {
    10.             if( $files[$i] != 'CommandsController.php' ) {
    11.                 $class = (string) explode('.', $files[$i])[0];
    12.                 (new $class($object))->execute();
    13.             }
    14.         }
    15.     }
    16. }
    Но выдает, что class not found, хотя если сделать new <Class>(), то все работает отлично
     
  2. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    @Danil005, что ты городишь?
     
  3. Danil005

    Danil005 Активный пользователь

    С нами с:
    2 янв 2015
    Сообщения:
    528
    Симпатии:
    30
    Мне нужно запустить каждый метод из каждого файла
    --- Добавлено ---
    И все работает на autoload
     
  4. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    это какое-то мракобесие
     
  5. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.744
    Симпатии:
    1.319
    Адрес:
    Лень
    __autoload deprecated
    --- Добавлено ---
    что в методах есть ?
     
  6. mike4ip

    mike4ip Новичок

    С нами с:
    24 авг 2019
    Сообщения:
    18
    Симпатии:
    1
    Вы не включаете файл с классом, а сразу же его создаёте. Поэтому он не находится. Сделайте сперва require_once($dir . '/' . $files[$i]);

    И autoload прокачайте, видимо, он у вас кривой. Дадите код в студию - подскажу, что можно сделать.
     
  7. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.744
    Симпатии:
    1.319
    Адрес:
    Лень
    @mike4ip зачем советуешь кеш забивать файлом ?
     
  8. mike4ip

    mike4ip Новичок

    С нами с:
    24 авг 2019
    Сообщения:
    18
    Симпатии:
    1
    Вы о чём? Без включения файла класс из него не вызвать.
     
  9. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.744
    Симпатии:
    1.319
    Адрес:
    Лень
    я об *_once, зачем файл заливать в кеш ?
     
  10. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    А зачем его несколько раз подключать?
     
  11. mike4ip

    mike4ip Новичок

    С нами с:
    24 авг 2019
    Сообщения:
    18
    Симпатии:
    1
    Ну это так, привычка у меня такая... в данном случае вероятность повторного включения нулевая, поэтому необязательно.
     
  12. vvas

    vvas Новичок

    С нами с:
    9 апр 2018
    Сообщения:
    50
    Симпатии:
    10
    Админы, это точно вопрос для профи?

    Чтобы странная задумка работала, надо проверить две вещи:
    - реальное имя класса в переменной $class, содержит ли оно неймспейс;
    - как настроена автозагрузка классов. если пользуешься composer (!!!), то в секции "autoload" можно маппинг по неймспейсам задать.
     
    MouseZver нравится это.
  13. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.744
    Симпатии:
    1.319
    Адрес:
    Лень
    Затем, что spl
    PHP:
    1. spl_autoload_register ( function ( $name )
    2. {
    3.     $replaces = [
    4.         '\\' => DIRECTORY_SEPARATOR,
    5.         'Aero\\Database\\' => 'src\\Lerma\\Database\\',
    6.         'TestingMethods' => 'TestingMethods\\TestingMethods'
    7.     ];
    8.    
    9.     include strtr ( $name, $replaces ) . '.php';
    10. } );
    Регистрирует NAMESPACE + NAME класса и больше не загружает файл по новому. Это для единой точки, всей системы сайта.
     
    vvas нравится это.
  14. vvas

    vvas Новичок

    С нами с:
    9 апр 2018
    Сообщения:
    50
    Симпатии:
    10
    Я думаю проблема именно в неймспейсе. Когда ты находясь в namespace Foo, делаешь new Bar(), то реально происходит new \Foo\Bar()
    !!!!!!1111111расрас

    Но это НЕ работает внутри хитровыделанных фокусов с переменными и функциями. В них подстановка текущего неймспейса не работает. Надо явно писать $class = "Foo\Bar" (лидирующий \ можно не писать) чтобы сработал new $class()
     
    Danil005 нравится это.
  15. mike4ip

    mike4ip Новичок

    С нами с:
    24 авг 2019
    Сообщения:
    18
    Симпатии:
    1
    Подозрение ещё вызывает вот это:

    Начинаю думать, что explode что-то не то выдаёт. И делать (string) там, где возвращается строка, тоже незачем.
     
  16. vvas

    vvas Новичок

    С нами с:
    9 апр 2018
    Сообщения:
    50
    Симпатии:
    10
    @mike4ip при чём тут explode :D . Класс не найден потому что напутано с пространством имён. Инфа 100%.
    См. моё объяснение в предыдущем каменте.

    Допустим у нас есть классы Foo\Bar и Foo\Baz, которые нормально мапятся неважно в какие папки, главное автолоадер их находит )))
    И мы хотим обратиться из одного класса к другому:
    PHP:
    1. <?php
    2.  
    3. namespace Foo;
    4.  
    5. class Baz
    6. {
    7.     public function hello()
    8.     {
    9.         // $class = 'Bar'; new $class(); -- так будет ошибка "класс не найден", потому что неймспейс не указан
    10.         // при том, что new Bar() работает нормально, потому что здесь PHP учитывает "текущее пространство имён"
    11.         // но если имя класса в переменной, то текушее пространство игрорируется. делай так:
    12.         $class = 'Foo\\Bar'; // а вот так сработает!
    13.         $bar = new $class();
    14.         $barHello = $bar->hello();
    15.         return 'It\'s not "'.$barHello.'" but "Hello from ' . self::class.'"';
    16.     }
    17. }
    Проверочка в консоли
    Код (Text):
    1.  
    2. $ php index.php
    3. Hello from Foo\Bar
    4. It's not "Hello from Foo\Bar" but "Hello from Foo\Baz"
     

    Вложения:

    #16 vvas, 25 авг 2019
    Последнее редактирование: 25 авг 2019
  17. mike4ip

    mike4ip Новичок

    С нами с:
    24 авг 2019
    Сообщения:
    18
    Симпатии:
    1
    Не понимаю, откуда такой вывод. Мне кажется, наш товарищ вообще неймспейсы не использует.
     
  18. vvas

    vvas Новичок

    С нами с:
    9 апр 2018
    Сообщения:
    50
    Симпатии:
    10
    Это тебе кажется. Какой-то автолоадер у него работает, он это указал в посте. Моя демка в приаттаченном ариве. Можешь поиграть с комментированием/раскомментированием и намотать инфу на ус.

    Не забываем ставить лайки!
     
  19. mike4ip

    mike4ip Новичок

    С нами с:
    24 авг 2019
    Сообщения:
    18
    Симпатии:
    1
    У меня инфа про аутолоадеры и неймспейсы давно намотана уже. Просто автор вопроса не удосужился дать полную картину, теперь приходится перебирать все возможные варианты.
     
  20. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.744
    Симпатии:
    1.319
    Адрес:
    Лень
    без неймспейсов, придется городить библиотеку путей [ 'class_name' => 'directory...' ], как в Yii
     
  21. vvas

    vvas Новичок

    С нами с:
    9 апр 2018
    Сообщения:
    50
    Симпатии:
    10
    @Danil005 ты бы ещё разик вывел содержимое массива после scandir(). А вдруг там не то, что ты думаешь! Например '.' и '..' — ты их тоже как имена классов будешь обрабатывать?

    Слушай var_dump() используй, да! Надо отладкой пользоваться прежде чем спрашивать "профи".
     
  22. mike4ip

    mike4ip Новичок

    С нами с:
    24 авг 2019
    Сообщения:
    18
    Симпатии:
    1
    Это понятно. Просто ТС не упоминал неймспейсы, в приведённом коде класса его тоже не было. Поэтому и не подумал, что дело может быть в этом.
     
  23. Danil005

    Danil005 Активный пользователь

    С нами с:
    2 янв 2015
    Сообщения:
    528
    Симпатии:
    30
    Все было сделано на composer лоаде, все настроено правильно.
    PHP:
    1. <?php
    2.  
    3. namespace Roma\Commands;
    4.  
    5.  
    6.  
    7. class CommandsController
    8. {
    9.     private static $dir = 'src/Commands';
    10.  
    11.     public static function execute(array $object)
    12.     {
    13.         $files = scandir(self::$dir, 0);
    14.         for($i = 2; $i < count($files); $i++) {
    15.             if( $files[$i] != 'CommandsController.php' ) {
    16.                 $class = 'Roma\Commands\\' . (string) explode('.', $files[$i])[0];
    17.                 (new $class($object))->execute();
    18.             }
    19.         }
    20.     }
    21. }
    Вот решение.
    --- Добавлено ---
    А это я делал для того, чтобы класс по типу 1.php, был стрингом (это бот просто).
     
  24. mike4ip

    mike4ip Новичок

    С нами с:
    24 авг 2019
    Сообщения:
    18
    Симпатии:
    1
    Всё равно лишнее, оно итак конкатенируется к строке. Но это уже детали.
     
  25. vvas

    vvas Новичок

    С нами с:
    9 апр 2018
    Сообщения:
    50
    Симпатии:
    10
    Ну вот, я был прав про упущенный неймспейс. @mike4ip :)

    Дополнительно я бы рекомендовал непонятные for ($i=2;...) и explode('.',...) заменить на более надёжное:
    PHP:
    1. $files = scandir(__DIR__);
    2. foreach ($files as $file) {
    3.   if (pathinfo($file, PATHINFO_EXTENSION) !== 'php' || $file === 'CommandsController.php') {
    4.     continue;
    5.   }
    6.   $class = __NAMESPACE__ . '\\' . basename($file, '.php');
    7.   // ...
    8. }