68 votes

Comment lancer des objets en PHP

Ive certains clases qui partagent certains attributs, et je voudrais faire quelque chose comme: $chien = (Chien) $cat;

est-il possible ou est-il un générique contourner?

Ce n'est pas une super-classe ou une interface, ou liés d'une quelconque façon. Ils sont juste 2 clases je voudrais php mapper les attributs d'une classe chat pour un chien et de me donner le nouvel objet. –

je suppose que j'ai de préciser un peu plus la cause sembler absurde chose à faire.

ive clases qui hérite de diferents parent clases cause ive a fait une arborescence d'héritage basé sur la méthode de sauvegarde, peut-être mon mauvais depuis le début, mais le problème est que j'ai beaucoup de clases qui sont pratiquement à égalité, mais interagit avec un mysql et le otherone avec des fichiers xml. j'ai donc: classe MySql_SomeEntity s'étend SomeMysqlInteract{} et Xml_SomeEntity s'étend SomeXmlInteract{} c'est un petit peu plus profond arbre, mais le problème ses que. je ne peux pas faire hérite de la même classe de cause multimple l'héritage n'est pas admis, et je ne peux pas séparer les courants de l'interaction avec superclases provoquer des serait une grosse throuble.

Fondamentalement, les attributs de chacun pratiques sont les mêmes.

depuis j'ai beaucoup de cette maching clases, je voudrais faire quelques génériques de casting ou quelque chose comme ça qui peut convertit (transmettre les valeurs de chaque attribut) et de mais im essayant de trouver le moyen le plus simple pour tout le monde de ce clases.

36voto

Adam Puza Points 451

Vous pouvez utiliser la fonction ci-dessus pour la conversion d'objets de classe non similaires (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;
}
 

EXEMPLE:

 class A 
{
  private $_x;   
}

class B 
{
  public $_x;   
}

$a = new A();
$b = new B();

$x = cast('A',$b);
$x = cast('B',$a);
 

29voto

user250120 Points 672

Il n'existe pas de méthode intégrée pour le type coulée de l'utilisateur défini des objets dans PHP. Cela dit, voici plusieurs solutions possibles:

1) Utiliser une fonction comme celle ci-dessous pour désérialiser l'objet, changer de chaîne, de sorte que les propriétés dont vous avez besoin sont inclus dans le nouvel objet une fois qu'il est désérialisé.

function cast($obj, $to_class) {
  if(class_exists($to_class)) {
    $obj_in = serialize($obj);
    $obj_out = 'O:' . strlen($to_class) . ':"' . $to_class . '":' . substr($obj_in, $obj_in[2] + 7);
    return unserialize($obj_out);
  }
  else
    return false;
}

2) vous pouvez aussi copier les propriétés de l'objet à l'aide de réflexion / manuellement une itération à travers eux tous les ou à l'aide de get_object_vars().

Cet article devrait vous éclairer sur les "coins sombres de PHP et la mise en œuvre de typecasting sur le niveau de l'utilisateur.

5voto

rockacola Points 3973

Sans l'aide de l'héritage (comme mentionné par l'auteur), il semble que vous êtes à la recherche d'une solution qui peut - transform une classe à l'autre avec preassumption de le développeur sait et comprendre la similitude des 2 classes.

Il n'y a pas de solution existante pour la transformer entre les objets. Ce que vous pouvez essayer sont:

3voto

useless Points 1083

une meilleure aproach:

 class Animal
{
    private $_name = null;

    public function __construct($name = null)
    {
        $this->_name = $name;
    }

    /**
     * casts object
     * @param Animal $to
     * @return Animal
     */
    public function cast($to)
    {
        if ($to instanceof Animal) {
            $to->_name = $this->_name;
        } else {
            throw(new Exception('cant cast ' . get_class($this) . ' to ' . get_class($to)));
        return $to;
    }

    public function getName()
    {
        return $this->_name;
    }
}

class Cat extends Animal
{
    private $_preferedKindOfFish = null;

    public function __construct($name = null, $preferedKindOfFish = null)
    {
        parent::__construct($name);
        $this->_preferedKindOfFish = $preferedKindOfFish;
    }

    /**
     * casts object
     * @param Animal $to
     * @return Animal
     */
    public function cast($to)
    {
        parent::cast($to);
        if ($to instanceof Cat) {
            $to->_preferedKindOfFish = $this->_preferedKindOfFish;
        }
        return $to;
    }

    public function getPreferedKindOfFish()
    {
        return $this->_preferedKindOfFish;
    }
}

class Dog extends Animal
{
    private $_preferedKindOfCat = null;

    public function __construct($name = null, $preferedKindOfCat = null)
    {
        parent::__construct($name);
        $this->_preferedKindOfCat = $preferedKindOfCat;
    }

    /**
     * casts object
     * @param Animal $to
     * @return Animal
     */
    public function cast($to)
    {
        parent::cast($to);
        if ($to instanceof Dog) {
            $to->_preferedKindOfCat = $this->_preferedKindOfCat;
        }
        return $to;
    }

    public function getPreferedKindOfCat()
    {
        return $this->_preferedKindOfCat;
    }
}

$dogs = array(
    new Dog('snoopy', 'vegetarian'),
    new Dog('coyote', 'any'),
);

foreach ($dogs as $dog) {
    $cat = $dog->cast(new Cat());
    echo get_class($cat) . ' - ' . $cat->getName() . "\n";
}
 

3voto

darpet Points 1198

Vous n'avez pas besoin de casting. Tout est dynamique.

J'ai un rabais de classe.
J'ai plusieurs classes qui étend cette classe:
ProductDiscount
StoreDiscount
ShippingDiscount
...

Quelque part dans le code j'ai:

 $pd = new ProductDiscount();
$pd->setDiscount(5, ProductDiscount::PRODUCT_DISCOUNT_PERCENT);
$pd->setProductId(1);

$this->discounts[] = $pd;

.....

$sd = new StoreDiscount();
$sd->setDiscount(5, StoreDiscount::STORE_DISCOUNT_PERCENT);
$sd->setStoreId(1);

$this->discounts[] = $sd;
 

Et quelque part j'ai:

 foreach ($this->discounts as $discount){

    if ($discount->getDiscountType()==Discount::DISCOUNT_TYPE_PRODUCT){

        $productDiscount = $discount; // you do not need casting.
        $amount = $productDiscount->getDiscountAmount($this->getItemTotalPrice());
        ...
    }

}// foreach
 

Où getDiscountAmount est une fonction spécifique à ProductDiscount et getDiscountType est une fonction spécifique à Discount.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X