PHP Unsichtbare Zeichen: %E2%80%8E


Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

EuroCent

Klappstuhl 2.0
Hallo zusammen,

seit Stunden habe Ich an einem Skript einen Fehler gesucht.
Es ging dabei um ein Datumsformat: 2020-07-06

Inhaltlich hat er es mir korrekt angezeigt.
Sobald die Abfrage dann via SQL an die DB ging, hieß es dann seitens DB: "conversion failed when converting date and/or time from character string".

Ich suchte seit Heute früh 6 Uhr nach dem Problem, warum er den Eintrag nicht speichern will.
Hatte Ich die Abfrage 1:1 nach geschrieben in die DB direkt, kam es zu keinem Fehler.

Also überprüfte Ich weiterhin mein Skript, um die Ursache heraus zu finden.
Selbst als Ich das Datumsformat manuell in die Variable gepackt hatte, gab es den selbigen Fehler.

PHP:
<?php
    //Dies hole Ich aus meinem Formular
    $date = $_REQUEST['dateformat'];
?>
   
<?php
    //Manuelle Schreibweise
    $date = "2020-07-06";
?>
Beide geben mit den oben-genannten Fehler der DB zurück.

Nach langem hin und her, suchen und machen... kam Ich mal auf die Glorreiche Idee und wande "rawurlencode" an.
Sie da: aus 2020-07-06 wurde: "%E2%80%8E2020-07%E2%80%8E-%E2%80%8E06%E2%80%8E"

Die Daten werden via JS an Ajax zum Skript geliefert.

Meine Frage:
Welche Ursache kann dies denn haben, dass er mir diesen Kryptischen Text zurückliefert.
Ich verwende in dem Skript kein UTF8-Decode oder Encode.

Lediglich "header("Content-Type: text/html; charset=utf-8");" => Hatte ich weg gelassen, der Fehler war der selbe!

Gibt es dafür irgendeine Erklärung wie sowas passieren kann?
 

Loddar1

Erfahrenes Mitglied
Was ist das für eine Zeit?
Ist das ein Zeitstempel also aktuelles Datum.
oder was?

Nutzt Du
created_at DATETIME DEFAULT CURRENT_TIMESTAMP

oder
datum int(12) unsigned NOT NULL,

in der DB zum speichern?
 

EuroCent

Klappstuhl 2.0
Nein ich nutze nur den Type Datetime dem ich das Feld mitteile...
Der Fehler tritt aber nicht Datenbank eben auf sondern über PHP, und da geb Ich nur GETDATE() mit...
 

Loddar1

Erfahrenes Mitglied
Zeig doch mal den Ausschnitt deiner Datenbank wo das datum gespeichert werden soll.
Irgendwie musst du die DB ja mal erstellt haben.

Die Kryptischen Zeichen werden durch rawurlencode erzeugt.

Wie lautet der Code um das Datum in die DB zu schreiben?
 
Zuletzt bearbeitet:

ComFreek

Mod | @comfreek
Moderator
Sie da: aus 2020-07-06 wurde: "%E2%80%8E2020-07%E2%80%8E-%E2%80%8E06%E2%80%8E"
Wenn du im Internet nach e2808e suchst (genau die Zeichen hinter den ersten drei Prozentzeichen), dann kommt sofort Unicode Character 'LEFT-TO-RIGHT MARK' (U+200E).

Die Kryptischen Zeichen werden durch rawurlencode erzeugt.
Das bezweifle ich. Der ursprüngliche String, den OP von JS per AJAX bekommt enthält wahrscheinlich schon diesen unsichtbare left-to-right-mark.

Zeig mal, wie genau dein JS es an den Server schickt und woher das JS selbst die Daten bezieht.
 

EuroCent

Klappstuhl 2.0
Die Kryptischen Zeichen werden durch rawurlencode erzeugt.
Nichts für ungut aber das ist totaler Nonsens!
Dann wäre das Problem nicht nur beim Datumsformat!

Selbst wenn man danach Googlet bekommt man wie ComFreak es erwähnt Left-To-Right und kein Problem seitens rawurlencode oder rawurldecode :)
@ComFreek
Kann Ich Dir leider erst morgen Zeigen :)

Aktuell funktioniert es, aber Ich zeige Dir morgen einen Ajax Abschnitt und die Verarbeitung via PHP. :)

Aber eins kann Ich schonmal sagen, per Ajax wird das Datum aus dem Feld Date an Ajax übergeben :)

An der HTML-5 Syntax kann es also aus meiner Sicht nicht liegen :)
 

EuroCent

Klappstuhl 2.0
So wie gestern erwähnt hier das HTML-5 Element (ist kein DATE sondern TEXT):
HTML:
<input type="text" class="form-control form-control-sm" required value="06.07.2020" min="01.01.2050" max="01.01.2050" name="catalogexpiredFrom" id="catalogexpiredFrom" />
Ajax-Call:
Javascript:
$('form[name="catalogFormAdd"]').submit(function(e) {
    e.preventDefault();

    let form = $('form[name="catalogFormAdd"]').serializeArray();

    $.ajax({
        type: "POST",
        url: "save/catalog_save.php",
        data: form,
        cache: false,
        success: function(data) {
            let dataJson = JSON.parse(data);
        },
        error: function(xhr, status, error) {}
    });
});
in catalogexpiredFrom steht: 06.07.2020.

PHP:
PHP:
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/framework/config.php'; //Verbindungsdaten
require_once $_SERVER['DOCUMENT_ROOT'] . '/framework/php/basic_funct.php'; //Verbindungsdaten
////////////////////////Head////////////////////////////////////////////////////////////////////
$mainPage = new Page();
$mainPage->setConnection($con);
$msconnect = $mainPage->msconnect_srv;

$_REQUEST['catalogexpiredFrom'] = explode('.', $_REQUEST['catalogexpiredFrom']);
$_REQUEST['catalogexpiredFrom'] = $_REQUEST['catalogexpiredFrom'][2]."-".$_REQUEST['catalogexpiredFrom'][1]."-".$_REQUEST['catalogexpiredFrom'][0];
?>
Wenn jetzt rawurlencode nehme weil mir die DB mitteilt dass der Type ein datetime-format haben muss, dann kommt das dabei raus:
Code:
%E2%80%8E2020-07%E2%80%8E-%E2%80%8E06%E2%80%8E
 

Loddar1

Erfahrenes Mitglied
in catalogexpiredFrom steht: 06.07.2020.
ist kein Datumsformat aber Du könntest es als text in die DB schreiben!
Oder nutze einfach beim speichern einen timestemp.

mach aus 06.07.2020 einfach 2020-07-06

$datum = date("Y-m-d");

Table = `datum` datetime NOT NULL,
 
Zuletzt bearbeitet:

basti1012

Erfahrenes Mitglied
Hast du mal da was von versucht ?
 

Loddar1

Erfahrenes Mitglied
Ich arbeite absolut ohne javascript,ajax,jQuery usw.
aber Du hast noch immernicht den DB auszug, und deinen Weg zum speichern in eine DB gepostet.
 

EuroCent

Klappstuhl 2.0
Hast du mal da was von versucht ?
Ja das hab Ich schon genutzt.
Das ergebnis bleibt daher das selbe.

Ich arbeite absolut ohne javascript,ajax,jQuery usw.
aber Du hast noch immernicht den DB auszug, und deinen Weg zum speichern in eine DB gepostet.
Nichts für ungut, aber der Eintrag in die DB ist nicht das Problem.
Sondern vorweg die Codierung.

Daher ist es nicht notwendig dir einen Auszug zu schicken.

Wie gesagt das Feld in der DB ist als datetime deklariert.

PHP:
<?php
$sql = "INSERT INTO [dbo].[tabelle] ([catalog_date]) VALUES(?)";
$params = array($_REQUEST['catalogexpiredFrom']);
$stmt = sqlsrv_prepare($msconnect, $sql, $params);
sqlsrv_execute($stmt);
sqlsrv_free_stmt($stmt);
?>
 

ComFreek

Mod | @comfreek
Moderator
Ich vermute, dass der Browser dieses Zeichen einfügt. Überprüfe doch mal, ob nach Veränderung der Eingabe (manuell mittels Tastatur) der Wert des Eingabefeldes das left-to-right-mark enthält. Etwa via hexEncode(document.getElementById('catalogexpiredFrom').value), wobei du dir hexEncode irgendwo aus dem Internet ziehen müsstest, z. B. von Javascript: Unicode string to hex.

Was spricht dagegen ein <input>-Feld vom type="date" zu benutzen? Ich würde stark vermuten, dass da der Browser so etwas nicht einfügen würde.

Nebenbei: wenn dein <input>-Feld type="text" hat, machen dann die Attribute "min" und "max" überhaupt noch Sinn -- geschweige denn sind erlaubt?
 

EuroCent

Klappstuhl 2.0
Ich vermute, dass der Browser dieses Zeichen einfügt. Überprüfe doch mal, ob nach Veränderung der Eingabe (manuell mittels Tastatur) der Wert des Eingabefeldes das left-to-right-mark enthält. Etwa via hexEncode(document.getElementById('catalogexpiredFrom').value), wobei du dir hexEncode irgendwo aus dem Internet ziehen müsstest, z. B. von Javascript: Unicode string to hex.
Das werde Ich mir morgen anschauen :)
Sieht zumindestens sehr viel versprechend aus. :)

Vielen Dank :D

Was spricht dagegen ein <input>-Feld vom type="date" zu benutzen? Ich würde stark vermuten, dass da der Browser so etwas nicht einfügen würde.
Leider verwenden wir noch den IE11 und der nimmt zwar das date-Attribute aber baut es als en-GB das Datum um (2020-06-07).
Das irritiert aber viele, da der Chrome welcher Alternative unterstützt wird, macht.

Sobald der neue Edge draußen ist, wird dieser für das Unternehmen entsprechend Verwendet.
Dann ist die alternative zu Chrome dann auch hinfällig :D

Daher hab Ich es aktuell in text umgestellt damit es nicht zu Problemen führt. :)

Nebenbei: wenn dein <input>-Feld type="text" hat, machen dann die Attribute "min" und "max" überhaupt noch Sinn -- geschweige denn sind erlaubt?
Macht natürlich null Sinn, an der Stelle hab Ich es nur versäumt, es entsprechend zu entfernen.
Das wird natürlich noch entfernt. :)
 

ComFreek

Mod | @comfreek
Moderator
Ich verstehe! Wenn es tatsächlich der Browser ist, würde ich das clientseitig mit String.prototype.trim() aus dem inputField.value entfernen. Ich würde sowieso empfehlen, clientseitig sowie serverseitig das eingegebene Datum zu validieren.
 

EuroCent

Klappstuhl 2.0
Ich verstehe! Wenn es tatsächlich der Browser ist, würde ich das clientseitig mit String.prototype.trim() aus dem inputField.value entfernen. Ich würde sowieso empfehlen, clientseitig sowie serverseitig das eingegebene Datum zu validieren.
Naja ist halt die Frage ob er diese Zeichen ebenfalls entfernt. :)

Ich werde es dennoch versuchen :)
Bin zwar nicht sicher, aber glaube dass Ich dies bereits gemacht hatte. :)
Aber egal... auf ein neues :D
 

ComFreek

Mod | @comfreek
Moderator
Oh, tatsächlich werden die mit trim() oder Regex \s nicht gematched und entfernt:
Javascript:
"\u200e".trim().length // result: 1
"\u200e".replace(/^\s*/g, "").length // result: 1
Dann müsstest du U200E (oder gleich eine umgebende Range*) explizit im Regex vermerken.

* zum Beispiel ist der Right-to-Left-Mark mit U200F direkt daneben.
 

EuroCent

Klappstuhl 2.0
Oh, tatsächlich werden die mit trim() oder Regex \s nicht gematched und entfernt:
Javascript:
"\u200e".trim().length // result: 1
"\u200e".replace(/^\s*/g, "").length // result: 1
Dann müsstest du U200E (oder gleich eine umgebende Range*) explizit im Regex vermerken.

* zum Beispiel ist der Right-to-Left-Mark mit U200F direkt daneben.
Okay dann ist meine Lösung schon bereits eingebunden gewesen.
Denn mit regex habe Ich es bereits php seitig gelöst. :)
 
Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

Neue Beiträge