Regenbogenjonny: php: Object kopieren / klonen

Hallo Forum,

ich habe ein Problem. Ich erstelle aus meinem Bild zuerst ein Thumb und dann resize ich das Original. Leider überschreibt aber ImageMagick das Bild, sodass mein resiztes Original an Bildqualität verliert.

Meine Idee: Original kopieren, dann Thumb erstellen, dann Kopie vernichten. Dann Original wieder kopieren, dann resizen, dann Kopie wieder vernichten. Dann Original kopieren und sonstiges machen, falls nötig und dann Kopie vernichten. Ich will also vor jedem Schritt mein Objekt kopieren und mit der Kopie arbeiten während das Original als Objekt erhalten bleibt.

Mein Problem ist, dass ich anscheinend nur die Referenz kopiere und beim Ändern von Instanzvariablen am Original herum schraube.

Beispiel:

    protected function copyMyObject() {        
    $copyObject = $this;
    return $copyObject;
    }


    public function make_thumb($x, $y) {
        $copyObject = $this->copyMyObject();
        echo("21:05:50: ----> ".$this->origWidth."<br>");
        $copyObject->origWidth = "222";
        echo("21:06:41: ----> ".$copyObject->origWidth."<br>");
        echo("21:05:50: ----> ".$this->origWidth."<br>");
        exit;

Ausgabe:

21:05:50: ----> 5120 21:06:41: ----> 222 21:05:50: ----> 222

2 Fragen:

1.) Ist meine Vorgehensweise überhaupt die richtige? 2.) Selbst wenn nicht, wie kopiere/clone ich ein Object so, dass es wirklich doppelt vorhanden und über seine Variablen und Methoden ansprechbar ist?

Jonny

  1. Tach!

    Mein Problem ist, dass ich anscheinend nur die Referenz kopiere und beim Ändern von Instanzvariablen am Original herum schraube.

    Richtig. Objekte werden in PHP immer per Referenz übergeben. Aber du hast in der Überschrift schon das passende Stichwort erwähnt: clone.

    1.) Ist meine Vorgehensweise überhaupt die richtige?

    Ich würde ja versuchen, das Bild zu kopieren und nicht das Fremd-Objekt, von dem ich nicht weiß, was da alles noch beachtet werden muss.

    2.) Selbst wenn nicht, wie kopiere/clone ich ein Object so, dass es wirklich doppelt vorhanden und über seine Variablen und Methoden ansprechbar ist?

    Schau ins PHP-Handbuch, da gibt es ein Kapitel zu OOP, auch zum Klonen und was man dabei beachten muss steht dort.

    dedlfix.

    1. Hi,

      Ich würde ja versuchen, das Bild zu kopieren und nicht das Fremd-Objekt, von dem ich nicht weiß, was da alles noch beachtet werden muss.

      ... würde ich ja auch normalerweise. Aber doch nicht bei meinem ersten OOP-Test-Script ;-)

      Schau ins PHP-Handbuch, da gibt es ein Kapitel zu OOP, auch zum Klonen und was man dabei beachten muss steht dort.

      Habe ich eben schon gemacht, aber (noch) nicht richtig verstanden.

      Aber:

      Wenn ich in meiner Kopier-Methode folgendes notiere, klappt es:

          protected function copyMyObject() {        
          $copyObject = new bilder($this->myfile, $this->pdfExcelWordThumbnailDefaultPath, $this->watermarkfile);
          return $copyObject;
          }
      
      
      ~~~php
          public function make_thumb($x, $y) {
              $copyObject = $this->copyMyObject();
              echo("21:05:50: ----> ".$this->origWidth."<br>");
              $copyObject->origWidth = "222";
              echo("21:06:41: ----> ".$copyObject->origWidth."<br>");
              echo("21:05:50: ----> ".$this->origWidth."<br>");
              exit;
      

      Ausgabe:

      21:05:50: ----> 5120 21:06:41: ----> 222 21:05:50: ----> 5120

      
      Ist gegen dieses Art des Clonens etwas auszusetzen?
      
      Jonny
      
      
      1. Tach!

        Wenn ich in meiner Kopier-Methode folgendes notiere, klappt es:

            protected function copyMyObject() {        
            $copyObject = new bilder($this->myfile, $this->pdfExcelWordThumbnailDefaultPath, $this->watermarkfile);
            return $copyObject;
            }
        

        Damit erstellst du ein neues Objekt und übergibst drei Werte. Wenn das keine Objekte sind, werden sie kopiert, ansonsten sind das dann Referenzen auf die im anderen Objekt referenzierten Objekte.

        Ist gegen dieses Art des Clonens etwas auszusetzen?

        Ja, es ist umständlich, weil clone solch eine so genannte shallow copy auch erzeugen kann.

        dedlfix.

        1. Hi dedlfix,

          Damit erstellst du ein neues Objekt und übergibst drei Werte. Wenn das keine Objekte sind, werden sie kopiert, ansonsten sind das dann Referenzen auf die im anderen Objekt referenzierten Objekte.

          Aha. Solange ich elementare Datentypen übergebe... gut zu wissen.

          Ist gegen dieses Art des Clonens etwas auszusetzen?

          Ja, es ist umständlich, weil clone solch eine so genannte shallow copy auch erzeugen kann.

          Ok. Scheint sich zu lohnen, mir das genauer anzusehen. Danke!

          Jonny

  2. Lieber Regenbogenjonny,

    Ich erstelle aus meinem Bild zuerst ein Thumb und dann resize ich das Original.

    warum in dieser Reihenfolge? Wenn Du das Original zuerst (herunter-?)skalierst, dann kannst Du von diesem Ergebnis doch auch noch ein Thumbnail erzeugen, oder nicht?

    Liebe Grüße,

    Felix Riesterer.

    1. Lieber Regenbogenjonny,

      Ich erstelle aus meinem Bild zuerst ein Thumb und dann resize ich das Original.

      warum in dieser Reihenfolge? Wenn Du das Original zuerst (herunter-?)skalierst, dann kannst Du von diesem Ergebnis doch auch noch ein Thumbnail erzeugen, oder nicht?

      Liebe Grüße,

      Felix Riesterer.

      Hi Felix,

      prinzipiell einverstanden.

      Aber ich bin neu in OOP. Und ich kenne keine Klasse, die vorgibt, in welcher Reihgenfolge die Methoden zu benutzen sind. Oder ist das Usus?

      Jonny

  3. hi,

    1.) Ist meine Vorgehensweise überhaupt die richtige?

    Klar, warum nicht, machbar ist alles. Andere Idee:

    Das Original wird als Attribut (readonly) in der Instanz abgelegt. Somit steht es in jeder Methode zur Verfügung und die Clonerei entfällt.

    MfG

    1. Hi,

      Das Original wird als Attribut (readonly) in der Instanz abgelegt. Somit steht es in jeder Methode zur Verfügung und die Clonerei entfällt.

      Das verstehe ich nicht. Kannst Du mir das genauer erklären oder als Beispiel darstellen?

      Gruß, Jonny

      1. Hi,

        Das Original wird als Attribut (readonly) in der Instanz abgelegt. Somit steht es in jeder Methode zur Verfügung und die Clonerei entfällt.

        Das verstehe ich nicht. Kannst Du mir das genauer erklären oder als Beispiel darstellen?

        Ganz einfach, ggf. bereits im Konstruktor:

         $this->binary; //= original Bilddatei
        

        Oder eine Methode bereitstellen, womit eine Bilddatei eingelesen werden kann.

        Damit kannst in Deinen Methoden alles machen, was das Herz begehrt und ohne das Original kaputtzumachen.

        MfG

        1. Hi pl,

          Ganz einfach, ggf. bereits im Konstruktor:

           $this->binary; //= original Bilddatei
          

          Und was ist dann die "original Bilddatei"? Doch nicht der Pfad?? Ich weiß schon, was Du meinst, aber wie lege ich ein Bild (also nicht den Pfad zum Bild) in eine Variable?

          Jonny

          1. Lieber Regenbogenjonny,

            Und was ist dann die "original Bilddatei"? Doch nicht der Pfad?? Ich weiß schon, was Du meinst, aber wie lege ich ein Bild (also nicht den Pfad zum Bild) in eine Variable?

            vielleicht mit file_get_contents('./pfad/datei.jpg')?

            $this->binary = file_get_contents($path);
            

            Liebe Grüße,

            Felix Riesterer.

            1. Tach!

              Ich weiß schon, was Du meinst, aber wie lege ich ein Bild (also nicht den Pfad zum Bild) in eine Variable?

              vielleicht mit file_get_contents('./pfad/datei.jpg')?

              Diese Antwort passt zwar zur Frage, aber allgemein ist dieser Zweig des Threads (bisher) nicht zielführend. Die Verarbeitung des Bildes findet mit der Imagick-Klasse statt. Die nimmt keine Binärdaten nur Dateinamen.

              Ich finde aber gerade, dass diese Klasse eine Methode clone() hat, die man aber nicht mehr nehmen soll. Stattdessen wird auf den clone-Operator von PHP verwiesen. Leider ist die Dokumentation etwas spärlich. "Makes an exact copy of the Imagick object" sagt jetzt nicht direkt aus, ob das dann eine völlig unabhängige Instanz wird. Zu vermuten ist das, alles andere ergäbe keinen gesteigerten Sinn.

              dedlfix.

              1. Tach!

                Ich weiß schon, was Du meinst, aber wie lege ich ein Bild (also nicht den Pfad zum Bild) in eine Variable?

                vielleicht mit file_get_contents('./pfad/datei.jpg')?

                Diese Antwort passt zwar zur Frage, aber allgemein ist dieser Zweig des Threads (bisher) nicht zielführend. Die Verarbeitung des Bildes findet mit der Imagick-Klasse statt.

                Ach was.

                Die nimmt keine Binärdaten nur Dateinamen.

                Klasse erweitern oder Delegation ist die Lösung. Welche genau, weiß der OP. Falls er am Lernen ist, sollte er alles mal gemacht haben.

                MfG