Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model Creation on Installation #932

Open
RK311y opened this issue Mar 4, 2021 · 7 comments
Open

Model Creation on Installation #932

RK311y opened this issue Mar 4, 2021 · 7 comments
Assignees
Labels
Bug: Unconfirmed Bug report that is not yet confirmed and/or is not reproducible. EE6 under review An EE team member is reviewing this issue

Comments

@RK311y
Copy link
Contributor

RK311y commented Mar 4, 2021

Overview

I have a custom add-on that has a Model called Contact. The Contact model has a relationship to ee:Member. Upon installation, after the database table is created, a Contact model is created for each ee:Member to which it belongs. In the previous version of EE, directly accessing the related model by its name was possible, now it is not.

For example: Addon_upd::install()

parent::install();

ee()->load->dbforge();

// forge the Contact models table    
ee()->dbforge->add_field(array(
    'contact_id' => [
        'type' => 'INT',
        'constraint' => 11,
        'unsigned' => TRUE,
        'auto_increment' => TRUE,
    ],
    'member_id' => [
        'type' => 'INT',
        'constraint' => 11,
        'unsigned' => TRUE,
    ],
// ... there are some more fields
));
ee()->dbforge->add_key('contact_id', TRUE);
ee()->dbforge->add_key('member_id');
ee()->dbforge->create_table('hat_contacts', TRUE);

// Now that the contact table is created, let's make some Contact models

// get all on the member models
$members = ee('Model')->get('ee:Member')->all();

// loop through all of the member models
foreach($members as $member) {
     // make a new 'Contact' model
    $new_contact = ee('Model')->make('hat:Contact');
    // assign the 'Member' model to the 'Contact's relationship
    // HERE is where the error ocurs, this used to be possible, now I get an error
    $new_contact->Member = $member;
    // save the newly created 'Contact' model
    $new_contact->save();
}
return TRUE;

I am unable to assign the contact's member model to the relationship: $new_contact->Member = $member.

Based on the details of the error message, I am lead to believe the ee:Member model does not recognize the inverse relationship which is defined in the Contact model's relationship - because it says, "The index MemberContact" is undefined. (Below, I will include my Contact model code to show the definition of the relationship)

Here is a screenshot of the error I receive:

model_error_screenshot

Contact Model Code

namespace Addons\Hat\Model\Contact;

use ExpressionEngine\Service\Model\Model;

class Contact extends Model
{
    
    protected static $_primary_key = 'contact_id';
    protected static $_table_name = 'hat_contacts';
    
    protected $contact_id;
    protected $member_id;
    // some other properties...
    
    protected static $_validation_rules = array();
    protected static $_events = array();
    protected static $_typed_columns = array();
    
    protected static $_relationships = array(
        'Member' => array(
            'type'      => 'belongsTo',
            'from_key'  => 'member_id',
            'to_key'    => 'member_id',
            'model'     => 'ee:Member',
            'weak'      => TRUE,
            'inverse'   => array( // inverse relationship
                'name'      => 'MemberContact',
                'type'      => 'hasOne'
            )
        )
    );   
}

Problem Narrowed

This problem does not occur after the addon is installed. I am able to access/assign this relationship once the addon is installed.

i.e. this code runs just fine afterwards:

$members = ee('Model')->get('ee:Member')->all();

foreach($members as $member) {
    $new_contact = ee('Model')->make('hat:Contact');
    $new_contact->Member = $member;
    $new_contact->save();
}

Furthermore

This was not a problem prior to EEv6. So maybe it has something to do with the new ExpressionEngine\Service\Addon\Installer.... but I do not know...

@intoeetive
Copy link
Contributor

Looks like the model is not fully loaded when the manipulation happens.

Is the model listed in addons.setup.php?
Does it get saved if you set the relation using the key, i.e.
$new_contact->member_id = $member->member_id ?

@intoeetive intoeetive added the EE6 label Mar 5, 2021
@RK311y
Copy link
Contributor Author

RK311y commented Mar 5, 2021

Addon Setup File

@intoeetive

My addon.setup.php file contains both the 'model' declaration/definition for the addon and the dependencies..

In the array returned I have the following within:

'models' => array(
    'Contact' => 'Model\Contact\Contact', // Yes, the Contact.php file is in a directory such as...addon/Model/Contact/Contact.php
),
'models.dependencies' => array(
    'Contact' => array(
        'ee:Member'
    ),
)

Installation Tests

The direct initialization of $new_contact->member_id does work as expected. It will even load the ee:Member model after the hat:Contact->member_id property is set. (See code)

$members = ee('Model')->get('ee:Member')->all();
        
foreach($members as $member) {
    $new_contact = ee('Model')->make('hat:Contact');
    $new_contact->member_id = $member->member_id;
    echo json_encode($new_contact->Member->getValues()); // This does work. It echos the member properties
    $new_contact->save();
}

Interestingly, $new_contact->Member loads the related ee:Member model after the $new_contact->member_id is set...

And yes, the database values reflect what would be expected in the code above after installation.

@ops-andy ops-andy added Bug: Unconfirmed Bug report that is not yet confirmed and/or is not reproducible. under review An EE team member is reviewing this issue labels Mar 25, 2021
@dougblackjr
Copy link
Contributor

@RK311y You showed in your code that your model is in the namespace:

namespace Addons\Hat\Model\Contact;

Does it work if you change it to:

namespace Hat\Model\Contact;

@RK311y
Copy link
Contributor Author

RK311y commented Mar 28, 2021

@dougblackjr,

Brief Response: the namespace does NOT have an effect on the error I am getting.

More Detail

My knowledge of namespaces in EE is somewhat limited. I have not been able to pinpoint the significants of the namespaces with regards to visibility via the core dependency injection container. What I have learned is that:

  • using a namespace is any library, driver, controller, module, updater, or extension gives me problems and errors.
  • the namespace for models is dependent on the directory scheme. For example:
    • namespace Addons\Hat\Model\Contact; must be used for a model located at ../addons/hat/Model/Contact/Contact.php
    • namespace Hat\Model\Contact; must be used for a model located at ../addons/hat/Model/Contact.php

The reason I have put the hat:Contact model in a directory (../addons/hat/Model/Contact) is because I have other related models in the Contact directory.

Furthermore

I have made a simplified version of my addon with only the necessary component for you all to see what is happening.

There is a settings controller page via the Hat addon for you to create hat:Contact models with some member relationships

  • hat.zip - A proof of concept. No model creation in the upd.hat.php installer - just creating the necessary DB tables. And a namespace using Addons\Hat\Model\Contact;
    • Checkout the Hat settings controller page to see that it works as expected
  • hat_one.zip - Prime example of what I am trying to accomplish via the installer class.
  • hat_two.zip - Shows that using namespace Hat\Model\Contact results in the same error upon installation attempts.

Note: Looking at the mcp.hat.php::save_contact(), you will see that the following assignment works as expected.

$member_id = ee()->input->get_post('member_id', TRUE);
$member = ee('Model')->get('ee:Member', $member_id)->first();

if(!is_null($member)) {
    $contact->Member = $member;
}

Conclusion

The exact problem is occurring during installation under the upd.hat.php::install().

$member = ee('Model')->get('ee:Member')->first();    
$new_contact = ee('Model')->make('hat:Contact');

// set some temporary info
$new_contact->set([
    'first_name' => 'John',
    'last_name' => 'Smith'
]);

//
// HERE is where the error occurs
$new_contact->Member = $member; // DOES NOT WORK
// I'll add the screen shot of the error below again


// this DOES work
//$new_contact->member_id = $member->getId();

$new_contact->save();

Screenshot of Error

Screenshot from 2021-03-28 13-32-12

@dougblackjr
Copy link
Contributor

@RK311y I pulled down your addon and tested. Two changes should be able to get this to work:

  1. In your addon.setup.php, your namespace was interfering with the native Addons namespace. I tested with changing the namespace here:
    // 'namespace' => 'Addons\Hat', changed to
    'namespace' => 'Hat',
  1. Made a similar change in your Model:
// namespace Addons\Hat\Model\Contact; changed to
namespace Hat\Model\Contact;

use ExpressionEngine\Service\Model\Model;

class Contact extends Model

And was able to get to the index, and create a model.
Screenshot from 2021-03-29 11-36-51
Screenshot from 2021-03-29 11-36-28

Those two changes should allow you to create your model succesfully.

@RK311y
Copy link
Contributor Author

RK311y commented Mar 29, 2021

@dougblackjr I made the namespace changes that you mentioned. But the I am still getting an error during add-on installation.
(i.e. upd.hat.php::install())

I am able to work with relationships, as described here, post-installation. But during installation, I am only able to set the related key.

// DOES NOT WORK
$new_contact->Member = $member; 

// DOES WORK
$new_contact->member_id = $member->getId();

Can you confirm that this version installs for you?
hat.zip

It is the same as hat_one.zip above - with the namespace changes that you suggested.

@dougblackjr
Copy link
Contributor

@RK311y Yes, it loads for me on EE6.0.3. Can you post your error you are receiving?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug: Unconfirmed Bug report that is not yet confirmed and/or is not reproducible. EE6 under review An EE team member is reviewing this issue
Projects
None yet
Development

No branches or pull requests

4 participants