Что у меня есть: класс 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
Похоже, вам следует исправить второстепенную проблему, а не устранять ее симптомы хакерским способом. if ($this->currentGame). I have to place it inside each method to avoid Eloquent-related Exceptions. Я не использую Eloquent, но я использовал пару ORM в свое время, возможно, если вы дадите больше информации о том, что это такое ... .
@ Don'tPanic Game - яркая модель. Я ошибся, это может быть класс CurrentGame, но не Game. Редактировать не буду, потому что ответы уже есть.
@ Тарасович, вы видели ответы ниже?
@yivi да, все еще ищу то, что мне подойдет
Почему ответы тебе не подходят? Расскажите подробнее, почему они вам не подходят, и мы постараемся помочь.






Думаю, этого можно добиться с помощью __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.
}
Gameсама по себе красноречивая модель? Вроде так из звонкаGame::where(.... Если это так, то почему вы устанавливаетеcurrentGameна другой экземплярGameи используете его в этих методах, а не просто используете текущий экземпляр?