• Как можно решить проблему с доступам к методам PHP классов унаследованным от одного класса?

    alestro
    @alestro
    Как вариант можно сбрасывать скоп внутри метода $api->dependency

    class Node
    {
        protected function func1() {
        }
    }
    class NodeA extends Node
    {
        public function FUNC2() {}
    }
    class NodeB extends Node
    {
        // Функция инициализации
        public function __construct()
        {
            (new Api())->dependency(
                function (?NodeA $a) {
                    $a->FUNC2(); // Метод успешно вызывется так как он public
                    $a->func1();  // Call to protected method Node::func1() from global scope
                }
            );
        }
    }
    
    class Api {
        function dependency(callable $dependency) {
            if ($dependency instanceof Closure) {
                $dependency = Closure::bind($dependency, null, null);
                $dependency(new NodeA());
            }
        }
    }


    Либо можно использовать белый список и проверить стек вызовов, если вызывающего класса нет в списке, то кидать исключение.

    class Node
    {
        private array $whiteList = [
            NodeA::class
        ];
    
        protected function func1() {
            $scope = debug_backtrace(2, limit: 2)[1]['class'];
            if (!in_array($scope, $this->whiteList)) {
                throw new Exception('Нельзя вызвать метод для данного класса '. $scope);
            }
        }
    }
    class NodeA extends Node
    {
        public function FUNC2() {}
    }
    class NodeB extends Node
    {
        // Функция инициализации
        public function __construct()
        {
            (function (?NodeA $a) {
                $a->FUNC2(); // Метод успешно вызывется так как он public
                $a->func1();  // Нельзя вызвать метод для данного класса NodeB
            })(new NodeA());
        }
    }
    Ответ написан
    1 комментарий
  • Как можно решить проблему с доступам к методам PHP классов унаследованным от одного класса?

    Красиво сделать не получится. Но можно сделать так, чтобы хотя бы на тестах оно упало и показало, что нельзя так делать.

    <?php
    
    class Node
    {
        protected function func1() {
            print "NODE PARENT; ";
        }
    }
    class NodeA extends Node
    {
        public function FUNC2() {
            print "NODE A; ";
        }
    
        // Используем метод родителя внутри этого класса
        public function func1Overrided() {
            print "From parent: " . parent::func1();
        }
    
        // Переопределяем метод так, чтобы его нельзя было использовать
        protected function func1() {
            throw new \Exception("Нельзя вызывать этот метод из NodeB");
        }
    }
    
    class NodeB extends Node
    {
        // Функция инициализации
        public function onInit(NodeA $a): void
        {
            // Сделал так, чтобы не мокать api )
            (function (?NodeA $a) {
                $a->FUNC2(); // Метод успешно вызывется так как он public
                $a->func1();  // Метод теперь кидает исключение, использовать не получится
            })($a);
        }
    }
    
    $nodeA = new NodeA;
    $nodeA->func1Overrided(); // Работает вызов метода funс1 из родителя
    
    $nodeB = new NodeB;
    $nodeB->onInit($nodeA); // Выдаёт ошибку, нельзя использовать метод func1 из класса NodeB


    Но у меня для вас совет: старайтесь как можно меньше использовать наследование. Из моего опыта могу сказать, что всякий раз, когда я с помощью наследования пытаюсь решить хоть сколько-нибудь сложную задачу, постоянно вылазят такие подводные камни, что жить не хочется. Используйте композицию и интерфейсы, и вам не придётся заниматься подобной ерундой.

    Вот минимально-инвазивное решение, которое позволит и наследование сохранить (если оно прям ну вот сильно надо), и решить проблему при помощи композиции, основанной на трейте.

    <?php
    // Делаем общий трейт для всех классов
    trait Func1 {
        private function func1() {
            print "FUNC1; ";
        }
    }
    
    class Node
    {
        // Включаем трейт
        use Func1;
    }
    
    class NodeA extends Node
    {
        // Включаем трейт
        use Func1;
    
        public function FUNC2() {
            print "FUNC 2 NODEA; ";
        }
    }
    
    class NodeB extends Node
    {
        // Включаем трейт
        use Func1;
    
        // Функция инициализации
        public function onInit(NodeA $a): void
        {
            // Добавить зависимость
            (function (?NodeA $a) {
                $a->FUNC2(); // Метод успешно вызывется так как он public
                $a->func1();  // Метод использовать не получится, т.к. он private
            })($a);
        }
    }
    
    $nodeA = new NodeA;
    
    $nodeB = new NodeB;
    $nodeB->onInit($nodeA); // Выдаёт ошибку, нельзя использовать метод func1 из класса NodeB
    Ответ написан
  • Можно ли перезапустить сервер консольной командой?

    @Yadalay Автор вопроса
    Php, Mysql, Html, Css, Js/Jquery/Ajax, Laravel
    Нашёл всё-таки ответ. Вот:
    "C:\Openserver\Open Server.exe" /restart (перезапуск сервера)
    ---
    В кавычках указывается свой путь до исполняемого файла OpenServer.
    Если у вас 64-битная, то адрес будет, например, таким: "С:\OpenServer\Open Server x64.exe" /restart
    Ответ написан
    Комментировать
  • Как в параметре маршрута использовать значение с точкой?

    yarkov
    @yarkov Куратор тега Vue.js
    Помог ответ? Отметь решением.
    Интересная ситуация. Очевидно что путь с точкой обрабатывается как "имяфайла.расширение". Вот на стэковерфлоу кажется ваша проблема описана
    https://stackoverflow.com/questions/71029445/handl...
    Ответ написан
    Комментировать
  • Как изменить имя выходного файла через CMakeLists.txt?

    @res2001
    Developer, ex-admin
    На счет имени таргета посмотрите тут: https://stackoverflow.com/questions/31038963/how-d...
    С каталогом, ну я бы в проекте сделал подкаталог MyDir и в нем свой cmakelists.txt с описанием таргета для библиотеки. Библиотека будет собираться в своем подкаталоге. В корневой cmakelists.txt включать подкаталог с помощью add_subdirectory(MyDir)
    Ответ написан
    1 комментарий
  • Как продолжить выполнение php кода после Fatal Error?

    SilenceOfWinter
    @SilenceOfWinter Куратор тега PHP
    та еще зажигалка...
    shasoftX, добавь автозагрузчик который в случае отсутствия класса выполняет `class_alias(Dummy::class, $className)`, но тогда смысла нет смысла в рефлексии.
    Ответ написан
    2 комментария