Toon posts:

PHP import CSV

Pagina: 1
Acties:

Onderwerpen

Vraag


  • josvane
  • Registratie: oktober 2002
  • Laatst online: 03-12 18:43
Al enige tijd ben ik aan het proberen om een CSV bestand met PHP in te lezen in een mysql database.
Via een formulier upload ik een CSV file welke dit omzet in een array.

Om dubbele records te voorkomen in de database wil ik op basis van het artikelnummer controleren of het bestaand artikel is of dat het gaat om een nieuw artikel.

Het zijn er natuurlijk meerdere maar een array ziet er zo uit
code:
1
2
3
4
5
6
7
8
9
10
11
12
Array
(
    [sku] => USG-3
    [search_code] => Ubiquiti
    [description] => Ubiquiti USG 3 security gateway
    [article_group] => 8000
    [is_divisible] => 0
    [journal_code_credit] => 8000
    [journal_code_debit] => 7000
    [is_active] => 1
    [exact] => 0
)

sku is degene die niet dubbel mag voorkomen. Als ik in mijn where statement deze waarde gebruik dan krijg ik geen resultaat. Vul ik USG-3 handmatig in dan werkt de query wel.

Als ik mijn sql code vergelijk zijn deze letterlijk identiek.
SQL code met variabele
code:
1
SELECT crm_articles.id, crm_articles.article_group, crm_articles.sku, crm_articles.is_active, crm_articles.created_at, crm_articles.description, crm_articles.price, crm_article_groups.label AS type FROM crm_articles LEFT JOIN crm_article_groups ON crm_articles.article_group = crm_article_groups.id WHERE crm_articles.sku = "USG-3"


SQL code met handmatig ingevulde sku
code:
1
SELECT crm_articles.id, crm_articles.article_group, crm_articles.sku, crm_articles.is_active, crm_articles.created_at, crm_articles.description, crm_articles.price, crm_article_groups.label AS type FROM crm_articles LEFT JOIN crm_article_groups ON crm_articles.article_group = crm_article_groups.id WHERE crm_articles.sku = "USG-3"


Zoals te zien totaal geen verschil.

Als ik onderstaande doe, dan is het resultaat string.
PHP:
1
echo gettype($data['sku']);

Daarnaast heb ik het geprobeerd zonder qoutes.
Iemand tips?

Beste antwoord (via josvane op 31-12-2020 11:48)


  • RobIII
  • Registratie: december 2001
  • Laatst online: 01:00

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

KelvinX schreef op woensdag 30 december 2020 @ 21:49:
dan is dit de snelste methode om het verschil te zien.
Nee, de snelste manier om te zien óf er verschil is ;) Hét verschil zie je als je gewoon ASCII waardes dumpt ofzo. Er is inderdaad kans dat er een 'tab' of ander 'onzichtbaar' teken in je waarde zit.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
function dump_string($value) {
  $result = '';
  for ($i = 0; $i < strlen($value); $i++) {
    $hexval = dechex(ord($value[$i]));
    $result .= "$value[$i] $hexval\n";
  }
  return $result;
}

echo dump_string($data['sku']);
?>

Geeft iets als:
U 55
S 53
G 47
- 2d
3 33


Verder eens met @Daos: gebruik parameterized queries.

Even los van dat alles: "Om dubbele records te voorkomen" heb je gewoon een unique constraint. Laat heel die select lekker zitten en laat je DB het lekker uitzoeken. Nu is 't maar een import scriptje, maar als je met meerdere gebruikers (of scripts die tegelijkertijd lopen enzo) te maken krijgt dan heb je een race condition. MySQL heeft daar een (non-ANSI SQL) on duplicate key voor, waar dat in veel andere RDBMS'en merge is.

[Voor 40% gewijzigd door RobIII op 30-12-2020 22:31]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Roses are red Violets are blue, Unexpected ‘{‘ on line 32.

Over mij

Alle reacties


  • Daos
  • Registratie: oktober 2004
  • Niet online
Prepared statements gebruiken. Is sowieso nodig als je sql-injection wilt voorkomen. Je moet zelf even zoeken op die prepared statements in combinatie met pdo of mysqli (welke van de 2 je gebruikt in je project)

  • KelvinX
  • Registratie: december 2019
  • Niet online
Wat is het verschil tussen md5($deEneSKU) en md5($deAndereSKU)?

Ik weet het, md5, bla bla bla, maar als je extra spaties hebt of gekke leestekens ofzo dan is dit de snelste methode om het verschil te zien.

Acties:
  • Beste antwoord
  • +3Henk 'm!

  • RobIII
  • Registratie: december 2001
  • Laatst online: 01:00

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

KelvinX schreef op woensdag 30 december 2020 @ 21:49:
dan is dit de snelste methode om het verschil te zien.
Nee, de snelste manier om te zien óf er verschil is ;) Hét verschil zie je als je gewoon ASCII waardes dumpt ofzo. Er is inderdaad kans dat er een 'tab' of ander 'onzichtbaar' teken in je waarde zit.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
function dump_string($value) {
  $result = '';
  for ($i = 0; $i < strlen($value); $i++) {
    $hexval = dechex(ord($value[$i]));
    $result .= "$value[$i] $hexval\n";
  }
  return $result;
}

echo dump_string($data['sku']);
?>

Geeft iets als:
U 55
S 53
G 47
- 2d
3 33


Verder eens met @Daos: gebruik parameterized queries.

Even los van dat alles: "Om dubbele records te voorkomen" heb je gewoon een unique constraint. Laat heel die select lekker zitten en laat je DB het lekker uitzoeken. Nu is 't maar een import scriptje, maar als je met meerdere gebruikers (of scripts die tegelijkertijd lopen enzo) te maken krijgt dan heb je een race condition. MySQL heeft daar een (non-ANSI SQL) on duplicate key voor, waar dat in veel andere RDBMS'en merge is.

[Voor 40% gewijzigd door RobIII op 30-12-2020 22:31]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Roses are red Violets are blue, Unexpected ‘{‘ on line 32.

Over mij


  • Wim-Bart
  • Registratie: mei 2004
  • Laatst online: 10-01 17:43

Wim-Bart

Zie signature voor een baan.

Codering, ASCII UTF-8 UTF-16 Unicode...... In de editor ziet het er allemaal het zelfde uit maar voor een applicatie kan het zo maar verschillende gegevens zijn.

Overigens EAN code moet uniek zijn en SKU hoeft dat niet.

Beheerders, Consultants, Servicedesk medewerkers. We zoeken het allemaal. Stuur mij een PM voor meer info of kijk hier De mooiste ICT'er van Nederland.


  • josvane
  • Registratie: oktober 2002
  • Laatst online: 03-12 18:43
RobIII schreef op woensdag 30 december 2020 @ 21:58:
[...]

Nee, de snelste manier om te zien óf er verschil is ;) Hét verschil zie je als je gewoon ASCII waardes dumpt ofzo. Er is inderdaad kans dat er een 'tab' of ander 'onzichtbaar' teken in je waarde zit.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
function dump_string($value) {
  $result = '';
  for ($i = 0; $i < strlen($value); $i++) {
    $hexval = dechex(ord($value[$i]));
    $result .= "$value[$i] $hexval\n";
  }
  return $result;
}

echo dump_string($data['sku']);
?>

Geeft iets als:
U 55
S 53
G 47
- 2d
3 33


Verder eens met @Daos: gebruik parameterized queries.

Even los van dat alles: "Om dubbele records te voorkomen" heb je gewoon een unique constraint. Laat heel die select lekker zitten en laat je DB het lekker uitzoeken. Nu is 't maar een import scriptje, maar als je met meerdere gebruikers (of scripts die tegelijkertijd lopen enzo) te maken krijgt dan heb je een race condition. MySQL heeft daar een (non-ANSI SQL) on duplicate key voor, waar dat in veel andere RDBMS'en merge is.
Thx voor je feedback, ik heb weer leesvoer.
KelvinX schreef op woensdag 30 december 2020 @ 21:49:
Wat is het verschil tussen md5($deEneSKU) en md5($deAndereSKU)?

Ik weet het, md5, bla bla bla, maar als je extra spaties hebt of gekke leestekens ofzo dan is dit de snelste methode om het verschil te zien.
Er zit inderdaad een verschil tussen de md5 waardes

  • RobIII
  • Registratie: december 2001
  • Laatst online: 01:00

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

josvane schreef op woensdag 30 december 2020 @ 22:41:

Er zit inderdaad een verschil tussen de md5 waardes
Nou, dan laat je de dump_string(...) op beide waardes los en kijk je naar de verschillen.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Roses are red Violets are blue, Unexpected ‘{‘ on line 32.

Over mij


  • Mr. HTTP
  • Registratie: november 2020
  • Laatst online: 16-11 15:04
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php


$sku = " \tUSG-3\r\n";
// $sku = "USG-3";


// Identify at least one white space character in UTF-8 mode (debug use-case)
// Does SKU have any white space?
if ( preg_match('/\s/u',$sku) === 1 ) {
  echo 'Hello kind sir, I have some of the finest white space for you!' . PHP_EOL;
  // debug
  var_dump($sku);
  // do json_encode to see characters encoded as \r \n \t \u0000 etc
  echo json_encode($sku);
}


// Make sure SKU from a CSV import is in the correct format/syntax (production use-case)
// SKU validation approach
if ( preg_match('/^[A-Za-z0-9\-]{1,32}$/',$sku) === 1 ) {
  echo 'SKU is a string with at least one character from the ranges A-Z, a-z, 0-9 or a dash (-), with a max of 32 characters' . PHP_EOL;
} else {
  echo 'You got problems buddy!' . PHP_EOL;
}

?>

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
// more PCRE love

// remove all white space
$sku = 'A1  -  B2  -   C3';
$sku_no_wsp = preg_replace('/\s{1,}/u','',$sku);
var_dump($sku_no_wsp); // A1-B2-C3

// remove all that is NOT from the ranges A-Z, a-z, 0-9 or a dash (-)
$sku = 'A1 !@ - B2 - ^$  C3';
$sku_cleaned = preg_replace('/[^A-Za-z0-9\-]{1,}/u','',$sku);
var_dump($sku_cleaned); // A1-B2-C3

?>


Bij dit soort problemen is er meestal hetvolgende aan de hand;
  • Er wordt geen rekening gehouden met een BOM (byte order mark) aan het begin van het CSV bestand.
  • Er wordt geen rekening gehouden met character encoding (UTF-8 of Latin1).
  • Er wordt geen rekening gehouden met verschil in EOL (end of line characters), \r\n (CRLF) op Windows, \n (LF) op Linux.
  • Er wordt geen schema validatie gedaan. - Geen checks of de input data klopt.
  • De CSV wordt steeds opgeslagen met extra markup (voorloopnullen, whitespace padding, locale conversion) of onzichtbare tekens vanwege wild copy-paste gedrag (RightToLeft of NonBreakingSpace markers).

[Voor 46% gewijzigd door Mr. HTTP op 31-12-2020 00:11]


  • DJMaze
  • Registratie: juni 2002
  • Niet online
josvane schreef op woensdag 30 december 2020 @ 22:41:
Er zit inderdaad een verschil tussen de md5 waardes
Gebruik eens bin2hex() op die waarde, dan weet je exact het probleem.

Maak je niet druk, dat doet de compressor maar


  • Voutloos
  • Registratie: januari 2002
  • Niet online
RobIII geeft al een gebruiksvriendelijke debug functie, dus vanwaar de drang om als spuit 11 incomplete suggesties te geven?

{signature}


  • raxon
  • Registratie: maart 2003
  • Laatst online: 16:41
Een goede functie is trim() te gebruiken op elk veld van je CSV, dan haal je die whitespace zo weg. Indien je geen str_getcsv() hebt gebruikt zie https://stackoverflow.com...647/multibyte-trim-in-php voor meer dan trim ascii karakters

[Voor 27% gewijzigd door raxon op 31-12-2020 21:47]

RaXon


  • DJMaze
  • Registratie: juni 2002
  • Niet online
Voutloos schreef op donderdag 31 december 2020 @ 11:37:
RobIII geeft al een gebruiksvriendelijke debug functie, dus vanwaar de drang om als spuit 11 incomplete suggesties te geven?
Rob zijn functie is correct voor standaard latin, niet voor unicode.
bin2hex is gewoon ook een manier, net als mb_strlen enzo.

Maak je niet druk, dat doet de compressor maar


  • Mr. HTTP
  • Registratie: november 2020
  • Laatst online: 16-11 15:04
raxon schreef op donderdag 31 december 2020 @ 18:18:
Een goede functie is trim() te gebruiken op elk veld van je CSV, dan haal je die whitespace zo weg. Indien je geen str_getcsv() hebt gebruikt
Als toevoeging; werkt dus alleen voor ASCII white space (single bytes characters). Een onzichtbare NBSP \u{00A0} haal je er niet mee weg.

  • Mr. HTTP
  • Registratie: november 2020
  • Laatst online: 16-11 15:04
DJMaze schreef op donderdag 31 december 2020 @ 18:40:
[...]

Rob zijn functie is correct voor standaard latin, niet voor unicode.
bin2hex is gewoon ook een manier, net als mb_strlen enzo.
Rob is idd correct voor single byte characters/binary, vandaar was ook mijn aanvulling op Rob. Met UTF-8 PCRE (/u modifier) en json_encode als maniertjes om snel bijzondere tekens en white space te spotten vanwege de conversie naar \t \n \u0000 (multi-byte characters) etc. in JSON strings. (Er vanuit gaande dat de workflow van TS in UTF-8 is en daar ook bij de import op getoetst wordt en er eventueel een conversie plaatsvindt. )

De opmerking van @Voutloos is waarschijnlijk omdat bin2hex niets meer toevoegt in deze context. Het ziet ook geen Unicode ofzo, als je dat denkt.

Zie dit voorbeeldje met CRLF (carriage return, line feed)
PHP:
1
2
3
4
5
6
7
8
9
$a = dechex(ord("\r"));
$b = dechex(ord("\n"));
$a_and_b = bin2hex("\r\n");

print_r([
  'a' => $a,
  'b' => $b,
  'a_b' => $a_and_b
]);


code:
1
2
3
4
5
6
Array
(
    [a] => d
    [b] => a
    [a_b] => 0d0a
)

[a] en [b] mist de voorloopnul, dat is normaal.

  • RobIII
  • Registratie: december 2001
  • Laatst online: 01:00

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

DJMaze schreef op donderdag 31 december 2020 @ 18:40:
[...]

Rob zijn functie is correct voor standaard latin, niet voor unicode.
Dat is helemaal niet relevant hier. Ja, er zijn vele mitsen rnaren en subtiliteiten in strings en hun encodings. Hier wil je gewoon even de "rauwe bytes" zien en dat komt, sorta-min-of-meer, neer op een "ASCII dump". Boeie. We kunnen hier in al die subtiliteiten gaan verzanden en het allemaal veel moeilijker maken dan nodig voor TS en er een wedstrijdje ver-pissen van maken óf TS gewoon even een inzicht verschaffen dat er waarschijnlijk iets onverwachts, en waarschijnlijk "onzichtbaars", in z'n string zit (en wáár dan). En mijn voorgestelde code werkt daar prima voor, unicode of niet.

[Voor 26% gewijzigd door RobIII op 31-12-2020 21:58]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Roses are red Violets are blue, Unexpected ‘{‘ on line 32.

Over mij

Pagina: 1


Nintendo Switch (OLED model) Apple iPhone 13 LG G1 Google Pixel 6 Call of Duty: Vanguard Samsung Galaxy S21 5G Apple iPad Pro (2021) 11" Wi-Fi, 8GB ram Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2021 Hosting door True

Tweakers maakt gebruik van cookies

Bij het bezoeken van het forum plaatst Tweakers alleen functionele en analytische cookies voor optimalisatie en analyse om de website-ervaring te verbeteren. Op het forum worden geen trackingcookies geplaatst. Voor het bekijken van video's en grafieken van derden vragen we je toestemming, we gebruiken daarvoor externe tooling die mogelijk cookies kunnen plaatsen.

Meer informatie vind je in ons cookiebeleid.

Sluiten

Forum cookie-instellingen

Bekijk de onderstaande instellingen en maak je keuze. Meer informatie vind je in ons cookiebeleid.

Functionele en analytische cookies

Deze cookies helpen de website zijn functies uit te voeren en zijn verplicht. Meer details

janee

    Cookies van derden

    Deze cookies kunnen geplaatst worden door derde partijen via ingesloten content en om de gebruikerservaring van de website te verbeteren. Meer details

    janee