Creating extra Street Address Fields

Open to all! Ask other shopowners for help.
Post Reply
User avatar
Portman
Contributor
Posts: 158
Joined: Mon Mar 08, 2021 1:04 am
Phoenix Version: v1.0.8.20
Has thanked: 29 times
Been thanked: 4 times

Creating extra Street Address Fields

Post by Portman »

Hi,

I'm working on version 1.1.0.4

I am trying to create 2 extra street address fields for my site (entry_street_address_2 & entry_street_address_3)

I have created clones of cd_street_address.php for each and have created a new cd_modified_address.php - which is just a copy of the cd_traditional_address with the extra fields added.

A new customer can add the details no problem.
THe issues arise on editing existing addresses and creating additional addresses...

When an address is edited - it seems to update the database, but I then get an error
when I add an additional address it does not update the database and i get a very similar error

Error for update;

Code: Select all

PHP Warning:  Undefined array key "customers" in .../includes/system/versioned/1.01.00.00/customer_write.php on line 85
PHP Warning:  foreach() argument must be of type array|object, null given in .../includes/system/versioned/1.01.00.00/query.php on line 142
PHP Fatal error:  Uncaught mysqli_sql_exception: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 in .../includes/system/versioned/1.0.8.1/database_core.php:67
Stack trace:
#0 .../includes/system/versioned/1.0.8.1/database_core.php(67): mysqli->query('UPDATE customer...', 0)
#1 .../includes/system/versioned/1.0.8.1/database_core.php(119): database_core->query('UPDATE customer...')
#2 .../includes/system/versioned/1.01.00.00/customer_write.php(85): database_core->perform('customers', Array, 'update', '')
#3 .../includes/system/versioned/1.0.5.1/customer_data.php(183): customer_write::update(Array, Array)
#4 .../address_book_process.php(48): customer_data->update(Array, Array, 'address_book')
#5 {main}
  thrown in .../includes/system/versioned/1.0.8.1/database_core.php on line 67
Error for additional address;

Code: Select all

PHP Fatal error:  Uncaught mysqli_sql_exception: Duplicate entry '' for key 'uq_customers_email_address' in .../includes/system/versioned/1.0.8.1/database_core.php:67
Stack trace:
#0 .../includes/system/versioned/1.0.8.1/database_core.php(67): mysqli->query('INSERT INTO cus...', 0)
#1 .../includes/system/versioned/1.0.8.1/database_core.php(119): database_core->query('INSERT INTO cus...')
#2 .../includes/system/versioned/1.01.00.00/customer_write.php(39): database_core->perform('customers', Array)
#3 .../includes/system/versioned/1.0.5.1/customer_data.php(167): customer_write::create(Array, Array)
#4 .../address_book_process.php(57): customer_data->add_address(Array)
#5 {main}
  thrown in .../includes/system/versioned/1.0.8.1/database_core.php on line 67
Obviously there is more I need to do to get this to work, could someone fill me in on what that is?

Thanks


Join The Code Co-op to get access to your library in the Code Co-op Forum
frankl
Builder
Posts: 159
Joined: Tue Feb 23, 2021 8:39 pm
Phoenix Version: v1.1.0.4
Has thanked: 17 times
Been thanked: 25 times

Re: Creating extra Street Address Fields

Post by frankl »

Looks like an error here:

Code: Select all

mysqli->query('UPDATE customer...', 0)
Is the customer_id being passed? Post the whole code and it can be checked.
User avatar
Portman
Contributor
Posts: 158
Joined: Mon Mar 08, 2021 1:04 am
Phoenix Version: v1.0.8.20
Has thanked: 29 times
Been thanked: 4 times

Re: Creating extra Street Address Fields

Post by Portman »

Hi @frankl

Im not sure which code you want me to post, so here is cd_street_address_2.php

Code: Select all

  class cd_street_address_2 extends abstract_customer_data_module {

    const CONFIG_KEY_BASE = 'MODULE_CUSTOMER_DATA_STREET_ADDRESS_2_';

    const PROVIDES = [ 'street_address_2' ];
    const REQUIRES = [  ];

    protected function get_parameters() {
      return [
        static::CONFIG_KEY_BASE . 'STATUS' => [
          'title' => 'Enable Street Address 2 module',
          'value' => 'True',
          'desc' => 'Do you want to add the module to your shop?',
          'set_func' => "Config::select_one(['True', 'False'], ",
        ],
        static::CONFIG_KEY_BASE . 'GROUP' => [
          'title' => 'Customer data group',
          'value' => '2',
          'desc' => 'In what group should this appear?',
          'use_func' => 'customer_data_group::fetch_name',
          'set_func' => 'Config::select_customer_data_group(',
        ],
        static::CONFIG_KEY_BASE . 'REQUIRED' => [
          'title' => 'Require Street Address 2 module (if enabled)',
          'value' => 'True',
          'desc' => 'Do you want the street address 2 to be required in customer registration?',
          'set_func' => "Config::select_one(['True', 'False'], ",
        ],
        static::CONFIG_KEY_BASE . 'MIN_LENGTH' => [
          'title' => 'Minimum Length',
          'value' => '3',
          'desc' => 'Minimum length of street address',
        ],
        static::CONFIG_KEY_BASE . 'PAGES' => [
          'title' => 'Pages',
          'value' => 'address_book;checkout_new_address;create_account;customers',
          'desc' => 'On what pages should this appear?',
          'set_func' => 'Customers::select_pages(',
          'use_func' => 'abstract_module::list_exploded',
        ],
        static::CONFIG_KEY_BASE . 'SORT_ORDER' => [
          'title' => 'Sort Order',
          'value' => '4210',
          'desc' => 'Sort order of display. Lowest is displayed first.',
        ],
        static::CONFIG_KEY_BASE . 'TEMPLATE' => [
          'title' => 'Template',
          'value' => 'includes/modules/customer_data/cd_whole_row_input.php',
          'desc' => 'What template should be used to surround this input?',
        ],
      ];
    }

    public function get($field, &$customer_details) {
      switch ($field) {
        case 'street_address_2':
          if (!isset($customer_details[$field])) {
            $customer_details[$field] = $customer_details['street_address_2']
              ?? $customer_details['entry_street_address_2'] ?? null;
          }
          return $customer_details[$field];
      }
    }

    public function display_input($customer_details = null) {
      $label_text = ENTRY_STREET_ADDRESS_2;
      $input_id = 'inputStreetAddress';

      $input = new Input('street_address_2', [
        'id' => $input_id,
        'autocomplete' => 'address-line1',
        'placeholder' => ENTRY_STREET_ADDRESS_2_TEXT,
        'minlength' => $this->base_constant('MIN_LENGTH'),
      ]);

      if ($customer_details && is_array($customer_details)) {
        $input->set('value', $this->get('street_address_2', $customer_details));
      }

      if ($this->is_required()) {
        $input->require();
        $input .= FORM_REQUIRED_INPUT;
      }

      include Guarantor::ensure_global('Template')->map($this->base_constant('TEMPLATE'));
    }

    public function process(&$customer_details) {
      $customer_details['street_address_2'] = Text::input($_POST['street_address_2']);

      if ((strlen($customer_details['street_address_2']) < $this->base_constant('MIN_LENGTH'))
        && $this->is_required()
        )
      {
        $GLOBALS['messageStack']->add_classed(
          $GLOBALS['message_stack_area'] ?? 'customer_data',
          sprintf(ENTRY_STREET_ADDRESS_2_ERROR, $this->base_constant('MIN_LENGTH')));

        return false;
      }

      return true;
    }

    public function build_db_values(&$db_tables, $customer_details, $table = 'both') {
      Guarantor::guarantee_subarray($db_tables, 'address_book');
      $db_tables['address_book']['entry_street_address_2'] = $customer_details['street_address_2'];
    }

    public function build_db_aliases(&$db_tables, $table = 'both') {
      Guarantor::guarantee_subarray($db_tables, 'address_book');
      $db_tables['address_book']['entry_street_address_2'] = 'street_address_2';
    }

  }
cd_street_address_3 is identical but with 3 in all of the relevant variable names instead of 2

here is cd_modified_address.php

Code: Select all

 class cd_modified_address extends abstract_module {

    const CONFIG_KEY_BASE = 'MODULE_CUSTOMER_DATA_MODIFIED_ADDRESS_';

    const PROVIDES = [ 'address' ];
    const REQUIRES = [ 'name', 'street_address', 'street_address_2', 'street_address_3', 'postcode', 'city', 'country' ];
    const FIELDS = [ 'name', 'street_address', 'street_address_2', 'street_address_3', 'postcode', 'city', 'country_id', 'company', 'suburb', 'state' ];

    private $active_fields;

    protected function get_parameters() {
      return [
        static::CONFIG_KEY_BASE . 'STATUS' => [
          'title' => 'Enable Address module - Modified for CA',
          'value' => 'True',
          'desc' => 'Do you want to add the module to your shop?',
          'set_func' => "Config::select_one(['True', 'False'], ",
        ],
      ];
    }

    public function get($field, &$customer_details) {
      switch ($field) {
        case 'address':
          if (!isset($customer_details[$field])) {
            $customer_details[$field] = array_combine(
              $this->get_fields(),
              array_map(
                function ($v) use (&$customer_details) {
                  return $GLOBALS['customer_data']->get($v, $customer_details);
                },
                $this->get_fields()
              )
            );
          }

          return $customer_details[$field];
      }
    }

    public function process(&$customer_details) {
      $results = $GLOBALS['customer_data']->process($this->get_fields());
      $customer_details = array_merge($customer_details, $results);

      return !empty($results);
    }

    public function get_fields() {
      if (is_null($this->active_fields)) {
        global $customer_data;

        $customer_data->has(self::FIELDS);
        $this->active_fields = array_diff(self::FIELDS, $customer_data->get_last_missing_abilities());
      }

      return $this->active_fields;
    }

    public function get_purveyors() {
      return array_map([$GLOBALS['customer_data'], 'get_module'], $this->get_fields());
    }

    public function build_db_values(&$db_tables, $customer_details, $table = 'both') {
      foreach ($this->get_purveyors() as $purveyor) {
        $purveyor->build_db_values($db_tables, $customer_details, $table);
      }
    }

    public function build_db_aliases(&$db_tables, $table = 'both') {
      foreach ($this->get_purveyors() as $purveyor) {
        $purveyor->build_db_aliases($db_tables, $table);
      }
    }

    function format($address, $html, $boln, $eoln) {
      $address_format_id = $address['format_id'] ?? $address['address_format_id'] ?? $this->get_address_format_id($address['country_id'] ?? $address['country']['id'] ?? null);
      $address_format = $GLOBALS['db']->query("SELECT address_format AS format FROM address_format WHERE address_format_id = " . (int)$address_format_id)->fetch_assoc();

      $company = htmlspecialchars($address['company'] ?? '');
      $name = htmlspecialchars($GLOBALS['customer_data']->get('name', $address) ?? '');

      $street = htmlspecialchars($address['street_address']);
      $street_2 = htmlspecialchars($address['street_address_2'] ?? '');
	  $street_3 = htmlspecialchars($address['street_address_3'] ?? '');
      $suburb = htmlspecialchars($address['suburb'] ?? '');
      $city = htmlspecialchars($address['city']);
      $state = htmlspecialchars($address['state'] ?? '');
      if (!empty($address['country_id'])) {
        $country = Country::fetch_name($address['country_id']);

        if (!empty($address['zone_id'])) {
          $state = Zone::fetch_code($address['zone_id'], $address['country_id'], $state);
        }
      } elseif (!empty($address['country']) && is_array($address['country'])) {
        $country = htmlspecialchars($address['country']['title']);
      } else {
        $country = '';
      }
      $postcode = htmlspecialchars($address['postcode']);
      $zip = $postcode;

      if ($html) {
        // HTML Mode
        $HR = '<hr>';
        $hr = '<hr>';
        if ( ($boln == '') && ($eoln == "\n") ) { // Values not specified, use rational defaults
          $CR = '<br>';
          $cr = '<br>';
          $eoln = $cr;
        } else { // Use values supplied
          $CR = $eoln . $boln;
          $cr = $CR;
        }
      } else {
        // Text Mode
        $CR = $eoln;
        $cr = $CR;
        $HR = '----------------------------------------';
        $hr = '----------------------------------------';
      }

      $statecomma = '';
      $streets = $street;
	  if ('' != $street_2) {
        $streets .= $cr . $street_2;
      }
	  if ('' != $street_3) {
        $streets .= $cr . $street_3;
      }
      if ('' != $suburb) {
        $streets .= $cr . $suburb;
      }
      if ('' != $state) {
        $statecomma = $state . ', ';
      }

      $fmt = $address_format['format'];
      eval("\$address = \"$fmt\";");

      if (!empty($company)) {
        $address = $company . $cr . $address;
      }

      return $address;
    }

    function get_address_format_id($country_id) {
      $address_format = $GLOBALS['db']->query("SELECT address_format_id AS format_id FROM countries WHERE countries_id = " . (int)$country_id)->fetch_assoc();

      return $address_format['format_id'] ?? '1';
    }

  }
I hope that helps
ecartz
Core Team
Posts: 3084
Joined: Tue Nov 05, 2019 6:02 pm
Phoenix Version:
Has thanked: 4 times
Been thanked: 208 times

Re: Creating extra Street Address Fields

Post by ecartz »

I doubt the problem is in the code you changed for this. Did you change anything else? Note that it is complaining that it is trying to insert a blank email into the customers table. Why? It's not clear. If you are editing an address, it should not try to modify the customers table at all.

Two possible problems:

1. You're missing the customer ID on the edit address page.
2. You have some field in customers on the edit address page. Perhaps customers_email_address or customers_telephone.

If you make a new vanilla test store and put only your street address changes in it, does it work? If so, it must be some other change that's causing the problem.
User avatar
Portman
Contributor
Posts: 158
Joined: Mon Mar 08, 2021 1:04 am
Phoenix Version: v1.0.8.20
Has thanked: 29 times
Been thanked: 4 times

Re: Creating extra Street Address Fields

Post by Portman »

thanks @ecartz ,

Yes I had some cusomer details listed on the address edit page - thanks for this I would have never picked that up!


Join The Code Co-op to get access to your library in the Code Co-op Forum
Post Reply