Contao-Camp 2024
Ergebnis 1 bis 13 von 13

Thema: Upload-Feld im Modul "Persönliche Daten": kein Datenbankeintrag nach Upload

  1. #1
    Contao-Nutzer
    Registriert seit
    11.05.2014.
    Beiträge
    20

    Standard Upload-Feld im Modul "Persönliche Daten": kein Datenbankeintrag nach Upload

    Liebe Contao-Experten!

    Bin in Contao 3.2.13 auf folgendes Problem gestoßen und würde gerne Eure Einschätzung hören, ob das ein Bug ist.

    Ich habe im Frontend ein Login-Formular für registrierte Mitglieder, welches zu einer Seite mit dem Modul "Persönliche Daten" weiterleitet. Die Felder des Moduls habe ich ergänzt um ein Feld für einen Foto-Upload:

    PHP-Code:
    $GLOBALS['TL_DCA']['tl_member']['fields']['foto'] = array
    (
        
    'label'                   => &$GLOBALS['TL_LANG']['tl_member']['foto'],
        
    'exclude'                 => true,
        
    'search'                  => true,
        
    'inputType'               => 'upload',
        
    'eval'                    => array('mandatory' => false,'feEditable' => true,'feViewable' => true,'feGroup' => 'address','tl_class'=>'clr long','extensions'=>$GLOBALS['TL_CONFIG']['uploadTypes'], 'storeFile'=>true'uploadFolder' => $this->User->homeDir'readonly' => false),
        
    'sql'                     => "text NULL"
    ); 
    Das Upload-Feld wird im Frontend angezeigt und der Upload funktioniert, d.h. die Datei wird im korrekten Verzeichnis abgelegt. Soweit alles gut.

    Nun hätte ich aber gerne, dass der Name (oder die UUID) der hochgeladenen Datei auch in der Datenbank in der Tabelle 'tl_member' gespeichert wird. Die entsprechende Spalte 'foto' ist ja in der DCA konfiguriert und nach Datenbank-Update auch in der Datenbank vorhanden. Nur wird da leider nichts drin gespeichert. Bei allen anderen Feldern des Moduls "Persönliche Daten" funktioniert das Speichern in der Datenbank einwandfrei.

    Ich bin mal in den PHP-Code abgestiegen und soweit ich sehe passiert hier Folgendes:

    Das Modul "Persönliche Daten" ist in der Datei "system/modules/core/modules/ModulePersonalData.php" kodiert. Dort wird nacheinander für alle Felder/Widgets des Formulars die Methode validate() aufgerufen und der Feldwert abgefragt (Zeilen 194-195):

    $objWidget->validate();
    $varValue = $objWidget->value;

    Dieser Wert wird dann im Member Model abgelegt (Zeile 265) und das Model wird gespeichert (Zeile 284), also in die Datenbank geschrieben.

    Für das Feld 'upload' ist die Methode validate() in der Datei "system/modules/core/forms/FormFileUpload.php" definiert. Aber diese Methode gibt soweit ich sehen kann gar keinen Wert zurück. Die Methode checkt erstmal auf mögliche Fehler. Wenn kein Fehler vorhanden ist, wird die Datei auf dem Server abgelegt, eine UUID kreiert und der Ordner-Hash aktualisiert. Schließlich werden die Datei-Infos in der Session gespeichert und es wird ein Log-Eintrag generiert. Und das war's. Was ich dort NICHT sehe, ist so etwas wie

    $this->varValue = $file['name'];

    oder irgendeine andere Zuweisung eines Wertes an $this->varValue. Damit bleibt aber auch im Modul "Persönliche Daten" das $objWidget->value in Zeile 195 undefiniert, und also wird auch nichts im Member Model bzw. in der Datenbank gespeichert.

    Nach dieser langen Vorrede jetzt zwei Fragen:

    1) Stimmt das soweit oder habe ich was übersehen?
    2) Falls es stimmt, ist das ein Bug oder gibt es irgendwelche wichtigen Gründe, warum das Upload-Widget keinen Wert zurückgibt? Anders gefragt: Spricht etwas dagegen, die Methode validate() in der "FormFileUpload.php" folgendermaßen zu ändern (ab Zeile 259):

    PHP-Code:
    // Add the session entry (see #6986)
    $_SESSION['FILES'][$this->strName] = array
    (
        
    'name'     => $file['name'],
        
    'type'     => $file['type'],
        
    'tmp_name' => TL_ROOT '/' $strFile,
        
    'error'    => $file['error'],
        
    'size'     => $file['size'],
        
    'uploaded' => true,
        
    'uuid'     => \String::binToUuid($objFile->uuid)
    );

    // Set the value
    $this->varValue $file['name']; // alternativ die UUID oder das ganze Array aus der $_SESSION['FILES']

    // Add a log entry
    $this->log('File "'.$file['name'].'" has been moved to "'.$strUploadFolder.'"'__METHOD__TL_FILES); 
    Wäre Euch sehr dankbar für Eure Einschätzungen!

  2. #2
    Contao-Fan
    Registriert seit
    10.01.2010.
    Ort
    Kiel
    Beiträge
    339

    Standard

    Hallo,

    erst mal vielen Dank für die ausführliche Erklärung!

    Auch, wenn es schon eine Weile her ist.
    Ich hänge an der gleichen Stelle fest. Hast du inzwischen weitere Erkenntnisse?

    Deine Lösung mit der Zeile
    PHP-Code:
    $this->varValue $file['name']; 
    funktioniert bei mir leider nicht. Es wird trotzdem nichts in die Datenbank geschrieben.

    Ich benutze Contao 3.4.5
    Geändert von Tina (12.05.2015 um 11:34 Uhr)

  3. #3
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.058
    Partner-ID
    10107

    Standard

    Du könntest einfach den updatePersonalData Hook verwenden. Dort kannst du die UUID selber nochmal in die tl_member Table speichern.

  4. #4
    Contao-Nutzer
    Registriert seit
    11.05.2014.
    Beiträge
    20

    Standard

    Hallo Tina,

    ich habe das mit einer eigenen Erweiterung gelöst, die den von spooky genannten hook verwendet. In der config.php der Erweiterung steht

    PHP-Code:
    $GLOBALS['TL_HOOKS']['updatePersonalData'][] = array('UserFileUpload''saveFileName'); 
    und in der UserFileUpload.php

    PHP-Code:
    class UserFileUpload 
    {
        public function 
    saveFileName($objUser$arrData$objModule)
        {
            \
    Database::getInstance()
            ->
    prepare("UPDATE tl_member SET foto=? WHERE id=?")
            ->
    execute($_SESSION['FILES']['foto']['name'], $objUser->id);
        }

    Die Funktion schreibt den Dateinamen direkt in die Datenbank. Allerdings nur den Dateinamen, nicht die UUID. Das setzt natürlich voraus, dass in der tl_member die Spalte 'foto' konfiguriert ist wie in meinem ersten Post beschrieben. Die Erweiterung funktioniert bei mir auch unter Contao 3.4.5.

    Hier gibt es auch eine Diskussion zu dem Thema auf Github: https://github.com/contao/core/issues/7256

    Hilft dir das weiter?

  5. #5
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.058
    Partner-ID
    10107

    Standard

    Damit du statt dessen die UUID drin hast, könntest du einfach folgendes machen:
    PHP-Code:
    public function saveFileName($objUser$arrData$objModule)
    {
        
    $objFile = \Dbafs::addResource$_SESSION['FILES']['foto']['name'] );
        if( 
    $objFile !== null )
            \
    Database::getInstance()
            ->
    prepare("UPDATE tl_member SET foto=? WHERE id=?")
            ->
    execute($objFile->uuid$objUser->id);

    Unter Umständen muss es allerdings so sein:
    PHP-Code:
    public function saveFileName($objUser$arrData$objModule)
    {
        
    $objFile = \Dbafs::addResourcestr_replaceTL_ROOT DIRECTORY_SEPARATOR''$_SESSION['FILES']['foto']['tmp_name'] ) );
        if( 
    $objFile !== null )
            \
    Database::getInstance()
            ->
    prepare("UPDATE tl_member SET foto=? WHERE id=?")
            ->
    execute($objFile->uuid$objUser->id);

    Siehe https://github.com/contao/core/blob/.../Form.php#L444

  6. #6
    Contao-Fan
    Registriert seit
    10.01.2010.
    Ort
    Kiel
    Beiträge
    339

    Standard

    Ja, toll, das hat geklappt! Vielen Dank!
    Danke auch Spooky für den Hinweis mit der UUID. Die zweite Version war's.

  7. #7
    Contao-Fan Avatar von dhe
    Registriert seit
    25.10.2010.
    Ort
    Esslingen a.N.
    Beiträge
    657

    Standard Fatal error: Uncaught exception Exception with message Invalid upload folder ID

    Hallo,
    ich versuche grad, das Modul "Persönliche Daten" um ein Uploadfeld zu erweitern, damit der angemeldete User Videos in sein Benutzerverzeichnis laden kann.
    Dazu habe ich in einer eigenen Erweiturung in dca/tl_member.php das hier eingefügt
    PHP-Code:
    $GLOBALS['TL_DCA']['tl_member']['fields']['video'] = array
    (
        
    'label'                   => &$GLOBALS['TL_LANG']['tl_member']['video'],
        
    'exclude'                 => true,
        
    'search'                  => true,
        
    'inputType'               => 'upload',
        
    'eval'                    => array(
            
    'mandatory' => false,
            
    'feEditable' => true,
            
    'feViewable' => true,
            
    'feGroup' => 'address',
            
    'tl_class'=>'clr long',
            
    'extensions'=>$GLOBALS['TL_CONFIG']['uploadTypes'],
            
    'storeFile'=>true
            
    'readonly' => false,
            
    'uploadFolder' => $this->User->homeDir
        
    ),
        
    'sql'                     => "text NULL"
    ); 
    Ich habe auch den Hook wie Tina beschrieben hat eingefügt.

    Im Modul "Persönliche Daten" kann ich dann auch das entsprechende Feld ausgeben lassen.
    wenn ich allerdings eine Datei hochladen will, dann kommt folgende Fehlermeldung.

    Code:
    Fatal error: Uncaught exception Exception with message Invalid upload folder ID thrown in system/modules/core/forms/FormFileUpload.php on line 202
    Hat jemand eine Idee, was ich noch machen kann, bzw wo mein Fehler liegt?

    Grüße

  8. #8
    Contao-Fan
    Registriert seit
    10.01.2010.
    Ort
    Kiel
    Beiträge
    339

    Standard

    Den Fehler hatte ich auch. Bei mir funktionierte die Zuweisung des Upload-Folders nicht korrekt. Ich habe das so gelöst:
    PHP-Code:
    $this->import('Database');
    $obj = \FilesModel::findByPath('files/pfad-zum-uploadVZ');
    $homeDirPath $obj->uuid
    Und dann entsprechend:
    PHP-Code:
    $GLOBALS['TL_DCA']['tl_member']['fields']['video']['eval']['uploadFolder'] = $homeDirPath

  9. #9
    Contao-Fan Avatar von dhe
    Registriert seit
    25.10.2010.
    Ort
    Esslingen a.N.
    Beiträge
    657

    Standard

    Hallo Tina,
    kannst du mir ein Beispiel zukommen lassen, wie die das in welche Dateien eingefügt hast?
    Ich kann doch in eine DCA Datei nicht direkt PHP-Code einfügen oder?

    grüße

    PS: sorry, steh grad auf'm schlauch

  10. #10
    Contao-Fan
    Registriert seit
    10.01.2010.
    Ort
    Kiel
    Beiträge
    339

    Standard

    Hallo,

    doch die DCA besteht aus PHP-Code. Schau mal in die erste Zeile, die sollte mit „<?php“ beginnen

    Als Beispiel hier der Code aus meiner DCA:
    PHP-Code:
    <?php

    $this
    ->import('Database');
    $obj = \FilesModel::findByPath('files/mitglieder-daten');
    $homeDirPath $obj->uuid;

    $GLOBALS['TL_DCA']['tl_member']['fields']['logo'] = array(
        
    'label'     => &$GLOBALS['TL_LANG']['tl_member']['logo'],
        
    'exclude'   => true,
        
    'inputType' => 'fileTree',
        
    'eval'        => array('fieldType'=>'radio''filesOnly'=>true'tl_class'=>'clr''feViewable'=>true'feEditable'=>true'extensions'=>$GLOBALS['TL_CONFIG']['uploadTypes'], 'storeFile'=>true'useHomeDir'=>true'uploadFolder'=>$homeDirPath'doNotOverwrite'=>true'feGroup'=>'personal'),
        
    'sql'        => "binary(16) NULL"
    );

  11. #11
    Contao-Nutzer
    Registriert seit
    11.05.2014.
    Beiträge
    20

    Standard

    Hallo dhe,

    ich habe mit Contao 3.4.5 dieselbe Fehlermeldung bekommen und konnte das lösen indem ich in der DCA die Zeile

    PHP-Code:
    'uploadFolder' => $this->User->homeDir 
    ersetzt habe durch

    PHP-Code:
    'useHomeDir' => true 
    Probiers mal aus!

  12. #12
    Contao-Nutzer
    Registriert seit
    12.03.2012.
    Ort
    Dresden
    Beiträge
    219

    Standard

    Zitat Zitat von Spooky Beitrag anzeigen
    Damit du statt dessen die UUID drin hast, könntest du einfach folgendes machen:
    PHP-Code:
    public function saveFileName($objUser$arrData$objModule)
    {
        
    $objFile = \Dbafs::addResource$_SESSION['FILES']['foto']['name'] );
        if( 
    $objFile !== null )
            \
    Database::getInstance()
            ->
    prepare("UPDATE tl_member SET foto=? WHERE id=?")
            ->
    execute($objFile->uuid$objUser->id);

    Unter Umständen muss es allerdings so sein:
    PHP-Code:
    public function saveFileName($objUser$arrData$objModule)
    {
        
    $objFile = \Dbafs::addResourcestr_replaceTL_ROOT DIRECTORY_SEPARATOR''$_SESSION['FILES']['foto']['tmp_name'] ) );
        if( 
    $objFile !== null )
            \
    Database::getInstance()
            ->
    prepare("UPDATE tl_member SET foto=? WHERE id=?")
            ->
    execute($objFile->uuid$objUser->id);

    Siehe https://github.com/contao/core/blob/.../Form.php#L444
    Darf ich hier nochmal nachhaken? Hab alles wie beschrieben konfiguriert, bekomme aber beim Ausführe des Hooks immer den Fehler:
    PHP-Code:
    Uncaught exception InvalidArgumentException with message Invalid resource .../10__2.jpg thrown in system\modules\core\library\Contao\Dbafs.php on line 63 
    Hab schon alles mögliche versucht und weiss mir keinen Rat mehr.

    Hab das Feld als filetree eingerichtet und im SQL als binary. Nutze Contao 3.5.24, vielleicht hat sich hier durch die Version wieder etwas geändert?

    Danke für jede Hilfe.
    Viele Grüße
    Silvia

  13. #13
    Contao-Nutzer
    Registriert seit
    12.03.2012.
    Ort
    Dresden
    Beiträge
    219

    Standard

    Ich habe nun eine Lösung gefunden:

    PHP-Code:
    $_SESSION['FILES']['foto']['tmp_name'
    liefert den Namen incl. absolutem Pfad, was wahrscheinlich den Fehler in Dbafs ausgelöst hat.

    PHP-Code:
    $_SESSION['FILES']['foto']['name'
    liefert nur den Dateinamen und man muss den relativen Pfad noch hinzufügen, dies habe ich folgendermaßen gelöst, keine Ahnung, ob das so die feine Art ist, bin nicht der geborene Programmierer: ;-)

    PHP-Code:
    $img = \FilesModel::findByPk($objUser->homeDir)->path.'/'.$_SESSION['FILES']['foto']['name'];
            
            
    $objFile = \Dbafs::addResource($img);
                    \
    Database::getInstance()
                    ->
    prepare("UPDATE tl_member SET foto=? WHERE id=?")
                    ->
    execute($objFile->uuid$objUser->id); 
    Viele Grüße
    Silvia

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Lesezeichen

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •