Jump to content

Member::load broken


Sly_Ripper
Go to solution Solved by Stuart Silvester,

Recommended Posts

Fresh install, trying to add an API route but Member::load breaks any time I pass $idField, even default fields.

works:

$member = \IPS\Member::load(1);

 

$member = \IPS\Member::load(1, 'member_id');

Returns

{
	"errorCode": "EX0",
	"errorMessage": ""
}

System log says "InvalidArgumentException (0)", viewing the log shows OutOfRangeException from line 115 /app/system/Patterns/ActiveRecord.php

 

Also, the docs need fixing: 

 

    /**
     * Add our own column to default fields
     */
    public function __construct()
    {
        static::$databaseIdFields = array_merge( static::$databaseIdFields, array( 'remote_id' ) );

    }
        parent::__construct();

 

Edited by Sly_Ripper
Link to comment
Share on other sites

You can only use the allowed values in the \IPS\Member class for the second parameter:

	/**
	 * @brief	[ActiveRecord] Database ID Fields
	 */
	protected static $databaseIdFields = array( 'name', 'email' );

 

If you want to load based on the member_id column, simply skip the second parameter. You need to provide it only if you're loading a member based on their name or email address.

Edited by teraßyte
Link to comment
Share on other sites

47 minutes ago, teraßyte said:

You can only use the allowed values in the \IPS\Member class for the second parameter:

	/**
	 * @brief	[ActiveRecord] Database ID Fields
	 */
	protected static $databaseIdFields = array( 'name', 'email' );

 

If you want to load based on the member_id column, simply skip the second parameter. You need to provide it only if you're loading a member based on their name or email address.

 

Ah you're right. What about with custom columns? My hook is valid since inputting a column that doesn't exist here throws an error, with a valid column it throws the same error as before:

static::$databaseIdFields = array_merge( static::$databaseIdFields, array( 'remote_id' ) );

 

Link to comment
Share on other sites

12 hours ago, teraßyte said:

As long as you fixed the parent call being outside the function in the example, it should work.

I you post here the hook's code I can take a quick look maybe.

It's literally just a fresh hook and the example code

//<?php

/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
	exit;
}

class appname_hook_CustomMemberColumns extends _HOOK_CLASS_
{
    /**
     * Add our own column to default fields
     */
    public function __construct()
    {      
        static::$databaseIdFields = array_merge( static::$databaseIdFields, array( 'remote_id' ) );
        
        parent::__construct();
    }

}

 

Link to comment
Share on other sites

Yes, that seems indeed correct. Try adding this code right before the parent call:

var_dump( static::$databaseIdFields );exit;

If the hook is being loaded properly, you should get an output of 3 values: name, email, remote_id.

 

If you don't get anything, maybe there's a typo in the class you're trying to extend. Something like \IPS\Members instead of \IPS\Member. I had it happen a few times. 😅

 

Link to comment
Share on other sites

55 minutes ago, teraßyte said:

Yes, that seems indeed correct. Try adding this code right before the parent call:

var_dump( static::$databaseIdFields );exit;

If the hook is being loaded properly, you should get an output of 3 values: name, email, remote_id.

 

If you don't get anything, maybe there's a typo in the class you're trying to extend. Something like \IPS\Members instead of \IPS\Member. I had it happen a few times. 😅

 

 

array(3) { [0]=> string(4) "name" [1]=> string(5) "email" [2]=> string(9) "remote_id" }

Still throws an error when trying to load a member with 'remote_id'. Being in an API route shouldn't make a difference?

Link to comment
Share on other sites

I think we need to take a step back and start from scratch here.

 

What are you trying to do exactly?

  1. If you just need to load a member by using their ID, you don't need the hook or the remote_id value.
  2. Or are you trying to load a member based on some kind of external ID after adding a remote_id column to the core_members table in the database?

 

Knowing your goal would help guide you in the correct direction.

Edited by teraßyte
Link to comment
Share on other sites

On 6/19/2023 at 5:30 PM, teraßyte said:

I think we need to take a step back and start from scratch here.

 

What are you trying to do exactly?

  1. If you just need to load a member by using their ID, you don't need the hook or the remote_id value.
  2. Or are you trying to load a member based on some kind of external ID after adding a remote_id column to the core_members table in the database?

 

Knowing your goal would help guide you in the correct direction.

2

 

@Matt this is either a bug or bad docs

Link to comment
Share on other sites

We've used this approach in a lot of plugins, so I know it's working properly. Make sure that you actually have a `remote_id` column created in the `core_members` table.

It may also be worthwhile to show the log from the system log page in the support section. The JSON is not a real error.

Although, these days we would recommend keeping track of SSO data in your own table so that you're not modifying core tables.

Link to comment
Share on other sites

10 minutes ago, Stuart Silvester said:

We've used this approach in a lot of plugins, so I know it's working properly. Make sure that you actually have a `remote_id` column created in the `core_members` table.

It may also be worthwhile to show the log from the system log page in the support section. The JSON is not a real error.

Although, these days we would recommend keeping track of SSO data in your own table so that you're not modifying core tables.

I mentioned the line that throws the error in the first post, using the doc's code, '$databaseIdFields' is not being overwritten by the hook correctly.

#0 /app/system/Member/Member.php(240): IPS\Patterns\_ActiveRecord::load()
#1 /app/applications/appname/api/members.php(28): IPS\_Member::load()
#2 /app/system/Api/Controller.php(180): IPS\appname\api\_members->GETitem()
#3 /app/system/Dispatcher/Api.php(343): IPS\Api\_Controller->execute()
#4 /app/api/index.php(11): IPS\Dispatcher\_Api->run()
#5 {main}

 

Doing it this way works, probably not the best idea though:

class appname_hook_CustomMemberColumns extends _HOOK_CLASS_
{
    protected static $databaseIdFields = array('name', 'email', 'remote_id');

 

Link to comment
Share on other sites

  • Solution

Thanks for the follow up.

That helps explain the issue you're having. When you're updated the allowed IDs in the __construct() method, the \IPS\Member object has to be instantiated in order for that code to run. This happens automatically when using this code has a front/admin session available in normal use on the front end (which is why we're all expecting it to be working).

Solving this (although not pretty) would be as simple as putting this in your code before you load the member.

new \IPS\Member;

 

Link to comment
Share on other sites

19 hours ago, Stuart Silvester said:

Thanks for the follow up.

That helps explain the issue you're having. When you're updated the allowed IDs in the __construct() method, the \IPS\Member object has to be instantiated in order for that code to run. This happens automatically when using this code has a front/admin session available in normal use on the front end (which is why we're all expecting it to be working).

Solving this (although not pretty) would be as simple as putting this in your code before you load the member.

new \IPS\Member;

 

Solved, thanks

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...