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

Что у меня есть: класс Game (как часть фреймворка Laravel 5.5)

class Game implements GameInterface
{
    private $currentGame;

    public function __construct()
    {
        $this->currentGame = Game::where('status', true)->first();
    }

    public function getPlayersAmount()
    {
        if ($this->currentGame)
            //fetch data & return it
        else
            return 0;
    }

    public function getPlayers()
    {
        if ($this->currentGame)
            //fetch data & return it
        else
            return null;
    }

    public function getAllStats()
    {
        if ($this->currentGame)
            //fetch data & return it
        else
            return null;
    }

    public function getTopScore()
    {
        if ($this->currentGame)
            //fetch data & return it
        else
            return 0;
    }
}

Моя проблема - if ($this->currentGame). Я должен поместить его в каждый метод, чтобы избежать исключений, связанных с Eloquent.

Как я могу сделать эту проверку if ($this->currentGame) перед каждым вызовом метода, чтобы избежать дублирования кода?

__call() не работает для общедоступных методов.

Мое текущее использование класса:

$game = new Game();
$game->getPlayers();
//and so on

Game сама по себе красноречивая модель? Вроде так из звонка Game::where(.... Если это так, то почему вы устанавливаете currentGame на другой экземпляр Game и используете его в этих методах, а не просто используете текущий экземпляр?

Don't Panic 02.10.2018 23:33

Похоже, вам следует исправить второстепенную проблему, а не устранять ее симптомы хакерским способом. if ($this->currentGame). I have to place it inside each method to avoid Eloquent-related Exceptions. Я не использую Eloquent, но я использовал пару ORM в свое время, возможно, если вы дадите больше информации о том, что это такое ... .

ArtisticPhoenix 02.10.2018 23:36

@ Don'tPanic Game - яркая модель. Я ошибся, это может быть класс CurrentGame, но не Game. Редактировать не буду, потому что ответы уже есть.

Tarasovych 03.10.2018 15:16

@ Тарасович, вы видели ответы ниже?

yivi 03.10.2018 19:24

@yivi да, все еще ищу то, что мне подойдет

Tarasovych 03.10.2018 19:55

Почему ответы тебе не подходят? Расскажите подробнее, почему они вам не подходят, и мы постараемся помочь.

scorgn 05.10.2018 00:16
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
6
81
3

Ответы 3

Думаю, этого можно добиться с помощью __call и call_user_func_array.

class Game implements GameInterface
{
    private $currentGame;

    public function __construct()
    {
        $this->currentGame = Game::where('status', true)->first();
    }

    public function __call($name, $arguments) {
        $name = '_'.$name;
        if ($this->currentGame && method_exists($this,$name)) return call_user_func_array(array($this, $name), $arguments);
        return null;
    }

    private function _getPlayersAmount()
    {
        return "sthg";
    }

    private function _getPlayers()
    {
        return "sthg else";
    }

    private function _getAllStats()
    {
        return "also sthg else";
    }

    private function _getTopScore()
    {
        return "different one";
    }
}

просто мы реализуем наши функции как частные с немного другим именем и позволяем им вызывать через __call через call_user_func_array. Мы также могли бы использовать switch-case, но так он более динамичный.

Вы можете использовать __call с этим, вам просто нужно сделать свои общедоступные функции частными, а затем добавить к ним какой-нибудь уникальный префикс, чтобы убедиться, что они являются единственными частными функциями, которые могут быть общедоступными.

Вот пример.

class Game implements GameInterface
{
    private $currentGame;

    public function __construct()
    {
        $this->currentGame = Game::where('status', true)->first();
    }

    public function __call($method, $args)
    {
        if ($this->currentGame) 
            return call_user_func_array(array($this, 'public'.ucfirst($method)), $args);
        else 
            return 0;
    }

    private function publicGetPlayersAmount()
    {
        //fetch data & return it
    }

    private function publicGetPlayers()
    {
        //fetch data & return it
    }

    private function publicGetAllStats()
    {
        //fetch data & return it
    }

    private function publicGetTopScore()
    {
        //fetch data & return it
    }
}

На мой взгляд, ваш подход не имеет большого смысла.

Если ваш экземпляр Game будет зависеть от наличия currentGame, создание экземпляра не должно быть возможным, если значение currentGame ложно.

Просто поместите проверку в конструктор и выбросьте исключение, если не удается создать экземпляр.

public function __construct()
  {
    $this->currentGame = Game::where('status', true)->first();

    if (! $this->currentGame) {
        throw new \Exception('Current game not available');
        // probably better if you define your own exception class
    }
  }

Затем вы просто проверяете, работает ли это при создании экземпляра и продолжает ли он нормально:

try { 
    $game = new Game();
    $game->getPlayers();
}
catch (\Exception $e) {
    // $game is not safe to use, do something about it.
}

Другие вопросы по теме