extending JUser

For Joomla! 1.5 Coding related discussions, please use: http://groups.google.com/group/joomla-dev-general
Forum rules
Please use the mailing list here: http://groups.google.com/group/joomla-dev-general rather than this forum.
Locked
VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

extending JUser

Post by VisiGod » Tue May 19, 2009 9:37 pm

I'm developing a component that needs to have new fields in the #__user table. I can't use another table since the component relies on an external program that reads from that db.

I've checked the topic "Extending JModel" (http://forum.joomla.org/viewtopic.php?f=304&t=379139) but I think that I need a different approach.

My question is: How can I extend the JUser object and add it more variables so that on a later stage I can do a JFactory::getUser() and get my new fields loaded?

Any examples would be appreciated.

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Thu May 21, 2009 1:42 pm

Anyone? I know that we can extend the JModel and use it's functions inside our own class, but what about the JUser?

User avatar
ianmac
Joomla! Virtuoso
Joomla! Virtuoso
Posts: 4784
Joined: Sat Sep 24, 2005 11:01 pm
Location: Toronto, Canada

Re: extending JUser

Post by ianmac » Thu May 21, 2009 2:13 pm

VisiGod wrote:Anyone? I know that we can extend the JModel and use it's functions inside our own class, but what about the JUser?
Please don't bump threads.

Anyway, look at:
http://forum.joomla.org/viewtopic.php?f=476&t=213754

Intrigued as to why you *have* to have the fields in the same table?

Ian

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Thu May 21, 2009 2:27 pm

Thanks for the reply Ian but I don't want to extend the parameters, I want to extend the table fields (I cannot fetch information from the user->parameters fields).

I need to *have" custom fields to integrate an external program (binary program, not code based) that reads from a user table with certain columns.

Extending the #__users table was the most reasonable way I've found. I can also add another table that replicates some info from the user table but why have 2 tables with the same info when I can have only one ? :)

User avatar
ianmac
Joomla! Virtuoso
Joomla! Virtuoso
Posts: 4784
Joined: Sat Sep 24, 2005 11:01 pm
Location: Toronto, Canada

Re: extending JUser

Post by ianmac » Thu May 21, 2009 2:56 pm

VisiGod wrote:Thanks for the reply Ian but I don't want to extend the parameters, I want to extend the table fields (I cannot fetch information from the user->parameters fields).

I need to *have" custom fields to integrate an external program (binary program, not code based) that reads from a user table with certain columns.

Extending the #__users table was the most reasonable way I've found. I can also add another table that replicates some info from the user table but why have 2 tables with the same info when I can have only one ? :)
Yes, there was information at the link I provided on adding table fields, though the immediate topic was parameters.
A quick hint how this should be used :

1. create a extended user database table, either by adding fields to the existing table or by create a new table and using the user_id to create a relationship

2. create an extended JTableUser class, that either uses joins or subqueries to work with the extra table or that is capable of handling the fields added to the existing table.

3. user JUser::getTable either statically or dynamically and feed it the name of you new user table class. Like

Code:
JUser::getTable('tablename');


4. in case the new user table class is not in joomla.database.table, you will need to tell JTable where to find it using JTable::addIncludePath.

Use cases :

The changes allow you to create a thicker JUser object that can be used in your code. You can choose to either only expose it to your own component by doing the above last two steps only for you component. Or you could create a system plugin which set the database table name and exposed your extended JUser object to the whole system.
Anyway, so you're stuck with a proprietary system and have to adapt to it. Fair enough.

Hope this helps.

Ian

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Thu May 21, 2009 3:15 pm

I'm stuck with an opensource C++ software and with an opensource PHP Framework. I'm more comfortable with the framework than with coding C++ :)

Thanks a zillion for your help. I'll try to work on it today and If I succeed I will post the results here.

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Thu May 21, 2009 11:55 pm

And It works like intended. I didn't test saving to the table yet, just retrieved some values. But I'm posting here as a reference for someone who's interested in developing his own extended JUser:

In my /administrator/components/com_younameit/tables/myuser.php

Code: Select all

<?php
defined('_JEXEC') or die('Restricted access');
JLoader::register('JTableUser', JPATH_LIBRARIES.DS.'joomla'.DS.'database'.DS.'table'.DS.'user.php');

class JTableMyUser extends JTableUser {

  var $country=null;
  var $city=null;
  var $photo=null;

	function __construct(&$db) {
		parent::__construct( $db );
	}

	function load($id) {
		return parent::load($id);
	}
}
?>
And in my /components/com_younameit/views/users/view.html.php

Code: Select all

<?php
defined('_JEXEC') or die();
 
jimport( 'joomla.application.component.view' );
 
class MyComponentViewMyUsers extends JView
{

  function display($tpl = null) {
      global $mainframe, $option;
      $db 			=& JFactory::getDBO();
      JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components'.DS.'com_younameit'.DS.'tables');

			$user = JUser::getTable('MyUser');
			$session  =& JFactory::getSession();
			$user->load($session->get('user')->id);
...
?>
So now I can use my own $user->country or $user->city or $user->photo and I will fetch the values from my own extended user table.

Once again, thank you Ian for your help and patiente.

User avatar
ianmac
Joomla! Virtuoso
Joomla! Virtuoso
Posts: 4784
Joined: Sat Sep 24, 2005 11:01 pm
Location: Toronto, Canada

Re: extending JUser

Post by ianmac » Fri May 22, 2009 3:15 am

VisiGod wrote:And It works like intended. I didn't test saving to the table yet, just retrieved some values. But I'm posting here as a reference for someone who's interested in developing his own extended JUser:

In my /administrator/components/com_younameit/tables/myuser.php

Code: Select all

<?php
defined('_JEXEC') or die('Restricted access');
JLoader::register('JTableUser', JPATH_LIBRARIES.DS.'joomla'.DS.'database'.DS.'table'.DS.'user.php');

class JTableMyUser extends JTableUser {

  var $country=null;
  var $city=null;
  var $photo=null;

	function __construct(&$db) {
		parent::__construct( $db );
	}

	function load($id) {
		return parent::load($id);
	}
}
?>
And in my /components/com_younameit/views/users/view.html.php

Code: Select all

<?php
defined('_JEXEC') or die();
 
jimport( 'joomla.application.component.view' );
 
class MyComponentViewMyUsers extends JView
{

  function display($tpl = null) {
      global $mainframe, $option;
      $db 			=& JFactory::getDBO();
      JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components'.DS.'com_younameit'.DS.'tables');

			$user = JUser::getTable('MyUser');
			$session  =& JFactory::getSession();
			$user->load($session->get('user')->id);
...
?>
So now I can use my own $user->country or $user->city or $user->photo and I will fetch the values from my own extended user table.

Once again, thank you Ian for your help and patiente.
Excellent!

Just as a side note, wanted to warn you to be careful with ?> at the end of files in case you ever want to do ajax or something. It is Joomla! convention to omit them as they are not required and leaving them out prevents problems from occuring (with random extra bytes getting pushed into the output).

ian

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Fri May 22, 2009 7:16 am

ianmac wrote: Just as a side note, wanted to warn you to be careful with ?> at the end of files in case you ever want to do ajax or something. It is Joomla! convention to omit them as they are not required and leaving them out prevents problems from occuring (with random extra bytes getting pushed into the output).

ian
It was just an example :)

User avatar
ianmac
Joomla! Virtuoso
Joomla! Virtuoso
Posts: 4784
Joined: Sat Sep 24, 2005 11:01 pm
Location: Toronto, Canada

Re: extending JUser

Post by ianmac » Fri May 22, 2009 12:52 pm

VisiGod wrote:
ianmac wrote: Just as a side note, wanted to warn you to be careful with ?> at the end of files in case you ever want to do ajax or something. It is Joomla! convention to omit them as they are not required and leaving them out prevents problems from occuring (with random extra bytes getting pushed into the output).

ian
It was just an example :)
For sure... was just putting that out there because it is a common problem I've seen. Basically, using the opportunity to educate people :)

Ian

ewel
Joomla! Guru
Joomla! Guru
Posts: 522
Joined: Mon Oct 01, 2007 11:35 am

Re: extending JUser

Post by ewel » Thu May 28, 2009 10:15 pm

This sounds very good, and thanks for posting it.
But would it be possible to create a plugin (onAfterRoute I suppose?) which would incorporate something similar to the above code, and then would also find and replace the content of the form on the com_user registration page to add fields corresponding to the new table columns?
To put it in another way, is there some way to use this without creating a component or changing the core, and still extend the user fields?

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Thu May 28, 2009 10:22 pm

I'm still working on the component so it's far from finish (well, not far, but still not finished). I will add it to my TODO list and will check it after I'm finish with upgrading my component.

User avatar
ianmac
Joomla! Virtuoso
Joomla! Virtuoso
Posts: 4784
Joined: Sat Sep 24, 2005 11:01 pm
Location: Toronto, Canada

Re: extending JUser

Post by ianmac » Fri May 29, 2009 2:37 am

ewel wrote:This sounds very good, and thanks for posting it.
But would it be possible to create a plugin (onAfterRoute I suppose?) which would incorporate something similar to the above code, and then would also find and replace the content of the form on the com_user registration page to add fields corresponding to the new table columns?
To put it in another way, is there some way to use this without creating a component or changing the core, and still extend the user fields?
The simplest way, in my experience, is to use something like the usermeta plugin by Kevin Devine and then do a layout override in your template.

Ian

ewel
Joomla! Guru
Joomla! Guru
Posts: 522
Joined: Mon Oct 01, 2007 11:35 am

Re: extending JUser

Post by ewel » Fri May 29, 2009 8:19 am

Thanks. After posting my question I discovered Kevin's plugin, and I think I will use that for the moment.

This thread is one of very few extremely helpful ones when it comes to trying to extend the user fields without installing a networking component. Kevin's plugin is at the moment the best ready-made solution. I was extremely pleased to discover it. But even Kevin's plugin has a severe drawback in that Tom, Dick and Harriet cannot get to results by simply clicking and typing in the administrator backend. I posted a suggestion in this direction at Kevin's project's forum, and I hope he or someone else will take on the challenge of enabling the creation of fields by filling in a few settings in the plugin manager, with automatic display of those fields in the frontend and backend.

My own thoughts were inspired by QContacts, HPRegister and Moovur. The idea was to have a plugin similar to that of Kevin, but to have two more capabilities built in for creating and displaying fields.
The first would be by way of plugin manager parameters similar to those of QContacts. These would be used to write to the xml file if changes are detected, and likewise to create or update a database table.
The second would be a) replacement plugin functionality or b) writing a template override automatically. Ad a: Where option is com_user and task is register or edit, the plugin could search for a chunk of the form, and replace it by a chunk which also includes custom fields. Moovur for Mollom does a similar sort of replacement. Ad b: a template override would be automatically written or updated using the information from the plugin manager settings.

Unless I am not making sense, I feel that something like this would be great for the core. It would keep Joomla lean while leaving the added value of networking components untouched, but it would help Tom, Dick and Harriet to do some basic customisation of user registration management. It would also provide a nice basis for third parties to develop more advanced solutions.

BTW, I would be glad to help in so far as I can. And sorry if I went a bit off topic.

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Fri May 29, 2009 9:22 am

I don't think we can compare the usermeta plugin since it doesn't extend the database, it uses the #__user parameters. It may work on some cases, but taking my example, I needed a single table for users to share between Joomla and my other application, so parameters or an external database is simply out of the question.

I still didn't work with plugins in the new structure but I will need to, so I will take a look at ewel post (using onAfterRoute) to see what does the core code offers us to be able to achieve this goal (using a single database without using parameters)

ewel
Joomla! Guru
Joomla! Guru
Posts: 522
Joined: Mon Oct 01, 2007 11:35 am

Re: extending JUser

Post by ewel » Fri May 29, 2009 10:01 am

Actually, I have just been playing with the usermeta plugin and found that it does have the capability to work with a database table, be it a separate table that must be manually created.

Have a look at those other extensions for examples of parts of what you would probably need to make a plugin. It looks like it has all been done before, although it may still be difficult to put the right parts together.

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Fri May 29, 2009 10:12 am

ewel, In my case, the external application is a binary and it reads from a MySQL database. It's easier for me to dig into Joomla code and develop what I need than to adapt a C++ code to Joomla :)

User avatar
ianmac
Joomla! Virtuoso
Joomla! Virtuoso
Posts: 4784
Joined: Sat Sep 24, 2005 11:01 pm
Location: Toronto, Canada

Re: extending JUser

Post by ianmac » Fri May 29, 2009 1:18 pm

ewel wrote:Thanks. After posting my question I discovered Kevin's plugin, and I think I will use that for the moment.

This thread is one of very few extremely helpful ones when it comes to trying to extend the user fields without installing a networking component. Kevin's plugin is at the moment the best ready-made solution. I was extremely pleased to discover it. But even Kevin's plugin has a severe drawback in that Tom, Dick and Harriet cannot get to results by simply clicking and typing in the administrator backend. I posted a suggestion in this direction at Kevin's project's forum, and I hope he or someone else will take on the challenge of enabling the creation of fields by filling in a few settings in the plugin manager, with automatic display of those fields in the frontend and backend.

My own thoughts were inspired by QContacts, HPRegister and Moovur. The idea was to have a plugin similar to that of Kevin, but to have two more capabilities built in for creating and displaying fields.
The first would be by way of plugin manager parameters similar to those of QContacts. These would be used to write to the xml file if changes are detected, and likewise to create or update a database table.
The second would be a) replacement plugin functionality or b) writing a template override automatically. Ad a: Where option is com_user and task is register or edit, the plugin could search for a chunk of the form, and replace it by a chunk which also includes custom fields. Moovur for Mollom does a similar sort of replacement. Ad b: a template override would be automatically written or updated using the information from the plugin manager settings.

Unless I am not making sense, I feel that something like this would be great for the core. It would keep Joomla lean while leaving the added value of networking components untouched, but it would help Tom, Dick and Harriet to do some basic customisation of user registration management. It would also provide a nice basis for third parties to develop more advanced solutions.

BTW, I would be glad to help in so far as I can. And sorry if I went a bit off topic.
There is a bunch of stuff planned for user field customization for 1.6. You could try looking at the experimental branch (wherever they have put it), and see what is in there.

I know there are certainly plans to make things easier, but how that looks exactly, I don't know.

Ian

psrch
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 110
Joined: Thu Sep 15, 2005 2:37 am
Location: Cumming, GA
Contact:

Re: extending JUser

Post by psrch » Thu Jun 18, 2009 3:01 pm

Thanks for the info on extending the Joomla user table. However, somehow, I'm having trouble with this... Of course, this is my first major Joomla component, so that's not surprising.

I have a table set up, called #__cm_clients. There's a field called id that I'm using to create the relationship between my table and the #__users table.

I've created an extended JTableUser class, as follows:

Code: Select all

<?php

// prevent direct access
defined ('_JEXEC') or die ('Direct access to this location is prohibited');

JLoader::register('JTableUser', JPATH_LIBRARIES.DS.'joomla'.DS.'database'.DS.'table'.DS.'user.php');

class JTableClients extends JTableUser
{
	var $client_num = null;
	var $id = null;
	var $status = null;
	var $org_flag = null;
	var $org_name = null;
	var $address1 = null;
	var $address2 = null;
	var $city = null;
	var $state = null;
	var $zipcode = null;
	var $phone = null;
	var $extension = null;
	
	function __construct(&$db)
	{
		parent::__construct($db);
	}
	
	function load($id)
	{
		return parent::load($id);
	}
}
?>
I set up a model to do the query (clientlist.php):

Code: Select all

<?php

// prevent direct access
defined ('_JEXEC') or die ('Direct access to this location is prohibited');

jimport('joomla.application.component.model');

class ModelClientmanClientlist extends JModel
{
	var $_clients = null;

	function getList()
	{
		if(!$this->_clients)
		{
			// $query = "SELECT * FROM #__cm_clients"; original query
			$query = "SELECT #__users.*, #__cm_clients.* "
				. "FROM #__users "
				. "INNER JOIN #__cm_clients on #__users.id = #__cm_clients.id";
			$this->_clients = $this->_getList($query, 0, 0);
		}
		return $this->_clients;
	}
}
?>

And the view.html.php file:

Code: Select all

<?php

// prevent direct access
defined ('_JEXEC') or die ('Direct access to this location is prohibited');

jimport('joomla.application.component.view');
class ClientmanViewClientlist extends JView
{
	function display($tpl = null)
	{
		global $mainframe, $option;
		
		JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components' . DS . $option . DS . 'tables');
		JUser::getTable('clients');

		$model =& $this->getModel();
		$list = $model->getList();
		for ($i = 0; $i < count($list); $i++)
		{
			$row =& $list[$i];
			$row->link = JRoute::_('index.php?option=' . $option . '&client_num=' . $row->client_num . '&view=showclient');
		}
		$this->assignRef('list',$list);
		parent::display($tpl);

	}
}
?>
And last but not least, the template default.php:

Code: Select all

<?php
// prevent direct access
defined ('_JEXEC') or die ('Direct access to this location is prohibited');
?>
<table>

	<thead>
		<tr>
			<th width="75" align="left">
				Client #
			</th>
			<th align="left">
				Client Name
			</th>
		</tr>
	</thead>



	<?php foreach($this->list as $row) : ?>
	<tr>
		<td align="left">
			<?php echo $row->client_num; ?>
		</td>
		<td align="left">
			<a href="<?php echo $row->link; ?>"><?php echo $row->$user->org_name; ?></a>
		</td>
	</tr>
	<?php endforeach; ?>
</table>

I'm not getting any errors, but nothing is displaying aside frm the column headings.

What am I doing wrong?
Paul Srch
Three Cats Design

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Thu Jun 18, 2009 6:27 pm

2 things you might want to check. bare with me if they look to obvious.

1 - run your query (the one in the model) on the database (via phpmyadmin ) to check if it's ok and if it returns any values;

2 - on the view.html.php, do a print_r($list) to see if you can get the values on the $list variable that is filled with the model query

VisiGod
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 171
Joined: Fri Sep 02, 2005 2:26 am
Location: Portugal
Contact:

Re: extending JUser

Post by VisiGod » Thu Jun 18, 2009 6:29 pm

You can also check my example ( posted on http://visigod.com/index.php/extending- ... class.html):

In /administrator/components/com_younameit/tables/myuser.php

Code: Select all

<?php
defined('_JEXEC') or die('Restricted access');
JLoader::register('JTableUser', JPATH_LIBRARIES.DS.'joomla'.DS.'database'.DS.'table'.DS.'user.php');

class JTableMyUser extends JTableUser {

  var $country=null;
  var $city=null;
  var $photo=null;

   function __construct(&$db) {
      parent::__construct( $db );
   }

   function load($id) {
      return parent::load($id);
   }
}
And in /components/com_younameit/views/users/view.html.php

Code: Select all

<?php
defined('_JEXEC') or die();

jimport( 'joomla.application.component.view' );

class MyComponentViewMyUsers extends JView
{

  function display($tpl = null) {
      global $mainframe, $option;
      $db          =& JFactory::getDBO();
      JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components'.DS.'com_younameit'.DS.'tables');

         $user = JUser::getTable('MyUser');
         $session  =& JFactory::getSession();
         $user->load($session->get('user')->id);
...
So now you can use $user->country or $user->city or $user->photo and It will fetch the values from your own extended user table.


Locked

Return to “Joomla! 1.5 Coding”