@phpcoder81

Как зафиксировать аргументы в методе?

Парни, прошу прощения, если не так назвал тему, переименуйте, если что)
У меня есть метод
public function changeStatus($id_product, $id_status, $id_user){
}

внутри приходится всегда проверку делать, то ли передали что надо: 3 проверки на !empty и три на is_numeric. Иначе return false; А дальше сам код метода.

Можно ли как-то сразу прописать в сами скобки жестко зафиксированные имена и типы. Чтоб не пустые и ни "другие типы" не проходили, а давали fatal error? Кстати, то же самое и массивов касается.
  • Вопрос задан
  • 100 просмотров
Пригласить эксперта
Ответы на вопрос 1
SilenceOfWinter
@SilenceOfWinter Куратор тега PHP
та еще зажигалка...
Eсли нет 7ки, то только так:
<?php
// Обработчик типов аргументов функций
final class TypeHint
{
	static private $TypeHints = array(
		'boolean'   => 'is_bool',
		'bool'      => 'is_bool',
		'string'    => 'is_string',
		'resource'  => 'is_resource',
		// Подменил ряд стандартных функий, чтобы числа переданные строкой не вызывали ошибок
		'integer'   => 'self::is_int',
		'int'       => 'self::is_int',
		'float'     => 'self::is_float',
		'double'    => 'self::is_float',
		// Для примера добавил несколько собственных типов:
		'strict'    => 'self::is_strict',    // Имена классов\функций\аргуметов
		'url_param' => 'self::is_url_param', // Параметры ЧПУ ссылки
		'filename'  => 'self::is_filename',  // Има файлов
	);
	
	// Проверка на соотвествие типу integer \ int
	static private function is_int($value)
	{
		if ((is_numeric($value) AND is_string($value) AND preg_match('/^[-]{0,1}[0-9]+$/u', $value )) OR is_int($value))
		{
			return TRUE;
		}
		return FALSE;
	}
	
	// Проверка на соотвествие типу float \ double
	static private function is_float($value)
	{
		if ((is_numeric($value) AND is_string($value) AND preg_match('/^[-]{0,1}[0-9]+\.[0-9]+$/u', $value)) OR is_float($value))
		{
			return TRUE;
		}
		return FALSE;
	}
	
	// Проверка на соотвествие типу strict
	static private function is_strict($value)
	{
		if (is_string($value) AND preg_match('/^[a-z_\x7f-\xff]{2,}[a-z0-9_\x7f-\xff]*$/iu', $value))
		{
			return TRUE;
		}
		return FALSE;
	}
	
	// Проверка на соотвествие типу url_param
	static private function is_url_param($value)
	{
		if ((is_string($value) OR is_int($value)) AND preg_match('/^[a-z0-9_\x7f-\xff]+$/iu', $value))
		{
			return TRUE;
		}
		return FALSE;
	}
	
	// Проверка на соотвествие типу filename
	static private function is_filename( $value )
	{
		if (is_string($value) AND preg_match('/^[a-z0-9_\x7f-\xff]+\.[a-z0-9_\x7f-\xff]+$/iu', $value))
		{
			return TRUE;
		}
		return FALSE;
	}
	
	// Создание объекта возможно только через метод initializeHandler
	private function __construct(){}
	private function __clone(){}
	private function __wakeup(){}
	
	// Инициализация обработчика
	static public function initializeHandler()
	{
		set_error_handler('TypeHint::handleTypeHint');
		return TRUE;
	}
	
	// Получение аргументов функции
	static private function getTypeHintedArgument($ThBackTrace, $ThFunction, $ThArgIndex, & $ThArgValue)
	{
		foreach ($ThBackTrace as $ThTrace)
		{
			if (isset($ThTrace['function']) AND $ThTrace['function'] == $ThFunction)
			{
				$ThArgValue = $ThTrace['args'][$ThArgIndex-1];
				return TRUE;
			}
		}
		return FALSE;
	}
	
	// Обработчик
	static public function handleTypeHint($ErrLevel, $ErrMessage, $ErrFile, $ErrLine)
	{
		if ($ErrLevel === E_RECOVERABLE_ERROR)
		{
			if (preg_match('/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/u', $ErrMessage, $ErrMatches))
			{
				list($ErrMatch, $ThArgIndex, $ThClass, $ThFunction, $ThHint, $ThType) = $ErrMatches;
				if (isset(self::$TypeHints[$ThHint]))
				{
					$ThBacktrace = debug_backtrace();
					$ThArgValue  = NULL;
					if (self::getTypeHintedArgument($ThBacktrace, $ThFunction, $ThArgIndex, $ThArgValue))
					{
						if (call_user_func(self::$TypeHints[$ThHint], $ThArgValue))
						{
							return TRUE;
						}
						throw new ErrorException($ErrMessage, 0, $ErrLevel, $ErrFile, $ErrLine);
					}
				}
			}
		}
		return FALSE;
	}
}

// Инициализируем обработчик
TypeHint::initializeHandler();

// Тест
function test(strict $arg1, filename $arg2, $arg3 = 1)
{
	echo "It's work! {$arg1} | {$arg2} | {$arg3}";
}

try
{
	test('func_2', array(1,2))
}
catch (ErrorException $e)
{
	var_export($e->getMessage());
}

try
{
	test(10.1, 'str')
}
catch (ErrorException $e)
{
	var_export($e->getMessage());
}

try
{
	test('class_name', '02.jpg')
}
catch (ErrorException $e)
{
	var_export($e->getMessage());
}
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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