StdClass অবজেক্টটিকে অন্য শ্রেণিতে রূপান্তর / কাস্ট করুন


90

আমি একটি তৃতীয় পক্ষের স্টোরেজ সিস্টেমটি ব্যবহার করছি যা আমাকে কেবল অস্পষ্ট কারণে খাওয়াই যায় না কেন কেবল আমাকে stdClass অবজেক্ট দেয়। সুতরাং আমি জানতে আগ্রহী যে এখানে কোনও স্টাডক্লাস বস্তুকে একটি নির্দিষ্ট ধরণের একটি পূর্ণাঙ্গ অবজেক্টে কাস্ট / রূপান্তর করার কোনও উপায় আছে কিনা।

উদাহরণস্বরূপ এর লাইন বরাবর কিছু:

//$stdClass is an stdClass instance
$converted = (BusinessClass) $stdClass;

আমি কেবল স্ট্রেডক্লাসকে একটি অ্যারেতে কাস্ট করছি এবং এটি বিজনেসক্লাস কনস্ট্রাক্টরকে খাওয়াই, তবে সম্ভবত প্রাথমিক ক্লাসটি পুনরুদ্ধার করার উপায় আছে যা সম্পর্কে আমি অবগত নই।

দ্রষ্টব্য: আমি 'আপনার স্টোরেজ সিস্টেমটি পরিবর্তন করুন' প্রকারের উত্তরগুলিতে আগ্রহী না কারণ এটি আগ্রহের বিষয় নয়। ভাষার সক্ষমতা সম্পর্কে এটি আরও একাডেমিক প্রশ্ন বিবেচনা করুন।

চিয়ার্স


এটি ছদ্ম কোডের নমুনার পরে আমার পোস্টে ব্যাখ্যা করা হয়েছে। আমি একটি অ্যারেতে কাস্ট করছি এবং একটি স্বয়ংক্রিয় কনস্ট্রাক্টরকে খাওয়াচ্ছি।
মাইটি রাবার হাঁস

@ অ্যাডাম পুজার উত্তর গৃহীত উত্তরে প্রদর্শিত হ্যাকের চেয়ে অনেক ভাল। যদিও আমি নিশ্চিত যে ম্যাপারটি এখনও পছন্দসই পদ্ধতি হবে
ক্রিস

আচ্ছা PDOStatement::fetchObjectএই কাজটি কীভাবে সম্পাদন করে ?
উইলিয়াম এন্টারিকেন

উত্তর:


90

সম্ভাব্য কাস্টগুলিতে টাইপ জাগলিংয়ের ম্যানুয়ালটি দেখুন ।

অনুমোদিত কাস্টগুলি হ'ল:

  • (int), (পূর্ণসংখ্যা) - পূর্ণসংখ্যাতে castালাই
  • (বুলিয়ান), (বুলিয়ান) - বুলিয়ান কাস্ট করুন
  • (ভাসা), (ডাবল), (বাস্তব) - ভাসতে কাস্ট করুন
  • (স্ট্রিং) - স্ট্রিং এ castালাই
  • (অ্যারে) - অ্যারেতে .ালাই
  • (অবজেক্ট) - আপত্তি করা to
  • (আনসেট না করা) - নূলে কাস্ট করুন (পিএইচপি 5)

আপনাকে একটি ম্যাপার লিখতে হবে যা স্টাডক্লাস থেকে অন্য কংক্রিটের ক্লাসে কাস্টিং করে। খুব বেশি কঠিন কাজ করা উচিত নয়।

অথবা, আপনি যদি হ্যাকিশ মুডে থাকেন তবে আপনি নিম্নলিখিত কোডটি মানিয়ে নিতে পারেন:

function arrayToObject(array $array, $className) {
    return unserialize(sprintf(
        'O:%d:"%s"%s',
        strlen($className),
        $className,
        strstr(serialize($array), ':')
    ));
}

যা একটি নির্দিষ্ট শ্রেণীর একটি বস্তুর জন্য একটি অ্যারের সিউডোকাস্ট করে। এটি প্রথমে অ্যারে সিরিয়ালাইজ করে এবং পরে সিরিয়ালযুক্ত ডেটা পরিবর্তন করে যাতে এটি একটি নির্দিষ্ট শ্রেণির প্রতিনিধিত্ব করে works ফলাফলটি তখন এই শ্রেণীর একটি উদাহরণে আনসিরিয়ালিজেড হয়। তবে আমি যেমন বলেছিলাম, এটি হ্যাকিশ, তাই পার্শ্ব-প্রতিক্রিয়া আশা করি।

অবজেক্ট অবজেক্টের জন্য কোডটি হবে

function objectToObject($instance, $className) {
    return unserialize(sprintf(
        'O:%d:"%s"%s',
        strlen($className),
        $className,
        strstr(strstr(serialize($instance), '"'), ':')
    ));
}

9
এই হ্যাক একটি চালাক কৌশল। সমস্যাটি সমাধান করার জন্য আমার বর্তমান পদ্ধতিটি আরও স্থিতিশীল, তবে তা তবে আকর্ষণীয় since
মাইটি রাবার হাঁস

4
আপনি __PHP_Incomplete_Classএই পদ্ধতিটি ব্যবহার করে কোনও অবজেক্টের সাথে শেষ করতে পারেন (কমপক্ষে পিএইচপি 5.6 হিসাবে)।
টিএমইএসপিলেটার

4
@ টিএমএসপিলেটার নং, আপনি করবেন না। Codepad.org/spGkyLzL দেখুন । ফাংশনটি বলার আগে নিশ্চিত হয়ে নিন যে কাস্ট করতে হবে সেই ক্লাসটি অন্তর্ভুক্ত ছিল।
গর্ডন

@ টিএমইএসপিএল্টার আপনার অর্থ কী তা নিশ্চিত হন না। এটা কাজ করেছে. এটি একটি উদাহরণ \ এখন Foo।
গর্ডন

হ্যাঁ সমস্যাটি এটি stdClass সম্পত্তি যুক্ত করে। সুতরাং আপনার কাছে দুটি fooBarএস ( example\Fooস্টাডক্লাস থেকে ব্যক্তিগত এবং এক জন) the পরিবর্তে এটি মানকে প্রতিস্থাপন করে।
টিএমইএসপি্লায়নার

53

অনুরূপ শ্রেণীর অবজেক্ট নয় (ing পিএইচপি> = 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);

4
এটি একটি সুন্দর মার্জিত সমাধান, আমি অবশ্যই বলতে হবে! আমি কেবল আশ্চর্য করি যে এটি কতটা ভাল পরিমাণে স্কেল করে ... প্রতিচ্ছবি আমাকে ভীতি প্রদর্শন করে।
থিওডোর আর স্মিথ

ওহে আদম, এই সমাধানটি এখানে আমার জন্য একই সমস্যাটি সমাধান করেছে: stackoverflow.com/questions/35350585/… আপনি যদি কোনও সহজ উত্তর দিতে চান, তবে এগিয়ে যান এবং আমি এটি বন্ধ করে দেব। ধন্যবাদ!
ওসিল

এটি পিতামাতার ক্লাস থেকে প্রাপ্ত সম্পত্তিগুলির জন্য কাজ করে না।
তোয়ালাল

বেহাতের সাথে এপিআই কার্যকরী পরীক্ষার জন্য পরিচিত আইডি সহ আমার ডেটাবেস বীজ করার জন্য আমি আমার সমাধানের ভিত্তি হিসাবে এটি ব্যবহার করেছি। আমার সমস্যাটি হ'ল যে আমার সাধারণ আইডিগুলি ইউআইডি তৈরি হয় এবং আমি কেবল আমার পরীক্ষার স্তরটির স্বার্থে আমার সত্তায় একটি সেটআইডি () পদ্ধতি যুক্ত করতে চাইনি এবং আমি ফিক্সচার ফাইলগুলি লোড করতে এবং পরীক্ষাগুলি ধীর করতে চাইনি। এখন আমি @Given the user :username has the id :idআমার বৈশিষ্ট্যে অন্তর্ভুক্ত করতে পারি এবং প্রসঙ্গ শ্রেণিতে প্রতিচ্ছবি সহ এটি পরিচালনা করতে পারি
nealio82

4
দুর্দান্ত সমাধান, আমি এটি যুক্ত করতে চাই যা $destination = new $destination();আপনার $destination = ( new ReflectionClass( $destination ) )->newInstanceWithoutConstructor();যদি কনস্ট্রাক্টরকে কল এড়াতে না চান তবে এটির সাথে অদলবদল করা যায় ।
স্কুজি

15

একটি বিদ্যমান সমস্ত বৈশিষ্ট্য 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

এটি newঅপারেটরের কারণে সীমাবদ্ধ কারণ এটি কোন পরামিতিগুলির প্রয়োজন তা অজানা। আপনার ক্ষেত্রে সম্ভবত উপযুক্ত।


4
এই পদ্ধতিটি ব্যবহার করার চেষ্টা করছেন অন্যদের অবহিত করা। এই ফাংশনটিতে একটি সতর্কতা রয়েছে যে নিজের বাইরে কোনও তাত্ক্ষণিক বস্তুর উপরে পুনরাবৃত্তি কাস্ট করা বস্তুর মধ্যে ব্যক্তিগত বা সুরক্ষিত বৈশিষ্ট্য সেট করতে সক্ষম হবে না। EG: জনসাধারণকে সেট করা হচ্ছে $ authKey = ''; to বেসরকারী $ authKey = ''; E_ERROR- এ ফলাফল: 1 টাইপ করুন - ব্যক্তিগত সম্পত্তি রিকুইকিয়ারি অ্যাক্সেস করতে পারবেন না :: uth authKey
উইল বি

যদিও ব্যক্তিগত সম্পত্তি সহ একটি স্টাডি ক্লাস?
ফ্রিগ

ওপি বিশেষভাবে এই প্রয়োজনীয়তা @Frug নির্দেশ ... ঢালাই / একটি প্রদত্ত ধরনের একটি পূর্ণাঙ্গ বস্তুর মধ্যে একটি stdClass বস্তুর রূপান্তর
oucil

11

আমি খুব একই সমস্যা আছে। সরলীকৃত প্রতিবিম্ব সমাধান আমার পক্ষে ঠিক কাজ করেছে:

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;
}

8

আশা করি যে কেউ এই দরকারী দরকারী

// 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;
}

আপনি কী ব্যাখ্যা করতে পারবেন "কেন_আররে ($ অবজেক্ট) || is_array ($ অবজেক্ট)"?
কুকিনসুল

5

গভীর ingালাইয়ের জন্য পরিবর্তিত ফাংশন (পুনরাবৃত্তি ব্যবহার করে)

/**
 * 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;
        }
    }
}

2

এবং ডেকোরেটারের প্যাটার্ন এবং পিএইচপিএস ম্যাজিক গেটর এবং সেটার ব্যবহার করে এখনও অন্য একটি পদ্ধতি:

// 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);

1

বিজনেসক্লাসে একটি নতুন পদ্ধতি যুক্ত করার বিষয়টি বিবেচনা করুন:

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;
}

তারপরে আপনি স্টাডক্লাস থেকে একটি নতুন বিজনেসক্লাস তৈরি করতে পারেন:

$converted = BusinessClass::fromStdClass($stdClass);

1

তবুও আরেকটি পন্থা।

নীচের এখন সাম্প্রতিক পিএইচপি 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 একটি বেনাম শ্রেণি হিসাবে আরম্ভ করা হচ্ছে যা কনস্ট্রাক্টরের জন্য কেবলমাত্র প্যারামিটার হিসাবে একটি অ্যারে বা stdClass নেয়।

অবশেষে, আমরা পাস করা বস্তুর মধ্যে থাকা প্রতিটি আইটেমটি লুপ করব এবং গতিশীলভাবে কোনও বস্তুর সম্পত্তিতে অর্পণ করব।

এই পদ্ধতির ইভেন্টটিকে আরও জেনেরিক করে তুলতে আপনি একটি ইন্টারফেস বা একটি বৈশিষ্ট্য লিখতে পারেন যা আপনি যে কোনও শ্রেণিতে প্রয়োগ করতে পারবেন যেখানে আপনি একটি স্টাডক্লাস কাস্ট করতে সক্ষম হবেন।


0

বিটিডাব্লু: আপনি সিরিয়ালযুক্ত হলে রূপান্তরকরণ অত্যন্ত গুরুত্বপূর্ণ, মূলত ডি-সিরিয়ালাইজেশনের কারণে ডেটটাইম অবজেক্টস সহ অবজেক্টের ধরণটি স্টাডক্লাসে পরিণত হয়।

আমি @ জাদ্রোভস্কির উদাহরণ আপডেট করেছি, এখন এটি বস্তু এবং অ্যারেগুলিকে অনুমতি দেয়।

উদাহরণ

$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);

কোড: (এটি পুনরাবৃত্তি) তবে অ্যারে দিয়ে এটির পুনরাবৃত্তি হবে কিনা তা আমি জানি না। এটির অতিরিক্ত গতি হতে পারে_আররে

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;
            }
        }
    }
}

0

এটিকে একটি অ্যারেতে রূপান্তর করুন, সেই অ্যারের প্রথম উপাদানটি ফিরিয়ে দিন এবং সেই ক্লাসে রিটার্ন পরম সেট করুন। এখন আপনার সেই শ্রেণীর জন্য স্বয়ত্তর সম্পূর্ণ হওয়া উচিত কারণ এটি এটি স্টাডক্লাসের পরিবর্তে that শ্রেণির হিসাবে পুনরায় কনফিগার করবে।

/**
 * @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];
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.