问题
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?
回答1:
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.
回答2:
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;
}
回答3:
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/test-reg-user-php?email=test02@test.com&password=pass or just create simple form with appropriate parameters
回答4:
http://joomlaportal.ru/content/view/1381/68/
INSERT INTO jos_users( `name`, `username`, `password`, `email`, `usertype`, `gid` )
VALUES( 'Иванов Иван', 'ivanov', md5('12345'), 'ivanov@mail.ru', '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() );
回答5:
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.
回答6:
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 :)
回答7:
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();
}
回答8:
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.
回答9:
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
回答10:
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...
回答11:
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.
来源:https://stackoverflow.com/questions/1904809/how-can-i-create-a-new-joomla-user-account-from-within-a-script