How can I create a new Joomla user account from within a script?
Asked Answered
J

12

22

We're creating an XML API for Joomla that allows partner sites to create new accounts for their users on our website.

We've created a standalone PHP script that processes and validates the API request, but now we need to actually create the new accounts. We were originally thinking about just doing a CURL call to submit the signup form, but we realized that there is an issue with the user token. Is there another clean way to create a user account without going into the guts of Joomla? If we do have to do some surgery, what is the best way to approach it?

Jamesjamesian answered 15/12, 2009 at 2:7 Comment(0)
L
18

You should use Joomla internal classes, like JUser, since there a lot of internal logic such as password salting. Create a custom script that uses the values from the API request and saves the users in the database using methods from Joomla User Classes.

Two ways to add joomla users using your custom code is a wonderful tutorial. The approach works. I've used this approach in some projects.

If you have to access Joomla Framework outside Joomla, check this resource instead.

Lout answered 15/12, 2009 at 2:26 Comment(1)
broken links. This is why you should always post the code here... :(Cormack
S
15

Based on the answer from waitinforatrain, which is not properly working for logged-in users (actually dangerous if you are using it in the back-end), I have modified it a bit and here it is, fully working for me. Please note that this is for Joomla 2.5.6, while this thread was originally for 1.5, hence the answers above:

function addJoomlaUser($name, $username, $password, $email) {
    jimport('joomla.user.helper');

    $data = array(
        "name"=>$name,
        "username"=>$username,
        "password"=>$password,
        "password2"=>$password,
        "email"=>$email,
        "block"=>0,
        "groups"=>array("1","2")
    );

    $user = new JUser;
    //Write to database
    if(!$user->bind($data)) {
        throw new Exception("Could not bind data. Error: " . $user->getError());
    }
    if (!$user->save()) {
        throw new Exception("Could not save user. Error: " . $user->getError());
    }

    return $user->id;
 }
Sort answered 26/7, 2012 at 10:13 Comment(7)
Thank you for posting this, I really needed to see the best way to do the encrypted password storage... and was to lazy to look at Joomla core code...Gilgamesh
nice, but I am getting an error, Αποτυχία ενημέρωσης επαφής: COM_CONTACT_WARNING_SAME_NAME, βοήθα ! :), and I am checking, the user does not exist before.Farouche
Themi, I don't think I can reply in Greek, due to the site rules, and taking under consideration the fact that these comments are supposed to help other readers. Although, I believe that the issue you face has something to do with the Contact component tables, and possibly about the alias. Have you googled it? Maybe you can contact me at my site, so that we can talk better. (it's exactly the same as my username, plus a .com)Sort
@Sort could you please explain where the " $cpassword " is being used in the function?Bohlen
@wardha-Web I would say that it is used at some secret function somewhere, but I wouldn't convince anyone! :) It seems that part wasn't necessary over there, and I turned it back to just $password in the data array. I can confirm that it works as it is, but it will probably also work if you remove lines 3 to 5. Nice point, thanks!Sort
thanks @mavrosxristoforos, your post helped me for Joomla 3.0. however, it needs modification in order to normally log in to the admin page. the new user should be a member of the 7th Admin group: "groups"=>array("1","2","7")Situated
@Yura.S Indeed, the above code is not supposed to add a user as admin. To do that, you would need to add more groups, as you suggested.Sort
P
7

Just go to documentation page: http://docs.joomla.org/JUser

Also competed sample of single page to register new users in Joomla:

<?php 

function register_user ($email, $password){ 

 $firstname = $email; // generate $firstname
 $lastname = ''; // generate $lastname
 $username = $email; // username is the same as email


 /*
 I handle this code as if it is a snippet of a method or function!!

 First set up some variables/objects     */

 // get the ACL
 $acl =& JFactory::getACL();

 /* get the com_user params */

 jimport('joomla.application.component.helper'); // include libraries/application/component/helper.php
 $usersParams = &JComponentHelper::getParams( 'com_users' ); // load the Params

 // "generate" a new JUser Object
 $user = JFactory::getUser(0); // it's important to set the "0" otherwise your admin user information will be loaded

 $data = array(); // array for all user settings

 // get the default usertype
 $usertype = $usersParams->get( 'new_usertype' );
 if (!$usertype) {
     $usertype = 'Registered';
 }

 // set up the "main" user information

 //original logic of name creation
 //$data['name'] = $firstname.' '.$lastname; // add first- and lastname
 $data['name'] = $firstname.$lastname; // add first- and lastname

 $data['username'] = $username; // add username
 $data['email'] = $email; // add email
 $data['gid'] = $acl->get_group_id( '', $usertype, 'ARO' );  // generate the gid from the usertype

 /* no need to add the usertype, it will be generated automaticaly from the gid */

 $data['password'] = $password; // set the password
 $data['password2'] = $password; // confirm the password
 $data['sendEmail'] = 1; // should the user receive system mails?

 /* Now we can decide, if the user will need an activation */

 $useractivation = $usersParams->get( 'useractivation' ); // in this example, we load the config-setting
 if ($useractivation == 1) { // yeah we want an activation

     jimport('joomla.user.helper'); // include libraries/user/helper.php
     $data['block'] = 1; // block the User
     $data['activation'] =JUtility::getHash( JUserHelper::genRandomPassword() ); // set activation hash (don't forget to send an activation email)

 }
 else { // no we need no activation

     $data['block'] = 1; // don't block the user

 }

 if (!$user->bind($data)) { // now bind the data to the JUser Object, if it not works....

     JError::raiseWarning('', JText::_( $user->getError())); // ...raise an Warning
     return false; // if you're in a method/function return false

 }

 if (!$user->save()) { // if the user is NOT saved...

     JError::raiseWarning('', JText::_( $user->getError())); // ...raise an Warning
     return false; // if you're in a method/function return false

 }

 return $user; // else return the new JUser object

 }

 $email = JRequest::getVar('email');
 $password = JRequest::getVar('password');

 //echo 'User registration...'.'<br/>';
 register_user($email, $password);
 //echo '<br/>'.'User registration is completed'.'<br/>';
?>

Please note that for registration used only email and password.

The sample of call: localhost/joomla/[email protected]&password=pass or just create simple form with appropriate parameters

Pemberton answered 18/11, 2010 at 8:13 Comment(3)
$data['block'] = 1; // don't block the user, it should be $data['block'] = 0;Pebrook
@Pemberton it's very late for me to comment. Will this send the joomla core activation email? Also will this obey joomla user plugin hooks like before after save?Crumble
How is the code even working? You are not including the core functionality.Manuscript
W
2

http://joomlaportal.ru/content/view/1381/68/

INSERT INTO jos_users( `name`, `username`, `password`, `email`, `usertype`, `gid` )
VALUES( 'Иванов Иван', 'ivanov', md5('12345'), '[email protected]', 'Registered', 18 );

INSERT INTO jos_core_acl_aro( `section_value`, `value` )
VALUES ( 'users', LAST_INSERT_ID() );

INSERT INTO jos_core_acl_groups_aro_map( `group_id`, `aro_id` )
VALUES ( 18, LAST_INSERT_ID() );
Wolenik answered 13/5, 2011 at 4:32 Comment(0)
S
2

Tested and working on 2.5.

function addJoomlaUser($name, $username, $password, $email) {
        $data = array(
            "name"=>$name, 
            "username"=>$username, 
            "password"=>$password,
            "password2"=>$password,
            "email"=>$email
        );

        $user = clone(JFactory::getUser());
        //Write to database
        if(!$user->bind($data)) {
            throw new Exception("Could not bind data. Error: " . $user->getError());
        }
        if (!$user->save()) {
            throw new Exception("Could not save user. Error: " . $user->getError());
        }

        return $user->id;
}

If you're outside the Joomla environment, you'll have to do this first, or if you're not writing a component, use the one in the link in @GMonC's answer.

<?php
if (! defined('_JEXEC'))
    define('_JEXEC', 1);
$DS=DIRECTORY_SEPARATOR;
define('DS', $DS);

//Get component path
preg_match("/\\{$DS}components\\{$DS}com_.*?\\{$DS}/", __FILE__, $matches, PREG_OFFSET_CAPTURE);
$component_path = substr(__FILE__, 0, strlen($matches[0][0]) + $matches[0][1]);
define('JPATH_COMPONENT', $component_path);

define('JPATH_BASE', substr(__FILE__, 0, strpos(__FILE__, DS.'components'.DS) ));
require_once ( JPATH_BASE .DS.'includes'.DS.'defines.php' );
require_once JPATH_BASE .DS.'includes'.DS.'framework.php';
jimport( 'joomla.environment.request' );
$mainframe =& JFactory::getApplication('site');
$mainframe->initialise();

I use this for unit testing my component.

Sparks answered 21/5, 2012 at 3:5 Comment(2)
Thanks, this helped me. One question: why $user = clone(JFactory::getUser()); instead of just $user = new JUser();?Gunboat
@Gunboat I don't recall why I did it that way. Does new JUser(); work? If so that would be a better solution.Sparks
M
2

Another smart way would be to use the actual /component/com_users/models/registration.php class method called register since it will take care of everything really.

First you add these methods to your helper class

/**
*   Get any component's model
**/
public static function getModel($name, $path = JPATH_COMPONENT_ADMINISTRATOR, $component = 'yourcomponentname')
{
    // load some joomla helpers
    JLoader::import('joomla.application.component.model'); 
    // load the model file
    JLoader::import( $name, $path . '/models' );
    // return instance
    return JModelLegacy::getInstance( $name, $component.'Model' );
}   

/**
*   Random Key
*
*   @returns a string
**/
public static function randomkey($size)
{
    $bag = "abcefghijknopqrstuwxyzABCDDEFGHIJKLLMMNOPQRSTUVVWXYZabcddefghijkllmmnopqrstuvvwxyzABCEFGHIJKNOPQRSTUWXYZ";
    $key = array();
    $bagsize = strlen($bag) - 1;
    for ($i = 0; $i < $size; $i++)
    {
        $get = rand(0, $bagsize);
        $key[] = $bag[$get];
    }
    return implode($key);
}  

Then you add the following user create method also to you component helper class

/**
* Greate user and update given table
*/
public static function createUser($new)
{
    // load the user component language files if there is an error
    $lang = JFactory::getLanguage();
    $extension = 'com_users';
    $base_dir = JPATH_SITE;
    $language_tag = 'en-GB';
    $reload = true;
    $lang->load($extension, $base_dir, $language_tag, $reload);
    // load the user regestration model
    $model = self::getModel('registration', JPATH_ROOT. '/components/com_users', 'Users');
    // set password
    $password = self::randomkey(8);
    // linup new user data
    $data = array(
        'username' => $new['username'],
        'name' => $new['name'],
        'email1' => $new['email'],
        'password1' => $password, // First password field
        'password2' => $password, // Confirm password field
        'block' => 0 );
    // register the new user
    $userId = $model->register($data);
    // if user is created
    if ($userId > 0)
    {
        return $userId;
    }
    return $model->getError();
}

Then anywhere in your component you can create a user like this

// setup new user array
$newUser = array(
    'username' => $validData['username'], 
    'name' => $validData['name'], 
    'email' => $validData['email']
    );
$userId = yourcomponentnameHelper::createUser($newUser); 
if (!is_int($userId))
{
    $this->setMessage($userId, 'error');
}

Doing it this way saves you all the trouble of handling the emails that needs to be send, since it automatically will use the system defaults. Hope this helps someone :)

Meanly answered 17/8, 2015 at 1:7 Comment(0)
A
2

I have made an ajax call and then just passing the variables to this script and it worked for me.

define('_JEXEC', 1);
define('JPATH_BASE', __DIR__);
define('DS', DIRECTORY_SEPARATOR);

/* Required Files */
require_once(JPATH_BASE . DS . 'includes' . DS . 'defines.php');
require_once(JPATH_BASE . DS . 'includes' . DS . 'framework.php');
$app = JFactory::getApplication('site');
$app->initialise();

require_once(JPATH_BASE . DS . 'components' . DS . 'com_users' . DS . 'models' . DS . 'registration.php');

$model = new UsersModelRegistration();

jimport('joomla.mail.helper');
jimport('joomla.user.helper');
$language = JFactory::getLanguage();
$language->load('com_users', JPATH_SITE);
$type       = 0;
$username   = JRequest::getVar('username');
$password   = JRequest::getVar('password');
$name       = JRequest::getVar('name');
$mobile     = JRequest::getVar('mobile');
$email      = JRequest::getVar('email');
$alias      = strtr($name, array(' ' => '-'));
$sendEmail  = 1;
$activation = 0;

$data       = array('username'   => $username,
            'name'       => $name,
            'email1'     => $email,
            'password1'  => $password, // First password field
            'password2'  => $password, // Confirm password field
            'sendEmail'  => $sendEmail,
            'activation' => $activation,
            'block'      => "0", 
            'mobile'     => $mobile,
            'groups'     => array("2", "10"));
$response   = $model->register($data);

echo $data['name'] . " saved!";
$model->register($data);

Only user is not getting activated automatically. I am passing 'block' => "0" for activating user but it is not working :( But rest of the code works fine.

Arp answered 21/1, 2016 at 10:32 Comment(0)
S
1

Update: oh I ddin't see you wanted 1.5 but you could do similar but wth the 1.5 API instead.

This is part of something I was usng for anther purpose but you would need to use the default group instead until an issue with using JUserHelper from the command line is fixed or make it a web application.

<?php
/**
 *
 * @copyright  Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 */

if (!defined('_JEXEC'))
{
    // Initialize Joomla framework
    define('_JEXEC', 1);
}

@ini_set('zend.ze1_compatibility_mode', '0');
error_reporting(E_ALL);
ini_set('display_errors', 1);

// Load system defines
if (file_exists(dirname(__DIR__) . '/defines.php'))
{
    require_once dirname(__DIR__) . '/defines.php';
}

if (!defined('JPATH_BASE'))
{
    define('JPATH_BASE', dirname(__DIR__));
}

if (!defined('_JDEFINES'))
{
    require_once JPATH_BASE . '/includes/defines.php';
}

// Get the framework.
require_once JPATH_LIBRARIES . '/import.php';


/**
 * Add user
 *
 * @package  Joomla.Shell
 *
 * @since    1.0
 */
class Adduser extends JApplicationCli
{
    /**
     * Entry point for the script
     *
     * @return  void
     *
     * @since   1.0
     */
    public function doExecute()
    {
        // username, name, email, groups are required values.
        // password is optional
        // Groups is the array of groups

        // Long args
        $username = $this->input->get('username', null,'STRING');
        $name = $this->input->get('name');
        $email = $this->input->get('email', '', 'EMAIL');
        $groups = $this->input->get('groups', null, 'STRING');

        // Short args
        if (!$username)
        {
            $username = $this->input->get('u', null, 'STRING');
        }
        if (!$name)
        {
            $name = $this->input->get('n');
        }
        if (!$email)
        {
            $email = $this->input->get('e', null, 'EMAIL');
        }
        if (!$groups)
        {
            $groups = $this->input->get('g', null, 'STRING');
        }

        $user = new JUser();

        $array = array();
        $array['username'] = $username;
        $array['name'] = $name;
        $array['email'] = $email;

        $user->bind($array);
        $user->save();

        $grouparray = explode(',', $groups);
        JUserHelper::setUserGroups($user->id, $grouparray);
        foreach ($grouparray as $groupId)
        {
            JUserHelper::addUserToGroup($user->id, $groupId);
        }

        $this->out('User Created');

        $this->out();
    }

}

if (!defined('JSHELL'))
{
    JApplicationCli::getInstance('Adduser')->execute();
}
Scrivings answered 26/12, 2012 at 23:16 Comment(5)
Thanks this was helpful for 2.5. The groups code is not working for me but I'll keep trying I think it is because my group has the name "Foo Bar" with spaces. I'll keep playing with it. Any other insight would be helpful.Gunboat
Oh you know what, I forgot that I have a pull request in to fix a bug with creating the groups.Scrivings
And that pull request was recently merged and will be in 3.1.Scrivings
@Scrivings I need to import a bunch of users from a csv file and would like to use your code here. But when I tried in Joomla 3.3.6, I got error like 'Error displaying the error page: Application Instantiation Error: Access Usergroup Invalid'. I appreciate it if you can update your code to used with Joomla3.3.x. thanks Elin.Gilbreath
Are you sure that the user group you are sending them to exists? Are you able to run other CLI applications? (try the garbage collecting one in the cli folder). I googled your error message and it seems like that happens if you have a third party user plugin installed. Can you please check that? If so you could temporarily disable it or else amend my code to disable it for the CLI.Scrivings
V
1

In my case (Joomla 3.4.3) the user was added to the session, so there was a buggy behaviour when trying to activate the account.

Just add this line, after $user->save():

JFactory::getSession()->clear('user', "default");

This will remove the newly created user from the session.

Virendra answered 3/8, 2015 at 12:14 Comment(0)
H
0

there is one module called "login module" you can use that module and display it in one of the menu.. in which u will get one link like "new user?" or "create an account" just click on it you will get one registration page with validation..this is just 3-step process to use registration page...it may be helpful to get result faster!!..thanx

Halicarnassus answered 2/2, 2011 at 12:28 Comment(0)
P
0

This won't work in joomla 1.6 as ACL are handled in another way... In the end is even simpler, you mandatory need to add an entry on the "jos_user_usergroup_map" table (further then the "jos_users" table) to declare at least one group for each user...

Preschool answered 26/4, 2011 at 14:9 Comment(1)
The configuration includes a default user group for new users. That's what you should use or override if you want something different.Scrivings
B
0

Valid for Joomla 3.9.xx If you are working with a separate 3rd party MySQL DB (other that the current DB that Joomla is running in), then you can use the following SQl. Its a bit crude but will get the job of "creating users" done.

INSERT INTO `datph_users` (`id`, `name`, `username`, `email`, `password`, `block`, `sendEmail`, `registerDate`, `lastvisitDate`, `activation`, `params`, `lastResetTime`, `resetCount`, `otpKey`, `otep`, `requireReset`)  VALUES (NULL, 'New Super User', 'newsuperuser', '[email protected]', MD5('newsuperuser'), '0', '1', '2019-09-03 11:59:51', '2020-09-15 15:01:28', '0', '{\"update_cache_list\":1,\"admin_style\":\"\",\"admin_language\":\"\",\"language\":\"\",\"editor\":\"\",\"helpsite\":\"\",\"timezone\":\"\"}', '0000-00-00 00:00:00', '0', '', '', '1');
INSERT INTO `datph_user_usergroup_map` (`user_id`, `group_id`) VALUES (LAST_INSERT_ID(), '8');
  • These are the bare basic necessary details required to have a "user" in Joomla. Remember to update the respective field values accordingly
  • This query will make the CMS ask the user to update the password on first login so its safe in terms of salt and stuff
  • The User Group is set to Super Administrator , you can set to what ever you wish to register the user to.
Bohlen answered 16/9, 2020 at 16:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.