Adding a new custom profile field

Discussion forum for Extension Writers regarding Extension Development.
Post Reply
User avatar
John Rippon
Registered User
Posts: 23
Joined: Sat Jan 23, 2016 8:18 pm

Adding a new custom profile field

Post by John Rippon » Fri Feb 05, 2016 6:13 am

Hi

I have written a simple extension that uses the value held in a custom profile field of the current user. Rather than have the administrator add the field in the ACP before enabling the extension, I'd prefer to have the field added as part of the migration checks when the extension is enabled. While it seems I could handle this with a few sql calls to the _profile_fields, _profile_lang and _profile_fields_data tables, is there another more preferred way using existing core functions?

Thanks
John

User avatar
gn#36
Translator
Posts: 185
Joined: Fri Oct 13, 2006 1:16 pm
Contact:

Re: Adding a new custom profile field

Post by gn#36 » Fri Feb 05, 2016 5:03 pm

The corresponding Page in the ACP does this manually: https://www.phpbb.de/infos/3.1/xref/nav ... .html#l808

However, there is a base migration that provides a function for exactly this: https://www.phpbb.de/infos/3.1/xref/nav ... n.php.html

If you simply create your migration to extend that migration, you can simply use the function in there, I would assume that is the preferred way of doing this.

So:

Code: Select all

class my_migration extends \phpbb\db\migration\profilefield_base_migration
{
     protected $profilefield_name;
  
      protected $profilefield_database_type;
  
      protected $profilefield_data;
  
      /**
      * Language data should be in array -> each language_data in separate key
      * array(
      *    array(
      *        'option_id'    => value,
      *        'field_type'    => value,
      *        'lang_value'    => value,
      *    ),
      *    array(
      *        'option_id'    => value,
      *        'field_type'    => value,
      *        'lang_value'    => value,
      *    ),
      * )
      */
      protected $profilefield_language_data;
  
      protected $user_column_name;
}
 
Have a look at the migration yourself, but I think if you fill the above variables, it will take care of everything else for you. You will need one migration per profile field.
German Support Team Member • http://www.phpbb.deMy Extensions in the CDBMy Extensions on Github • Contact with caos is inavoidable but no catastrophy if you keep an overview.

User avatar
John Rippon
Registered User
Posts: 23
Joined: Sat Jan 23, 2016 8:18 pm

Re: Adding a new custom profile field

Post by John Rippon » Sat Feb 06, 2016 5:25 am

Thanks for that. I'll try and work out what it all means.

rxu
Extensions Development Team
Posts: 2932
Joined: Wed Oct 25, 2006 12:46 pm
Location: Siberia, Russian Federation
Name: Ruslan
Contact:

Re: Adding a new custom profile field

Post by rxu » Sun Feb 07, 2016 7:22 am


User avatar
John Rippon
Registered User
Posts: 23
Joined: Sat Jan 23, 2016 8:18 pm

Re: Adding a new custom profile field

Post by John Rippon » Tue Feb 09, 2016 5:35 am

Thanks for the help guys. It's a steep learning curve for me.

Not much joy I'm afraid. Trying to build two migrations that add two user profile fields: jefit_id and jefit_bbcodes. Falls over when I try to install the extension.

The extension for the jefit_id fields is in m1_jefit_id_profilefield.php:

Code: Select all

<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace wtnz\jefit\migrations;
class m1_jefit_id_profilefield extends \phpbb\db\migration\profilefield_base_migration
{
	static public function depends_on()
	{
		return array(
			'\phpbb\db\migration\data\v310\profilefield_types',
			'\phpbb\db\migration\data\v310\profilefield_on_memberlist',
		);
	}
	protected $profilefield_name = 'jefit_id';
	protected $profilefield_database_type = array('VCHAR', '');
	protected $profilefield_data = array(
		'field_name'			=> 'jefit_id',
		'field_type'			=> 'profilefields.type.string',
		'field_ident'			=> 'jefit_id',
		'field_length'			=> '8',
		'field_minlen'			=> '0',
		'field_maxlen'			=> '8',
		'field_novalue'			=> '',
		'field_default_value'	=> '',
		'field_validation'		=> '[0-9]+',
		'field_required'		=> 0,
		'field_show_novalue'	=> 0,
		'field_show_on_reg'		=> 1,
		'field_show_on_pm'		=> 0,
		'field_show_on_vt'		=> 1,
		'field_show_profile'	=> 1,
		'field_hide'			=> 0,
		'field_no_view'			=> 0,
		'field_active'			=> 1,
	);
	protected $user_column_name = 'jefit_id';
}
Error message is:

Code: Select all

General Error
SQL ERROR [ mysqli ]

Unknown column 'jefit_id' in 'field list' [1054]

SQL

SELECT user_id, jefit_id FROM phpbb3_users WHERE jefit_id <> '' ORDER BY user_id LIMIT 250

BACKTRACE

FILE: (not given by php)
LINE: (not given by php)
CALL: msg_handler()

FILE: [ROOT]/phpbb/db/driver/driver.php
LINE: 855
CALL: trigger_error()

FILE: [ROOT]/phpbb/db/driver/mysqli.php
LINE: 193
CALL: phpbb\db\driver\driver->sql_error()

FILE: [ROOT]/phpbb/db/driver/mysql_base.php
LINE: 45
CALL: phpbb\db\driver\mysqli->sql_query()

FILE: [ROOT]/phpbb/db/driver/driver.php
LINE: 261
CALL: phpbb\db\driver\mysql_base->_sql_query_limit()

FILE: [ROOT]/phpbb/db/driver/factory.php
LINE: 321
CALL: phpbb\db\driver\driver->sql_query_limit()

FILE: [ROOT]/phpbb/db/migration/profilefield_base_migration.php
LINE: 199
CALL: phpbb\db\driver\factory->sql_query_limit()

FILE: (not given by php)
LINE: (not given by php)
CALL: phpbb\db\migration\profilefield_base_migration->convert_user_field_to_custom_field()

FILE: [ROOT]/phpbb/db/migrator.php
LINE: 550
CALL: call_user_func_array()

FILE: [ROOT]/phpbb/db/migrator.php
LINE: 496
CALL: phpbb\db\migrator->run_step()

FILE: [ROOT]/phpbb/db/migrator.php
LINE: 322
CALL: phpbb\db\migrator->process_data_step()

FILE: [ROOT]/phpbb/db/migrator.php
LINE: 202
CALL: phpbb\db\migrator->try_apply()

FILE: [ROOT]/phpbb/db/migrator.php
LINE: 185
CALL: phpbb\db\migrator->update_do()

FILE: [ROOT]/phpbb/extension/base.php
LINE: 80
CALL: phpbb\db\migrator->update()

FILE: [ROOT]/phpbb/extension/manager.php
LINE: 187
CALL: phpbb\extension\base->enable_step()

FILE: [ROOT]/includes/acp/acp_extensions.php
LINE: 177
CALL: phpbb\extension\manager->enable_step()

FILE: [ROOT]/includes/functions_module.php
LINE: 674
CALL: acp_extensions->main()

FILE: [ROOT]/adm/index.php
LINE: 81
CALL: p_master->load_active()
The field appears in the ACP and in the user's Edit Profile and I can give myself a value which appears where it should, so I'm picking it was trying to do something extra when it failed, the reason for which I don't understand.

Can anyone help please?

User avatar
gn#36
Translator
Posts: 185
Joined: Fri Oct 13, 2006 1:16 pm
Contact:

Re: Adding a new custom profile field

Post by gn#36 » Tue Feb 09, 2016 12:38 pm

There is a function that is converting data from a column in the users table. If you create a new profile field, you obviously don't have such a column. I didn't realize that the base migration is meant for conversion.

So you need to create your own update_data function in your migration, that does not do the conversion and only creates the profile field:

Code: Select all

      public function update_data()
      {
          return array(
              array('custom', array(array($this, 'create_custom_field'))),
              //array('custom', array(array($this, 'convert_user_field_to_custom_field'))),
          );
      }
This is a copy from the base migration with the conversion step commented out. Note that you will have to purge your extension to really test this migration, because if the creation of the profile field succeeded on the first try and only the conversion failed (which seems to be the case), then on the next installation try, the migration will simply mark itself as installed without doing anything because the profile field already exists.
German Support Team Member • http://www.phpbb.deMy Extensions in the CDBMy Extensions on Github • Contact with caos is inavoidable but no catastrophy if you keep an overview.

User avatar
John Rippon
Registered User
Posts: 23
Joined: Sat Jan 23, 2016 8:18 pm

Re: Adding a new custom profile field

Post by John Rippon » Wed Feb 10, 2016 6:59 am

gn#36 wrote:... you need to create your own update_data function in your migration, that does not do the conversion and only creates the profile field:

Code: Select all

      public function update_data()
      {
          return array(
              array('custom', array(array($this, 'create_custom_field'))),
              //array('custom', array(array($this, 'convert_user_field_to_custom_field'))),
          );
      }
Thanks for being so patient with a newbie. The migration completes correctly now without attempting to update the user table. :D

Just one more thing if I may:

create_custom_field does just than and only inserts a default value in the lang_name field in PROFILE_LANG_TABLE (viz: the profile field id in upper-case) and empty strings in the lang_explain and lang_default_value fields. I would like to put more user-friendly strings in lang_name and lang_explain. How would I best update these fields during the migration with strings of my own choosing? I'm probably OK with coding a database update for it, but pretty much lost with how to add the code to the migration class I've got.

Code: Select all

<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace wtnz\jefit\migrations;
class m1_jefit_id_profilefield extends \phpbb\db\migration\profilefield_base_migration
{
    static public function depends_on()
    {
        return array(
            '\phpbb\db\migration\data\v310\profilefield_types',
            '\phpbb\db\migration\data\v310\profilefield_on_memberlist',
        );
    }
    protected $profilefield_name = 'jefit_id';
    protected $profilefield_database_type = array('VCHAR', '');
    protected $profilefield_data = array(
        'field_name'            => 'jefit_id',
        'field_type'            => 'profilefields.type.string',
        'field_ident'            => 'jefit_id',
        'field_length'            => '8',
        'field_minlen'            => '0',
        'field_maxlen'            => '8',
        'field_novalue'            => '',
        'field_default_value'    => '',
        'field_validation'        => '[0-9]+',
        'field_required'        => 0,
        'field_show_novalue'    => 0,
        'field_show_on_reg'        => 1,
        'field_show_on_pm'        => 0,
        'field_show_on_vt'        => 0,
        'field_show_profile'    => 1,
        'field_hide'            => 0,
        'field_no_view'            => 0,
        'field_active'            => 1,
    );
    public function update_data()
    {
        return array(
            array('custom', array(array($this, 'create_custom_field'))),
        );
    }
}
On a more trivial note, I'm jealous of how you folks colour-code code snippets in your posts. Surely you don't do it using font colour BBCodes?

Edit: Cancel that last question!

User avatar
gn#36
Translator
Posts: 185
Joined: Fri Oct 13, 2006 1:16 pm
Contact:

Re: Adding a new custom profile field

Post by gn#36 » Wed Feb 10, 2016 12:45 pm

If you already know what you need to do in the database, you can simply add a new method to your migration which runs the appropriate queries. You can then add this method to the update_data function in the same way as the create_custom_field method is added in there.

So for example, you might simply add a method called populate_lang_explain:

Code: Select all

public function update_data()
{
      return array(
          array('custom', array(array($this, 'create_custom_field'))),
          //array('custom', array(array($this, 'convert_user_field_to_custom_field'))),
          array('custom', array(array($this, 'populate_lang_explain'))),
      );
}


public function populate_lang_explain()
{
    //do your queries here
}
However, there is also a field $profile_field_language_data in the base migration that you may be able to use for this, in combination with the existing method create_language_entries. That way, you only have to call that method in your update_data method and populate the array.
German Support Team Member • http://www.phpbb.deMy Extensions in the CDBMy Extensions on Github • Contact with caos is inavoidable but no catastrophy if you keep an overview.

User avatar
John Rippon
Registered User
Posts: 23
Joined: Sat Jan 23, 2016 8:18 pm

Re: Adding a new custom profile field

Post by John Rippon » Wed Feb 10, 2016 11:56 pm

Sweet. All working fine now. Just lacking a little confidence to try things before asking for help.

Thanks again!

Post Reply

Return to “Extension Writers Discussion”