Creating address for newly created user

  • Posts: 32
  • Thank you received: 5
11 months 1 week ago #358097

-- HikaShop version -- : 5.0.2
-- Joomla version -- : 4.4.1
-- PHP version -- : 8.1.26
-- Browser(s) name and version -- : Firefox 121.0 (64-bit)

Hi,

I made a scheduled task plugin that regularly checks a file and automatically creates new users if needed.

Now, I also need to create HikaShop addresses for these users and I am a bit lost.

I've noticed that HikaShop users are automatically created once Joomla users are created.

So my logic would be this:
1) Get the Hika user by email
2) Create new address using the information from my list
3) Add new address to user

I've gotten as far as including HikaShop's main files and loading the 'user' and 'address' classes.

Sadly, I can't find an overview of which functions I can work with to make the above happen. Where can I find documentation of these classes/Which functions should I use?

Thanks in advance!

Please Log in or Create an account to join the conversation.

  • Posts: 83022
  • Thank you received: 13403
  • MODERATOR
11 months 1 week ago #358099

Hi,

To get the user based on the email, you can do like this:

$user = $userClass->get($email_address, 'email');

To create a new address, you can do like this:
$address = new stdClass();
$address->address_user_id = $user->user_id;
$address->address_type = 'billing';
$address->address_published = 1;
$address->address_firstname = $firstname;
$address->address_lastname = $lastname;
...
$addressClass->save($address);

Note also that in address_state and address_country, you need to provide the namekey of the zone in the hikashop_zone table.
For example:
$country = "france";
$zoneClass = hikashop_get('class.zone');
$country_zone = $zoneClass->getZones(array($country), '*', 'zone_name_english', true);
$address->address_country = $country_zone['zone_namekey'];

You can infer this from looking directly at the code of the classes in the files of the folder administrator/components/com_hikashop/classes/
When you do hikashop_get('class.product') it basically returns you an object of the class in the file product.php of that folder.
The point of using hikashop_get instead of a require is that it's shorter to write, and it also handles dynamic overrides of the classes.

The following user(s) said Thank You: NTV

Please Log in or Create an account to join the conversation.

  • Posts: 32
  • Thank you received: 5
11 months 1 week ago #358127

Hi nicolas,

got it to work - many thanks!

Some things I had to change.

The value of $address_country is supposed to look like this: 'country_Germany_81'.

Since my input values are in german I have to use 'zone_name' as a key instead of 'zone_name_english'. Thankfully, my HikaShop installation is either smart enough or german as well, since this returns the right zone:

$zone_id = $zoneClass->getZones(array($user_data['country']), 'zone_id', 'zone_name', true);
$zone_name_english = $zoneClass->getZones(array($user_data['country']), 'zone_name_english', 'zone_name', true);
$address_country = 'country';
$address_country .= '_' . $zone_name_english[0];
$address_country .= '_' . $zone_id[0];

Two things I'm not quite happy with.
1) I'd rather have only one database call. But calling getZones() with two columns (or '*' as you put it) seems to return only the zone_id. I also tried setting $returnArrayWithOneColumn to false, but I'm guessing that is for something else.
2) Do I need to do that string formatting for $address_country myself or is there a HikaShop function that already does it (if I give it the zone_id for example)?

Please Log in or Create an account to join the conversation.

  • Posts: 83022
  • Thank you received: 13403
  • MODERATOR
11 months 1 week ago #358128

Hi,

1. You can set returnArrayWithOneColumn to false. In that case, you'll get an object and you can do:
$returnedObject->zone_namekey
to access the attributes.

2. The zone_namekey column should already contain the string formatted like you want. That's why I provided the code which uses the zone_namekey from the database.

The following user(s) said Thank You: NTV

Please Log in or Create an account to join the conversation.

  • Posts: 32
  • Thank you received: 5
11 months 1 week ago #358152

Hi,

you might laugh, but what tripped me up was that getZones() returns an array, so I simply had to do this:

$zones = $zoneClass->getZones(array($user_data['country']), 'zone_namekey', 'zone_name', true);
$address->address_country = $zones[0];

In conclusion: print_r() and logging is your friend.

Thanks again, you've been a great help as always.

The following user(s) said Thank You: nicolas

Please Log in or Create an account to join the conversation.

  • Posts: 32
  • Thank you received: 5
2 months 3 weeks ago #363503

Hi,

I've had to return to work on this because there are issues with finding the zone.

This line works:
$zoneClass->getZones(array('Switzerland'), 'zone_namekey', 'zone_name_english', true);
(Returns an array with one value: 'country_Switzerland_204')

This one doesn't:
$zoneClass->getZones(array('Schweiz'), 'zone_namekey', 'zone_name', true);
(Returns an empty array)

Shouldn't the german country name 'Schweiz' work in this case?

Please Log in or Create an account to join the conversation.

  • Posts: 83022
  • Thank you received: 13403
  • MODERATOR
2 months 3 weeks ago #363505

Hi,

The getZones function expects you to provide the exact value. However, the value for the zone_name for Switzerland is not "Schweiz", it's "Schweiz • Suisse • Svizzera • Svizra" by default.
If you need it to work with a more complex search, I would recommend running your own MySQL query instead of calling getZones:

$db = JFactory::getDBO();
$query = 'SELECT zone_namekey FROM #__hikashop_zone WHERE zone_name LIKE \'%Schweiz%\'';
$db->setQuery($query);
$zone_namekey = $this->database->loadColumn();

The following user(s) said Thank You: NTV

Please Log in or Create an account to join the conversation.

  • Posts: 32
  • Thank you received: 5
2 months 3 weeks ago #363608

Hi nicolas,

thanks for your reply. I had to change the last line to this, but then it worked:

$zone_namekey = $db->loadColumn();

I have previously used this syntax for SQL queries:

$query = $db->getQuery(true)
->select($db->quoteName('id'))
->from($db->quoteName('#__users'))
->where($db->quoteName('email') . ' = ' . $db->quote($user_data));
$db->setQuery($query);
$id = $db->loadResult();

Which is better?

Please Log in or Create an account to join the conversation.

  • Posts: 83022
  • Thank you received: 13403
  • MODERATOR
2 months 3 weeks ago #363610

Hi,

Yes. Sorry for the mistake on my copy/paste.

For your last question, the short answer is "it depends, but it doesn't matter much".
Using Joomla's functions to construct the MySQL queries allows your code to run on all the SQL drivers offered by Joomla. So, if Joomla supports Oracle's database engine in the future, your queries will work the same. In HikaShop we don't, and so HkaShop can only work on MySQL. In practice, 99% of the websites made with Joomla are made with MySQL so there is little incentive for us to spend months rewriting the queries in HikaShop with Joomla's functions.
Also, since the query is constructed by Joomla, it potentially reduce the probability that you forget to secure your SQL queries against SQL injection attacks (with calls to quote, quoteName, etc)
On the other side, the functions are limited in their capabilities. Some SQL functions which are specific to MySQL / MariaDB won't be supported, or not supported for all the SQL drivers. So it might constrain you. For example, with the filter system, or the report system, or export/import, we sometimes have to run complex MySQL queries which can't be done with the Joomla functions.
Also, suppose you hire a developer to help you with your work. You'll hire a PHP developer. It's highly likely he'll know how to write MySQL queries. So he will be familiar with the code I posted and will be able to read and write the queries faster than if the code uses Joomla functions.
HikaShop is meant to be used by people with no programming knowledge, and if they do, we want to make it as easy as possible for them to read our code. So we decided to keep writing MySQL queries the normal way. But both ways are ok in most cases.

The following user(s) said Thank You: NTV

Please Log in or Create an account to join the conversation.

Time to create page: 0.068 seconds
Powered by Kunena Forum