stdClass 개체를 다른 클래스로 변환/캐스팅합니다.
어떤 이유로 무엇을 입력하든 stdClass 객체만 반환하는 타사 스토리지 시스템을 사용하고 있습니다.따라서 stdClass 객체를 특정 유형의 완전한 개체로 캐스팅/변환할 수 있는 방법이 있는지 알고 싶습니다.
예를 들어 다음과 같은 것이 있습니다.
//$stdClass is an stdClass instance
$converted = (BusinessClass) $stdClass;
stdClass를 어레이에 삽입하여 BusinessClass 컨스트럭터에 공급하고 있습니다만, 제가 모르는 초기 클래스를 복원할 수 있는 방법이 있을지도 모릅니다.
참고: '스토리지 시스템 변경' 유형의 답변은 관심 사항이 아니므로 관심이 없습니다.언어 능력에 관한 학문적인 질문이라고 생각해 주세요.
건배.
가능한 캐스팅은 타입 저글링 매뉴얼을 참조하십시오.
허용되는 배역은 다음과 같습니다.
- (int), (정수) - 정수로 주조
- (부울), (부울) - 부울로 캐스팅
- (2중), (2중), (실제) - 뜨기 위해 주조
- (string) - 스트링에 캐스팅
- (어레이) - 어레이에 캐스트
- (객체) - 객체에 캐스팅
- (설정 해제) - NULL로 캐스트(PHP 5)
stdClass에서 다른 콘크리트 클래스로 주조하는 매퍼를 작성해야 합니다.그렇게 어려운 일은 아닐 거야
또는 해킹을 좋아하는 경우 다음 코드를 적용할 수 있습니다.
function arrayToObject(array $array, $className) {
return unserialize(sprintf(
'O:%d:"%s"%s',
strlen($className),
$className,
strstr(serialize($array), ':')
));
}
특정 클래스의 객체에 배열을 의사 캐스트합니다.이것은, 우선 어레이를 시리얼화한 후, 시리얼화된 데이터를 특정의 클래스를 나타내도록 변경하는 것으로 동작합니다.결과는 이 클래스의 인스턴스로 시리얼화되지 않습니다.하지만 내가 말했듯이, 이건 해킹이야, 그러니 부작용을 기대하세요.
오브젝트 투 오브젝트의 경우 코드는 다음과 같습니다.
function objectToObject($instance, $className) {
return unserialize(sprintf(
'O:%d:"%s"%s',
strlen($className),
$className,
strstr(strstr(serialize($instance), '"'), ':')
));
}
유사하지 않은 오브젝트(PHP > = 5.3)를 캐스팅할 때 위의 기능을 사용할 수 있습니다.
/**
* Class casting
*
* @param string|object $destination
* @param object $sourceObject
* @return object
*/
function cast($destination, $sourceObject)
{
if (is_string($destination)) {
$destination = new $destination();
}
$sourceReflection = new ReflectionObject($sourceObject);
$destinationReflection = new ReflectionObject($destination);
$sourceProperties = $sourceReflection->getProperties();
foreach ($sourceProperties as $sourceProperty) {
$sourceProperty->setAccessible(true);
$name = $sourceProperty->getName();
$value = $sourceProperty->getValue($sourceObject);
if ($destinationReflection->hasProperty($name)) {
$propDest = $destinationReflection->getProperty($name);
$propDest->setAccessible(true);
$propDest->setValue($destination,$value);
} else {
$destination->$name = $value;
}
}
return $destination;
}
예:
class A
{
private $_x;
}
class B
{
public $_x;
}
$a = new A();
$b = new B();
$x = cast('A',$b);
$x = cast('B',$a);
의 stdClass지정된 클래스 이름의 새 객체로 이동합니다.
/**
* recast stdClass object to an object with type
*
* @param string $className
* @param stdClass $object
* @throws InvalidArgumentException
* @return mixed new, typed object
*/
function recast($className, stdClass &$object)
{
if (!class_exists($className))
throw new InvalidArgumentException(sprintf('Inexistant class %s.', $className));
$new = new $className();
foreach($object as $property => &$value)
{
$new->$property = &$value;
unset($object->$property);
}
unset($value);
$object = (unset) $object;
return $new;
}
사용방법:
$array = array('h','n');
$obj=new stdClass;
$obj->action='auth';
$obj->params= &$array;
$obj->authKey=md5('i');
class RestQuery{
public $action;
public $params=array();
public $authKey='';
}
$restQuery = recast('RestQuery', $obj);
var_dump($restQuery, $obj);
출력:
object(RestQuery)#2 (3) {
["action"]=>
string(4) "auth"
["params"]=>
&array(2) {
[0]=>
string(1) "h"
[1]=>
string(1) "n"
}
["authKey"]=>
string(32) "865c0c0b4ab0e063e5caa3387c1a8741"
}
NULL
입니다. , this, 음, 음, 음 this this this this this this this this this this this this this this.new어떤 파라미터가 필요한지 알 수 없기 때문에 연산자.당신의 경우에 적합할 겁니다.
저도 비슷한 문제가 있어요.단순화된 반사 솔루션은 나에게 매우 효과적이었습니다.
public static function cast($destination, \stdClass $source)
{
$sourceReflection = new \ReflectionObject($source);
$sourceProperties = $sourceReflection->getProperties();
foreach ($sourceProperties as $sourceProperty) {
$name = $sourceProperty->getName();
$destination->{$name} = $source->$name;
}
return $destination;
}
누군가 이것을 유용하게 찾길 바란다.
// new instance of stdClass Object
$item = (object) array(
'id' => 1,
'value' => 'test object',
);
// cast the stdClass Object to another type by passing
// the value through constructor
$casted = new ModelFoo($item);
// OR..
// cast the stdObject using the method
$casted = new ModelFoo;
$casted->cast($item);
class Castable
{
public function __construct($object = null)
{
$this->cast($object);
}
public function cast($object)
{
if (is_array($object) || is_object($object)) {
foreach ($object as $key => $value) {
$this->$key = $value;
}
}
}
}
class ModelFoo extends Castable
{
public $id;
public $value;
}
딥 캐스팅 기능이 변경되었습니다(재귀 사용).
/**
* Translates type
* @param $destination Object destination
* @param stdClass $source Source
*/
private static function Cast(&$destination, stdClass $source)
{
$sourceReflection = new \ReflectionObject($source);
$sourceProperties = $sourceReflection->getProperties();
foreach ($sourceProperties as $sourceProperty) {
$name = $sourceProperty->getName();
if (gettype($destination->{$name}) == "object") {
self::Cast($destination->{$name}, $source->$name);
} else {
$destination->{$name} = $source->$name;
}
}
}
비즈니스 클래스에 새로운 메서드를 추가하는 것을 검토합니다.
public static function fromStdClass(\stdClass $in): BusinessClass
{
$out = new self();
$reflection_object = new \ReflectionObject($in);
$reflection_properties = $reflection_object->getProperties();
foreach ($reflection_properties as $reflection_property)
{
$name = $reflection_property->getName();
if (property_exists('BusinessClass', $name))
{
$out->{$name} = $in->$name;
}
}
return $out;
}
$stdClass에서 새로운 비즈니스 클래스를 만들 수 있습니다.
$converted = BusinessClass::fromStdClass($stdClass);
그리고 데코레이터 패턴과 PHP 매직게터&세터를 사용한 또 다른 접근법:
// A simple StdClass object
$stdclass = new StdClass();
$stdclass->foo = 'bar';
// Decorator base class to inherit from
class Decorator {
protected $object = NULL;
public function __construct($object)
{
$this->object = $object;
}
public function __get($property_name)
{
return $this->object->$property_name;
}
public function __set($property_name, $value)
{
$this->object->$property_name = $value;
}
}
class MyClass extends Decorator {}
$myclass = new MyClass($stdclass)
// Use the decorated object in any type-hinted function/method
function test(MyClass $object) {
echo $object->foo . '<br>';
$object->foo = 'baz';
echo $object->foo;
}
test($myclass);
또 다른 접근법입니다.
최근 PHP 7 버전 덕분에 다음과 같은 작업이 가능합니다.
$theStdClass = (object) [
'a' => 'Alpha',
'b' => 'Bravo',
'c' => 'Charlie',
'd' => 'Delta',
];
$foo = new class($theStdClass) {
public function __construct($data) {
if (!is_array($data)) {
$data = (array) $data;
}
foreach ($data as $prop => $value) {
$this->{$prop} = $value;
}
}
public function word4Letter($letter) {
return $this->{$letter};
}
};
print $foo->word4Letter('a') . PHP_EOL; // Alpha
print $foo->word4Letter('b') . PHP_EOL; // Bravo
print $foo->word4Letter('c') . PHP_EOL; // Charlie
print $foo->word4Letter('d') . PHP_EOL; // Delta
print $foo->word4Letter('e') . PHP_EOL; // PHP Notice: Undefined property
이 예에서는 $foo가 1개의 어레이 또는 stdClass를 컨스트럭터의 파라미터로만 사용하는 어나니머스 클래스로 초기화됩니다.
마지막으로 전달된 객체에 포함된 각 항목을 루프하여 객체의 속성에 동적으로 할당합니다.
이 접근 이벤트를 보다 범용적으로 만들기 위해 stdClass를 캐스팅할 수 있는 모든 클래스에서 구현할 인터페이스 또는 특성을 작성할 수 있습니다.
BTW: 시리얼라이즈된 경우 변환은 매우 중요합니다.주로 시리얼라이즈 해제에 의해 오브젝트의 타입이 해제되어 Date Time 오브젝트를 포함한 stdclass가 되기 때문입니다.
@Jadrovski의 예를 업데이트했습니다.이 예에서는 오브젝트와 어레이를 사용할 수 있게 되었습니다.
예
$stdobj=new StdClass();
$stdobj->field=20;
$obj=new SomeClass();
fixCast($obj,$stdobj);
예시 배열
$stdobjArr=array(new StdClass(),new StdClass());
$obj=array();
$obj[0]=new SomeClass(); // at least the first object should indicates the right class.
fixCast($obj,$stdobj);
code: (재귀적).그러나 배열에 따라 재귀적인지는 알 수 없습니다.추가 is_array가 없을 수 있습니다.
public static function fixCast(&$destination,$source)
{
if (is_array($source)) {
$getClass=get_class($destination[0]);
$array=array();
foreach($source as $sourceItem) {
$obj = new $getClass();
fixCast($obj,$sourceItem);
$array[]=$obj;
}
$destination=$array;
} else {
$sourceReflection = new \ReflectionObject($source);
$sourceProperties = $sourceReflection->getProperties();
foreach ($sourceProperties as $sourceProperty) {
$name = $sourceProperty->getName();
if (is_object(@$destination->{$name})) {
fixCast($destination->{$name}, $source->$name);
} else {
$destination->{$name} = $source->$name;
}
}
}
}
이를 배열로 변환하고 해당 배열의 첫 번째 요소를 반환하고 반환 매개 변수를 해당 클래스로 설정합니다.이제 해당 클래스가 stdclass가 아닌 해당 클래스로 재컨피규레이션되므로 해당 클래스에 대한 자동 완료를 얻어야 합니다.
/**
* @return Order
*/
public function test(){
$db = new Database();
$order = array();
$result = $db->getConnection()->query("select * from `order` where productId in (select id from product where name = 'RTX 2070')");
$data = $result->fetch_object("Order"); //returns stdClass
array_push($order, $data);
$db->close();
return $order[0];
}
언급URL : https://stackoverflow.com/questions/3243900/convert-cast-an-stdclass-object-to-another-class
'programing' 카테고리의 다른 글
| 애플리케이션 스레드를 안전하게 만드는 방법 (0) | 2022.10.22 |
|---|---|
| PHP를 통해 이메일로 HTML 전송 (0) | 2022.10.22 |
| 많은 인수를 메서드에 전달하기 위한 베스트 프랙티스? (0) | 2022.10.22 |
| MySQL Workbench - 테이블 데이터 가져오기 마법사(모든 날짜/시간 개체를 0000-00 00:00:00:00로 기록) (0) | 2022.10.22 |
| PHP: 원래 문자 집합을 모르는 상태에서 문자열을 UTF-8로 변환하거나 최소한 시도해 보십시오. (0) | 2022.10.22 |