Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

What exactly do the args in hasManyToMany mean?

This is an example of a hasManyToMany:

$this->hasManyToMany(
            'id',
            'RobotsParts',
            'robots_id', 'parts_id',
            'Parts',
            'id'
        );

As far as I know, the args mean this, but my hasmanytomany relationships aren't working, so maybe i'm wrong!

hasManyToMany(
    $idColumnNameOnLocalTable, 
    $middleTableClassName,
    $columnonMiddleTableThatPointsToLocalTable,
    $columnOnMiddleTableThatPointsToForeignModel,
    $foreignModelClassName,
    $columnOnForeignTableThatIsTheIdColumn  
    )

Is this right?

Also, is it possible to have a many-to-many to the same model? e.g. products and related products



38.6k
Accepted
answer

These are the parameter names in source:

$this->hasManyToMany(
    $fields,                              // field(s) of this model (Robots.id)
    $intermediateModel,     // table which stores the n:n relations (RobotParts)
    $intermediateFields,      // columns in intermediate table that refers to this model's fields (RobotParts.robots_id)
    $intermediateReferencedField, // columns in intermediate that that refers to the referenced table (RobotParts.parts_id)
    $referencedModel,        // referenced table (Parts)
    $referencedFields,         // referenced table columns (Parts.id)
    $options                          // array of extra options, for eg alias
);

As to your second question, yes, a table can reference itself in an n:n relationship, but make sure that you name it uniquely with the alias option:

$this->hasManyToMany(
            'id',
            'RobotsParts',
            'robots_id',
            'parts_id',
            'Parts',
            'id',
            array(
                'alias' => 'UniqueName'
            )
)
foreach(Robot::find() as $robot) {
   // you can access the n:n array with the alias magic property
    echo count($robot->UniqueName);
}

Excellent - thanks.

Is it possible to display a model with relationships without being explicit. e.g. ATM I have something like: return $this->response->setJsonContent(json_encode($model)); in the controllers for a JSON api. I'd like to display certain relationships in the json output as this just displays the raw model

No, unfortunately I don't know any functionality like that.

You could override the toArray method to include the relations, but then you dont have the option to fine-tune the sent package, thus creating unnecessary overhead. I would go for manually composing the response JSON at each API endpoint

The only way I can think of doing this - without nasty reflection to cycle through public properties - is to cast the model to an array and then just append the relation as an extra key, though this seems to give all the protected properties of the model

You know that setJsonContent already does json_encode, right?

Yes - what you mention is easiest way, and actually pretty fine and i use it, you can always try eager loading from incubator if you really need it. About the last argument in relations:

  • it's also for virtual foreign key https://docs.phalconphp.com/en/3.2/db-models-relationships#virtual-foreign-keys
  • and also you can actually pass argument called params which is exactly an array which you pass for example to Model::find() so like columns, order, custom conditions etc(keep in min that $this won't work here(it will be null any value from model)) because this is initialize method
edited Aug '17

With Micro it's easy as:

 $app->response->setJsonContent([$app->getReturnedValue()], JSON_NUMERIC_CHECK);

I.e. you can use all common json_encode additional options. This will set both Content-Type header and will json encode your array or object.

Excellent - thanks.

Is it possible to display a model with relationships without being explicit. e.g. ATM I have something like: return $this->response->setJsonContent(json_encode($model)); in the controllers for a JSON api. I'd like to display certain relationships in the json output as this just displays the raw model