Get associated link based on field name

Hi,

Taking the cakephp4 tutorial as example.

CREATE TABLE articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    slug VARCHAR(191) NOT NULL,
    body TEXT,
    published BOOLEAN DEFAULT FALSE,
    created DATETIME,
    modified DATETIME,
    UNIQUE KEY (slug),
    FOREIGN KEY user_key (user_id) REFERENCES users(id)
) CHARSET=utf8mb4;

Since the articles table has a FOREIGN KEY to link it to users table. From the Entity, how can I know/get Articles->user_id is associated to Users table ?

Is there something like getAssociatedSource('user_id') ?

If you follow Cake’s naming conventions this is very easy because user_id will imply the UsersTable and an association between Articles and Users. This is one of the many reasons that strictly following the naming conventions will make your life easier.

But if you get off into the willywags:

The entity has a getSource() method which will tell you which table created the Entity.

From there (a table class) you can discover and work with associations through these four tools:

Also from a table you can work with its schema:

Perhaps this is enough to get you started?

Hi @dreamingmind, what is the IDE you’re using on your screenshots above?

i know about the getSource (Class Entity | CakePHP 4.0)

But i want to get the associated table from the field name, e.g. user_id

In other words, how do I know that user_id is associated to Table->User from inside the Articles-entity itself ?

I guess you could iterate through the various associations on the table and look for one where they foreign key matches the field in question. Typically, though, people just know what the associations are…

PhpStorm. Though it cost a few dollars it’s not really expensive and has completely transformed my coding.

Thanks for the encouragement. Been looking at it for the longest time, but was going to buy Nova when my trial ends. So now is the time to reconsider. Thanks again!

I’m with @Zuluru, generally you will know that. Maybe we don’t understand your actual use case.

Is there some situation where your code will receive an arbitrary entity and have to deduce the association from the key?

If so (and if you follow naming conventions) you can create the default table name from the foreign key by dropping the _id and pluralizing then capitalizing the remainder. This will be that ‘standard’ Alias.

The Inflector Class provides some tools to help.

The ConventionsTrait provides a somewhat parallel tool set.

@Zuluru @dreamingmind Thanks for the suggestions. Maybe I wasn’t clear in my question.

I want to get back the table-object (e.g. $this->User) based on the field-name, so I can do a separate query on the fly. A simple example like below (getAssociatedTableFromField is what I am looking for):

$article = $this->Articles->get( 1 );
$table = $article->getAssociatedTableFromField( 'user_id' );
$table->find( .... )

Our point is that if you know it’s the Articles table you read the article from, and you know it’s the user_id field that you want to read related records for, then you should also know it’s the Users table you want to read those related records from, and you’d either use ['contain' => 'Users'] on the get call, or else $this->Articles->Users->find. What’s your scenario where this doesn’t work?

This will work for simple or 1 level association. I am looking for something with multiple deep associations, where the code can easily get it from the field.

This will work for any level of associations that you want it to work for. Still not understanding the use case where you need it to be generic.

One simple use case would be as such :

in getDirty(), we can map the field-name-id to the table (user_id to $usersTable). From there, we can get the user’s email, or additional processing/query.

foreach( $article->getDirty() as $dirty ){
	
	// Can be deeply-nested associated data
	$table = $article->getAssociatedSource( $dirty );
	$dataToWorkOn = $table->get( $dirty );
	// other work here...
	
}