Заставить параметр метода класса быть константой из абстрактного класса - PullRequest
0 голосов
/ 27 июня 2018

Черта интеграции

trait Integration {
    public function executeRequest($url, $method, $data, $acceptType) {
        //Do Something
    }
}

Прием покоя Тип Абстрактный класс

abstract class RestAcceptType {
    const xml= "text/xml";
    const html = "text/html";
    const json = "application/json";
    const text = "text/plain";
}

Я пытаюсь найти способ требовать, чтобы параметр метода $acceptType был константой из абстрактного класса Rest Accept Type.

е:

$a = new Integration;
$a->executeRequest("http://example.com/endpoint", "POST", $dataArray, RestAcceptType::json);

работает, но ...

$a = new Integration;
$a->executeRequest("http://example.com/endpoint", "POST", $dataArray, "json");

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

Ответы [ 3 ]

0 голосов
/ 27 июня 2018

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

Обычно этот шаблон достигается путем предоставления вашему классу списка «известных» констант, которые затем можно проверить либо с помощью метода того же класса, либо с помощью простой in_array проверки, если вы сделаете список общедоступным. Таким образом, вы можете добавить в класс RestAcceptType следующее:

public static function isValidAcceptType($type)
{
    return in_array($type, [
        self::xml,
        self::html,
        self::json,
        self::text,
    ]);
}

Затем вы можете использовать это в верхней части вашего executeRequest метода, используя что-то вроде:

if (!RestAcceptType::isValidAcceptType($acceptType)) {
  throw new InvalidArgumentException;
}

Я ценю, что это не самый чистый шаблон (особенно потому, что это означает внесение двух изменений при добавлении новой константы), но если не использовать что-то вроде ReflectionClass::getConstants, невозможно перебрать константы класса. По моему мнению, по крайней мере, это тоже не было бы особенно чисто (хотя именно так работает библиотека в другом ответе, так что это определенно вариант).

0 голосов
/ 27 июня 2018

Вы всегда можете использовать SplEnum , который настолько близок к "стандартному", насколько вы собираетесь получить.

class RestAcceptType extends SplEnum {

    const __default = self::xml;

    const xml= "text/xml";
    const html = "text/html";
    const json = "application/json";
    const text = "text/plain";
}

trait Integration {
  public function executeRequest($url, $method, $data, RestAcceptType $acceptType) {
    //Do Something
  }
}

$acceptType = new RestAcceptType(RestAcceptType::xml);
0 голосов
/ 27 июня 2018

Вы можете использовать библиотеку, например php-enum . Затем вы можете напечатать подсказку типа enum:

final class RestAcceptType extends Enum {
    public const XML = "text/xml";
    public const HTML = "text/html";
    public const JSON = "application/json";
    public const TEXT = "text/plain";
}

trait Integration {
    public function executeRequest($url, $method, $data, RestAcceptType $acceptType) {
        //Do Something
    }
}

$a = new class {
    use Integration;
};

$a->executeRequest("http://example.com/endpoint", "POST", $dataArray, RestAcceptType::JSON());

Обратите внимание, что здесь вы не обращаетесь к константе, а вместо этого вызываете статический метод, который возвращает синглтон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...