@BushaevDenis

Как получить доступ к методу, который вызывает текущий метод?

У меня есть главный класс, который всем управляет (app)
К нему идут все запросы клиентов (html, ajax).
В app->__construct запускаю метод app->ajax, который проверяет какой метод пытается запустить ajax делаем экземпляр другого класса, который (я планирую) будет содержать все ajax методы (appAjax).
Но в этом appAjax мне нужен доступ к основному классу (app).
Схема такая

App.php:
class App() {

function __construct() {

     ob_start();
     self::ajax();
}

private function ajax() {
     if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && ! empty( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest' ) {
			ob_end_clean();
			if ( ! empty( $_POST['ajax_action'] ) ) {

				$method_name = $_POST['ajax_action'];

				self::includeModule( 'ajaxes' );  //Инклудится файл с appAjax

				$ajax = new appAjaxes();

				if ( method_exists( $ajax, $method_name ) ) {
					$ajax->$method_name();
					die();
				}
			}
		} else {
			return;
		}
		die( '0' );
}

}

function __destruct() {
		ob_end_flush();
	}


ajaxes.php
class appAjaxes {

	function test() {
               //Как вот тут получить доступ к методам App?
		echo 'test';

	}
}



Сразу говорю, это моя первая попытка писать ООП. Выслушаю все предложения. (Решил не начинать с фреймворков, ибо самому хочется понять как это делать с вытекающими и получением своего опыта.
  • Вопрос задан
  • 217 просмотров
Решения вопроса 2
402d
@402d
начинал с бейсика на УКНЦ в 1988
Если, что-то можно сделать только через жопу, то наверное Вы делаете, что-то не то.

Паттерн синглетон для класса App - самое то .
Ответ написан
Комментировать
ThunderCat
@ThunderCat Куратор тега PHP
{PHP, MySql, HTML, JS, CSS} developer
Но хотелось бы красиво всё сделать с одной точкой входа.

у вас слегка неверное понятие единой точки входа.
1) Статика это плохо, тем более если это стартовый класс.
2) Не проще организовать нормальный мвц?
3) Как заметил Олег Муравейко - если вы пытаетесь почесать яйца пяткой - скорее всего вы выбрали не ту конечность.

точка входа - индекс, она уже вызывает класс Апп, или бутстрап или еще какой-то стартовый класс, который уже выполняет настройку окружения и запускает Роутер, в котром и происходит магия выбора Контроллера и экшна, после чего уже все полученные в контроллере данные передаются в Вид, который рендерится и отдается клиенту. У вас же прям в стартовом классе все в кашу - и старт контроллеров, и "роутинг", и экшны запускаются. Салют салатом.
Нужен аякс - заводите аякс контроллер и там уже экшны, которые отвечают на определенные запросы от фронта.
Нужен Юзер - заводитен юзер контролллер и там все экшны - лист, эдд, делит, едит, шоу...
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@tester_toster
Добавлю к ответам остальных - еще посоветовал бы почитать про depency injection.
Посмотрите, как приложение реализовано laravel.
Там есть хелпер app(), который всегда вернет экземпляр приложения из контейнера "прямого singleton" - там нет, за три года разработки ни разу не увидел необходимости прямого singlton, все можно сделать через контейнер управления зависимостями.
Если вы не используете фреймворк, или хотите написать сами, вот вам мой пример:
точка входа: index.php
-- Подключается автозагрузка классов, лучше composer - без этого сейчас писать моветон.
-- Подключается файл с хелперами и нужными функциями: app() и.т.д.
-- Создается обертка для request вида: $request = new request($_GET,$_POST,...) и.т.д.
-- Создается экземпляр приложения: $app = new App($config), где конфиг либо массив настроек, либо в моем случае класс.
-- $response = $app->handle($request), у меня просто echo $app->handle($request), присутствует немного магии
-- Как выглядит метод handle:
$this->instance(RequestContract::class, $request);
        try {
            $this->instance(RequestContract::class, $request);
            $response = $this->getPipeLine()->send($request);

            $this->afterHandle($request);
        } catch (\Exception $e){
            $response = app(Handler::class)->handle($e);
        }

        if(!$response instanceof ResponseContract){
            $response = $this->prepareResponse($response);
        }

        return $response;

Объект request - регистрируется в контейнере и всегда будет отдаваться один и тот-же экземпляр.
$this->getPipeLine - можете упростить, у меня это посредники (laravel style), в этом месте возьмите сразу работу с диспетчером роутера.
Я использую обвязку для fastroute, так как это реальный проект, но написать на регулярках простой роутер несложно.
Если роут не найден, либо была ошибка в коде в глубину - выбрасывается определенный exception, который обрабатывается в специальном классе и также отдает response с 404, 501 и.т.д. ошибками.
Если роут найден, то он вызывается и возвращает данные.
Я использую контейнер laravel с autowiring, в моем случае, если контроллер и метод найдены, все выглядит так.
return $this->container->call(
                    [$this->container->make($handler[0], $routeInfo[2]), $handler[1]],
                    $routeInfo[2]
                );

Автоваринг - достаточно удобная штука на рефлексии, сама подставляет зависимости из контейнера, и если не ошибаюсь, в laravel появилась раньше, чем в symfony, свой контейнер похожий на laravel вышел 130 строчек, можете поискать в английском интернете по фразе: "php autowiring"- там есть статьи на эту тему.
Сейчас меня заплюют, про то, что нужно взять готовый фреймворк и не писать костыли, но при 10млн просмотров нестатичных страниц в день, такое решение в разы обходит по скорости готовый фреймворк, так как лишнего ничего нет. Еще вам скинули ссылку на курс на ютубе Дмитрия Елисеева, может быть он и профессиональный разработчик, но видосики по 2 часа - это реальное издевательство, очень сильно разжевано, да, но очень долго, возможно отдельный редактор бы его спас. Я бы его лучше слушал вместо музыки. То, что ты именно не понимаешь - глазами не найти, лучше ищите статьи, желательно на английском, очень много разных заметок, смотрите исходные коды разных фреймворков - это даст вам понять, как все работает. Еще скажу о PSR - это не свод законов, а рекомендации, хотя первые - это реальное табу, нарушать нельзя, но все psr не поддерживает почти не один современный фреймворк. Так как стандартизация не всегда вяжется с удобством и скоростью, всегда приходится выбирать.
P.S Это только мой взгляд, у разных людей - разные мнения и разный опыт.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы