Neukunden Kontoanlage: außer Straße auch Hausnummer verlangen

Thema wurde von Thomas Gehrke, 9. Dezember 2015 erstellt.

  1. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    16. Januar 2016
    Beiträge:
    656
    Danke erhalten:
    112
    Danke vergeben:
    20
    Fuer alle die das Thema noch interessiert. Ich (muss) ja kein Code hier veroeffentlichen, aber einen kleinen Hinweis andeuten.
    Updatesicher koennt ihr eure eigene Validierungen durch Ueberladen oder (in Gambiosprache) Overload der Klasse
    "CustomerInputValidator" loesen.

    Will man zum Beispiel auf valide PLZ hin pruefen.
    Dann koennt ihr das unter

    PHP:
    /**
    * Checks if the entered postcode is valid.
    *
    * @param string $p_postcode Customer's post code.
    *
    * @return bool Is valid?
    */

    // TODO: Diesen Witz durch RegEx in einer Overload-Klasse ersetzen
    // Hinweis: getPostcodeMaxLength() ist auf 10 Zeichen hart codiert in der Klasse "CustomerInputValidatorSettings".
    // Hinweis: getPostcodeMinLength() ist auf 4 Zeichen hart codiert in der Datenbank hinterlegt.

    public function validatePostcode($p_postcode)
    {
        if (
    strlen_wrapper(trim((string)$p_postcode)) > $this->settings->getPostcodeMaxLength()) {
            
    $this->errorStatus true;
            
    $this->errorMessageCollection->setValue('error_post_code'$this->settings->getInvalidInputErrorMessage());

            return 
    false;
        }
       
        if (
    strlen_wrapper((string)$p_postcode) < $this->settings->getPostcodeMinLength()) {
            
    $this->errorStatus true;
            
    $this->errorMessageCollection->setValue('error_post_code'$this->settings->getPostcodeErrorMessage());

            return 
    false;
        }

        return 
    true;
    }
    Dann wuensche ich euch viel Erfolg und gutes gelingen.
    Fuer Tipps stehe ich euch, wie immer gerne zur Verfuegung!


    Entschuldigt bitte den Text ohne Umlaute - Habe auf der mobilen Workstation englische Tastatur. :)
     
  2. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    16. Januar 2016
    Beiträge:
    656
    Danke erhalten:
    112
    Danke vergeben:
    20
    #22 Anonymous, 4. April 2016
    Zuletzt bearbeitet: 4. April 2016
    Keine schöne aber auf die schnelle eine Lösung bzgl. Straße und Postleitzahl erstellt, wo auch mein Vorgesetzter nichts sagen dürfte (da kein 1:1 Code)

    Unter "user_classes/overloads/CustomerRegistrationInputValidatorService/" zum Beispiel eine Datei "CheckoutFormValidation.php" erstellen und mit:

    PHP:
    class CheckoutFormValidation extends CheckoutFormValidation_parent
    {
        
    /**
         * Checks if the entered data is valid.
         *
         * Expects an array with the following keys:
         *  - gender
         *  - firstname
         *  - lastname
         *  - dob (date of birth)
         *  - company
         *  - email_address
         *  - suburb
         *  - email_address_confirm
         *  - postcode
         *  - city
         *  - country
         *  - state (ID or name)
         *  - telephone
         *  - fax
         *  - vat
         *
         * @param array $inputArray Customer Input array.
         *
         * @return bool Is customer data valid?
         */
        
    protected function _validateDataByArray(array $inputArray)
        {
            
    $this->validateGender($inputArray['gender']);
            
    $this->validateFirstname($inputArray['firstname']);
            
    $this->validateLastname($inputArray['lastname']);
            
    $this->validateDateOfBirth($inputArray['dob']);
            
    $this->validateCompany($inputArray['company']);
            
    $this->validateEmailAndConfirmation($inputArray['email_address'], $inputArray['email_address_confirm']);
            
    $this->validateSuburb($inputArray['suburb']);

            
    /*
             * RegEx für Straße/Nr.
             */
            
    if (!preg_match("/^([\wüäö\s*?(\-\.)?]{2,})\s*?(\d)+?\w*?$/i"$inputArray['street_address'])) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_street''Straßeneingabe ist ungültig.');
            }

            
    /*
             * RegEx für Postleitzahl
             *
             * @country->getId()
             * 150 = Niederlande
             * 222 = Großbritannien
             */

            
    $country $this->customerCountryRepository->findById(new IdType($inputArray['country']));

            if (
    $country->getId() === 150 &&
                !
    preg_match("/^([0-9]{4}\s?[a-z]{2})$/i"$inputArray['postcode'])
            ) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_post_code''Postcode is ongeldig.');
            } elseif (
    $country->getId() === 222 &&
                !
    preg_match("/^([a-z0-9]{2,4}\s?[a-z0-9]{3})$/i"$inputArray['postcode'])
            ) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_post_code''Zip code is invalid.');
            }

            if (!
    preg_match("/^([0-9]{4,10})$/i"$inputArray['postcode'])) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_post_code''Postleitzahl ist ungültig.');
            }

            
    $this->validateCity($inputArray['city']);
            
    $this->validateCountry($inputArray['country']);
            
    $this->validateCountryZone($inputArray['state'], $inputArray['country']);
            
    $this->validateTelephoneNumber($inputArray['telephone']);
            
    $this->validateFaxNumber($inputArray['fax']);

            return !
    $this->getErrorStatus();
        }
    }
    befüllen... Eventuell die Fehlerausgaben durch den Translator jagen
    Danach die Cache leeren und gut ist.

    Getestet wurde an einem Gastkonto... von daher vor der Nutzung erst an einem Testshop testen!
     
  3. Christian Mueller

    Christian Mueller Beta-Held

    Registriert seit:
    4. Juli 2011
    Beiträge:
    3.198
    Danke erhalten:
    666
    Danke vergeben:
    235
    Danke, das sieht schon ganz gut aus. Leider Funktioniert die Prüfung der Straße nur dort, wo die Hausnummer HINTER der Straße steht. In Frankreich steht die immer davor. Deshalb habe ich einfach nur geprüft ob eine Zahl im String vorhanden ist, dann ist es egal ob vorne oder hinten. Funktioniert bei "Strasse des 17. Juni" dann natürlich auch ohne Hausnummer, aber so viele Strassennamen mit Zahlen drinn gibt es nicht.
     
  4. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    16. Januar 2016
    Beiträge:
    656
    Danke erhalten:
    112
    Danke vergeben:
    20
    Vielen Dank für den Hinweis wegen Frankreich...

    Vielleicht könnte man eine Auflistung der EU Länder erstellen, die von unseren bekannten Standard für Adressen abweichen und diese per Reguläre Ausdrücke abfangen. Damit hätten wir schon mal die EU Länder abgedeckt. Weiter hinaus glaube ich verkauft eh niemand seine Waren.
     
  5. Christian Mueller

    Christian Mueller Beta-Held

    Registriert seit:
    4. Juli 2011
    Beiträge:
    3.198
    Danke erhalten:
    666
    Danke vergeben:
    235
    Für die PLZ habe ich diese Liste regulärer Ausdrücke bereits erstellt und in Tabelle countries eingetragen. Da ist dann auch die Art der Adresse definiert.


    Man sollte aber nicht zu genau prüfen, dann gibt es wieder neue Probleme. Die Autofill-Problematik kann man auch so gut abfangen. Wenn man noch die Länge der PLZ prüft, hilft es falsche Länderangaben auszufiltern. Ein reine Dezimalangabe im Feld Ort sollte auch nicht erlaubt sein.
     

    Anhänge:

  6. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    16. Januar 2016
    Beiträge:
    656
    Danke erhalten:
    112
    Danke vergeben:
    20
    Ich schaue es mir später mal an, deine SQL-Datei.

    Du hast schon recht... Man sollte nicht all zu streng sein... Aber die Standards sollten gegeben sein.

    Zum Beispiel: Tippe so viele Leerzeichen ein, wie du lustig bist, solange du auch z.B eine Zahl eintippst und keine Sonderzeichen.
     
  7. Christian Mueller

    Christian Mueller Beta-Held

    Registriert seit:
    4. Juli 2011
    Beiträge:
    3.198
    Danke erhalten:
    666
    Danke vergeben:
    235
    Stimmt. Man könnte damit auch Zeilenschaltungen und nicht unterstützte Sonderzeichen filtern, die gerne im Feld Strasse eingegeben werden und später, z.B. beim Import in die Warenwirtschaft, Probleme machen.
     
  8. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    16. Januar 2016
    Beiträge:
    656
    Danke erhalten:
    112
    Danke vergeben:
    20
    #28 Anonymous, 5. April 2016
    Zuletzt bearbeitet: 5. April 2016
    Hallo Christian,

    habe mir deine SQL-Datei angeschaut.
    Die Postleitzahlen hätten wir ja mit der oben gezeigten Lösung schon mal alle EU-Länder abgedeckt.

    Für Straßen die RegEx für Straßen/Nr. mit diesem ersetzen

    PHP:
    /*
    * RegEx für Straße/Nr.
    */
    if (!preg_match("/^(\d+?\w*?\s*?([\wàâæçèéêëîïôœùûÿ\s*?(\-\.)?]{2,})|([\wüäö\s*?(\-\.)?]{2,})\s*?(\d)+?\w*?)$/i"$inputArray['street_address'])) {
        
    $this->errorStatus true;
        
    $this->errorMessageCollection->setValue('error_street''Straßeneingabe ist ungültig.');
    }

    Also

    PHP:
    class CheckoutFormValidation extends CheckoutFormValidation_parent
    {
        
    /**
         * Checks if the entered data is valid.
         *
         * Expects an array with the following keys:
         *  - gender
         *  - firstname
         *  - lastname
         *  - dob (date of birth)
         *  - company
         *  - email_address
         *  - suburb
         *  - email_address_confirm
         *  - postcode
         *  - city
         *  - country
         *  - state (ID or name)
         *  - telephone
         *  - fax
         *  - vat
         *
         * @param array $inputArray Customer Input array.
         *
         * @return bool Is customer data valid?
         */
        
    protected function _validateDataByArray(array $inputArray)
        {
            
    $this->validateGender($inputArray['gender']);
            
    $this->validateFirstname($inputArray['firstname']);
            
    $this->validateLastname($inputArray['lastname']);
            
    $this->validateDateOfBirth($inputArray['dob']);
            
    $this->validateCompany($inputArray['company']);
            
    $this->validateEmailAndConfirmation($inputArray['email_address'], $inputArray['email_address_confirm']);
            
    $this->validateSuburb($inputArray['suburb']);

            
    /*
             * RegEx für Straße/Nr.
             */
            
    if (!preg_match("/^(\d+?\w*?\s*?([\wàâæçèéêëîïôœùûÿ\s*?(\-\.)?]{2,})|([\wüäö\s*?(\-\.)?]{2,})\s*?(\d)+?\w*?)$/i"$inputArray['street_address'])) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_street''Straßeneingabe ist ungültig.');
            }

            
    /*
             * RegEx für Niederlande und Großbritannien
             *
             * @country
             * 150 = Niederlande
             * 222 = Großbritannien
             */

            
    $country $this->customerCountryRepository->findById(new IdType($inputArray['country']));

            if (
    $country->getId() === 150 &&
                !
    preg_match("/^([0-9]{4}\s?[a-z]{2})$/i"$inputArray['postcode'])
            ) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_post_code''Postcode is ongeldig.');
            } elseif (
    $country->getId() === 222 &&
                !
    preg_match("/^([a-z0-9]{2,4}\s?[a-z0-9]{3})$/i"$inputArray['postcode'])
            ) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_post_code''Zip code is invalid.');
            }

            if (!
    preg_match("/^([0-9]{4,10})$/i"$inputArray['postcode'])) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_post_code''Postleitzahl ist ungültig.');
            }

            
    $this->validateCity($inputArray['city']);
            
    $this->validateCountry($inputArray['country']);
            
    $this->validateCountryZone($inputArray['state'], $inputArray['country']);
            
    $this->validateTelephoneNumber($inputArray['telephone']);
            
    $this->validateFaxNumber($inputArray['fax']);

            return !
    $this->getErrorStatus();
        }
    }
    Weiß nur nicht wie die RegEx mit franz. Zeichen umgeht... Müsste man vorab gucken.
    Haben wir hier im Forum zufällig einen französischen Experten der alle Sonderzeichen der Franzosen auflisten kann?

    Und dann haben wir da noch die Spanier, Polen usw. mit ihren Sonderzeichen :)
     
  9. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    16. Januar 2016
    Beiträge:
    656
    Danke erhalten:
    112
    Danke vergeben:
    20

    Habe mir deine SQL nun genauer angeschaut und da gibt es doch noch die eine oder die andere Abweichung der Postleitzahlen in den EU-Ländern.

    Zum Beispiel: Polen - Die PLZ besteht auch wie in DE nur aus Ziffern, jedoch kann auch ein Bindestrich vorkommen, usw.

    Wie aktuell sind diese Angaben in deiner SQL?

    Kann mir gut vorstellen, dass wir dann unsere Lösung über RegEx von oben in Verbindung zum gewählten Land über eine Datenbankabfrage steuern können.

    Somit wäre der Quellcode etwas sauberer und leichter lesbar :)

    Was die Sonderzeichen in der jeweiligen Sprache betrifft, könnte man evtl. vorerst über eine Konstante

    PHP:
    const VALID_CHARACTERS " "// Alle möglichen Vorkommen von exotischen Wortzeichen.
    fest definieren und peu à peu das ganze (aus Performancegründen) nach Land optimieren und diese ebenfalls in der DB ablegen.

    Die fertige Lösung dann noch zusätzlich über eine Art "Autofill" ergänzen und perfekt ist das Disaster ;)
     
  10. Christian Mueller

    Christian Mueller Beta-Held

    Registriert seit:
    4. Juli 2011
    Beiträge:
    3.198
    Danke erhalten:
    666
    Danke vergeben:
    235
    Da muss ich schon wieder aufzeigen ;-)

    Guckst Du hier: https://www.hs-hannover.de/fileadmi...h2_online/f2_index/f2_index_sonderzeichen.pdf

    Der Einfachheit würde ich sagen, alle Zeichen von ASCII 000 bis 032 und von 168 bis 255 sperren
    oder nur Zeichen von 033 bis 167 erlauben.
     
  11. Christian Mueller

    Christian Mueller Beta-Held

    Registriert seit:
    4. Juli 2011
    Beiträge:
    3.198
    Danke erhalten:
    666
    Danke vergeben:
    235
  12. Christian Mueller

    Christian Mueller Beta-Held

    Registriert seit:
    4. Juli 2011
    Beiträge:
    3.198
    Danke erhalten:
    666
    Danke vergeben:
    235
    Übrigens gibt es in meiner SQL die Spalte "Sample" als Hinweistext für die Fehlermeldung.
     
  13. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    16. Januar 2016
    Beiträge:
    656
    Danke erhalten:
    112
    Danke vergeben:
    20

    Na ja, ich weiß nicht wie der Code reagieren wird, wenn wir auf ASCII-Werte prüfen, aber UTF-8 Code eingeleitet wird ;)
    und wir wollen ja eine performante Lösung haben :p

    Danke für den Wiki-Link... Mit den jeweiligen Links zu den einzelnen Ländern kann man deine Vorlagen zu Postleitzahlen aus der SQL etwas besser tunen
     
  14. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    16. Januar 2016
    Beiträge:
    656
    Danke erhalten:
    112
    Danke vergeben:
    20
    Sorry für die lange Wartezeit.. hatte beruflich viel um die Ohren :(

    Auf dieser Grundlage kannst du deine Datenbank ins Spiel bringen.
    Das Anpassen wegen RegEx und den ASCII-Werten überlasse ich dir.


    PHP:
    class CustomizedFormValidation extends CustomizedFormValidation_parent
    {
        protected 
    $settings;
        protected 
    $loader;
        protected 
    $db;
        protected 
    $errorfields = [
            
    'firstname'      => 'first_name',
            
    'lastname'       => 'last_name',
            
    'street_address' => 'street',
            
    'postcode'       => 'post_code',
            
    'city'           => 'city',
        ];

        public function 
    __construct(
            
    CustomerServiceInterface $customerServiceInterface,
            
    CountryServiceInterface $countryServiceInterface,
            
    CustomerInputValidatorSettingsInterface $customerInputValidatorSettingsInterface,
            
    CustomerCountryRepositoryInterface $customerCountryRepositoryInterface,
            
    CustomerCountryZoneRepositoryInterface $customerCountryZoneRepositoryInterface,
            
    VatNumberValidatorInterface $vatNumberValidatorInterface
        
    ) {
            
    $this->loader MainFactory::create('GXCoreLoader'MainFactory::create('GXCoreLoaderSettings'));
            
    $this->db     $this->loader->getDatabaseQueryBuilder();

            
    parent::__construct(
                
    $customerServiceInterface,
                
    $countryServiceInterface,
                
    $customerInputValidatorSettingsInterface,
                
    $customerCountryRepositoryInterface,
                
    $customerCountryZoneRepositoryInterface,
                
    $vatNumberValidatorInterface
            
    );
        }

        protected function 
    _validateDataByArray(array $inputArray)
        {
            foreach (
    $inputArray as $item => $value) {
                for (
    $i 0$i strlen($value); $i++) {
                    if (
    ord($value[$i]) <= 32 || ord($value[$i]) >= 168 && array_key_exists($item$this->errorfields)) {
                        
    $this->errorStatus true;
                        
    $this->errorMessageCollection->setValue('error_'.$this->errorfields[$item], 'Sonderzeichen sind nicht erlaubt.');
                    }
                }
            }

            
    $this->validateGender($inputArray['gender']);
            
    $this->validateFirstname($inputArray['firstname']);
            
    $this->validateLastname($inputArray['lastname']);
            
    $this->validateDateOfBirth($inputArray['dob']);
            
    $this->validateCompany($inputArray['company']);
            
    $this->validateEmailAndConfirmation($inputArray['email_address'], $inputArray['email_address_confirm']);
            
    $this->customValidateStreet($inputArray['street_address'], $inputArray['country']);
            
    $this->validateSuburb($inputArray['suburb']);
            
    $this->customValidatePostcode($inputArray['postcode'], $inputArray['country']);
            
    $this->validateCity($inputArray['city']);
            
    $this->validateCountry($inputArray['country']);
            
    $this->validateCountryZone($inputArray['state'], $inputArray['country']);
            
    $this->validateTelephoneNumber($inputArray['telephone']);
            
    $this->validateFaxNumber($inputArray['fax']);

            return !
    $this->getErrorStatus();
        }

        private function 
    customValidatePostcode($format$country)
        {
            
    // Holt sich das Format und ein Beispiel aus der Datenbank
            
    $regEx $this->db->select('zip_format, zip_sample')->from('countries')->where('countries_id'$country)->get()->result_array();

            if (!
    preg_match("/".$regEx[0]['zip_format']."/i"$format)) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_post_code''(Format: '.$regEx[0]['zip_sample'].')');
            }
        }

        private function 
    customValidateStreet($format$country)
        {
            
    // Holt sich das Format und ein Beispiel aus der Datenbank
            
    $regEx $this->db->select('street_format, street_sample')->from('countries')->where('countries_id'$country)->get()->result_array();

            if (!
    preg_match("/".$regEx[0]['street_format']."/i"$format)) {
                
    $this->errorStatus true;
                
    $this->errorMessageCollection->setValue('error_street''(Format: '.$regEx[0]['street_sample'].')');
            }
        }

    In "user_classes/overloads/CustomerRegistrationInputValidatorService" Datei erstellen und einfügen....
    Ist Updatesicher solange Gambio nichts schwerwiegendes verändert.

    Viel Spaß damit!
     
  15. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    22. September 2011
    Beiträge:
    851
    Danke erhalten:
    80
    Danke vergeben:
    120
    Nachdem es in letzer Zeit häufiger Bestellungen ohne Hausnummer gab, hab ich auch nach einer Lösung gesucht. Die Überprüfung klappt soweit, allerdings nur bei neu angelegten Adressen, allerdings nicht bei Adressänderungen oder abweichender Lieferadresse.
    Gibt es eine einfache Möglichkeit die Überprüfung auch dort durchzuführen?

    Außerdem habe ich das Problem, dass die Sonderzeichen nur als Viereck dargestellt werden. Die Datenbank und der Shop sind, aber auf UTF8 eingestellt, wo könnte das Problem liegen?
     
  16. Anonymous

    Anonymous Erfahrener Benutzer

    Registriert seit:
    19. Juni 2012
    Beiträge:
    4.550
    Danke erhalten:
    1.000
    Danke vergeben:
    866
    #36 Anonymous, 7. Juni 2020
    Zuletzt bearbeitet: 7. Juni 2020
    Habe das jetzt mal getestet (ohne die Sonderzeichen-SQL-Datenbank):

    Straße "XY-strasse 7/8/93" ist für Österreich damit nicht mehr möglich scheinbar. Ich dachte, der Regex prüft nur ob die Straße sowohl Buchstaben als auch Zahlen enthält? Das ist hier ja der Fall eigentlich...

    Ich dachte, ich könnte

    Code:
    if (!preg_match("/^(\d+?\w*?\s*?([\wàâæçèéêëîïôœùûÿ\s*?(\-\.)?]{2,})|([\wüäö\s*?(\-\.)?]{2,})\s*?(\d)+?\w*?)$/i", $inputArray['street_address'])) {
    ersetzen durch:

    Code:
    if (!preg_match("/([A-Za-z]+(\d+[A-Za-z]*)+|[A-Za-z]*\d+[A-Za-z]+)[A-Za-z0-9]*/", $inputArray['street_address'])) {
    Da wird aber nicht einmal eine "normale" Adresse ohne Slashes akzeptiert. Kann mir jemand auf die Sprünge helfen? Oder @Christian Mueller kann man auf deine Datenbankerweiterung nicht verzichten?
     
  17. Christian Mueller

    Christian Mueller Beta-Held

    Registriert seit:
    4. Juli 2011
    Beiträge:
    3.198
    Danke erhalten:
    666
    Danke vergeben:
    235
    Die Datenbank enthält Regex für die PLZ-Überprüfung für alle Länder. Nicht für die Straßenüberprüfung.

    Ich habe die Straßen-Hausnummer-Überprüfung einfacher gestaltet.
    Code:
        public function _validateDataByArray(array $inputArray)
        {
    
            /*
             *  Straße/Nr. auf Hausnummer prüfen
             */
             if (reset(array_filter(str_split($inputArray['street_address']), 'ctype_digit')) == '') {
                $this->errorStatus = true;
                $this->errorMessageCollection->setValue('error_street', ENTRY_HOUSE_NUMBER_ERROR);
            }