CodeIgniter Forums

Full Version: Relations Module
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi all! The compliment to my Schemas module, Relations provides very basic relationship loading. This is *not* a fully-featured ORM nor does it ever intend to be, but it does provide basic eager loading for related items (entity lazy loading coming with a future release).

Tatter/Relations - Entity relationships for CodeIgniter 4

Basic usage:

  1. Install with Composer: `> composer require tatter/relations`
  2. Extend the model: `class UserModel extends \Tatter\Relations\Model`
  3. Load relations: `$users = $userModel->with('groups')->findAll();`
Your models extend Tatter\Relations\Model which injects related items that you define into the returned rows. Related items can be requested by adding a $with property to your model:

PHP Code:
protected $with 'groups';
// or
protected $with = ['groups''permissions']; 

... or by requesting it on-the-fly using the new with() method:

PHP Code:
$users $userModel->with('groups')->findAll();
foreach (
$users as $userEntity)
{
echo 
"User {$user->name} has " count($user->groups) . " groups.";
... 

(As you can see the related items are added directly to their corresponding object or array returned from the primary model.)

Relations relies on the Schemas module to map the database and detect related tables and their relationship. (You may also provide explicit relationships using the Schemas File Handler). Schemas will also attempt to associate your database tables back to their models and Relations will use each table's model to find the related items. This keeps consistent the return types, events, and other aspects of your models. In addition to the return type, Relations will also adjust related items for singleton relationships:

PHP Code:
// User hasMany Widgets
$user $userModel->with('widgets')->find($userId);
echo 
"User {$user->name} has " count($user->widgets) . " widgets.";

// ... but a Widget belongsTo one User
$widget $widgetModel->with('users')->find($widgetId);
echo 
$widget->name " belongs to " $widget->user->name


Thanks for reading! I'm always glad for feedback and suggestions, feel free to leave a comment here or check out the repo at https://github.com/tattersoftware/codeig...-relations.
Huge update to the Relations module and its partner-in-crime, Schemas. The new versions have a lot better performance optimization, and make it easier for developers to use by moving methods to traits (so you can extend whatever other Models you like!). Also, probably the most exciting: entities are now supported. Simply add the trait to your entity and now you can lazy-load related items on-the-fly as properties:
PHP Code:
    $user $userModel->find(1);
    
    foreach (
$user->groups as $group)
    {
        echo 
$group->name;
    } 

The entity trait also comes with magic methods to make it easy to check and update related items:
PHP Code:
    $user->addGroup(3);
    
$user->removeGroups([12]);    
    
$user->setGroups([5]); 
Check it out on Packagist or GitHub and share any feedback you have. Thanks for reading!
I'm trying to use this and I got timed out every time.

There's any fully functional examples?
Can you provide more details and some code samples? Most likely you’re timing out on the schema generation, which ideally should be happening ahead of time (e.g. cron) via the CLI. Try running “php spark schema” and let it generate and cache a schema and then load your pages again.
I’m using this on a few projects very successfully but unfortunately they are for private clients. I will see if I can get an example project going. You can also check out the tests, and run them with “composer test” from a cloned repo.

Also: OS, PHP version, web server, etc would help.
(12-01-2019, 05:03 AM)MGatner Wrote: [ -> ]Can you provide more details and some code samples? Most likely you’re timing out on the schema generation, which ideally should be happening ahead of time (e.g. cron) via the CLI. Try running “php spark schema” and let it generate and cache a schema and then load your pages again.
I’m using this on a few projects very successfully but unfortunately they are for private clients. I will see if I can get an example project going. You can also check out the tests, and run them with “composer test” from a cloned repo.

Also: OS, PHP version, web server, etc would help.

Hello MGatner, could you please simplify the relations script, ant take all the schema stuff out? I think if everything is defined by hand is much better and clearer.

Thank you in advance.
It would be nice to use the module as an independent trait so as not to inherit from your classes. I saw that there is trait, but it overrides the model constructor, I would like the trait to be without a constructor.
@x1250 The Schemas dependency is essential to the design of the module, otherwise it wouldn’t know which tables are related to others and they nature of their relationship. If you don’t like the database-scanning nature of Schemas you can still define you schema in a single flat file using the DirectoryHandler. If you have other concerns about Schemas I’m open to hearing them.

@BasicApp the constructor isn’t essential but the code it runs needs to happen - I could move it to an init() function of some sort but then either you would be responsible for initializing or it would have to be checked on every method call. I’m open to input.
(02-18-2020, 04:25 AM)MGatner Wrote: [ -> ]@x1250 The Schemas dependency is essential to the design of the module, otherwise it wouldn’t know which tables are related to others and they nature of their relationship. If you don’t like the database-scanning nature of Schemas you can still define you schema in a single flat file using the DirectoryHandler. If you have other concerns about Schemas I’m open to hearing them.

@BasicApp the constructor isn’t essential but the code it runs needs to happen - I could move it to an init() function of some sort but then either you would be responsible for initializing or it would have to be checked on every method call. I’m open to input.

Hello MGatner. Right, my point is that an add-in like this shouldn't depend on the schema guesswork, since that limits its application. The guess work should be minimal and the schema stuff optional.

Also, in real applications, sometimes there is no way any programmed guess work will be able to determine any relations between tables.

IMO, relations should be defined directly in the model and nowhere else and the schema thing should be optional.

I hope someone can do it, because it is out of my technical capacity for now   Shy
I understand the qualms, but I'd also suggest that Schemas is equipped to do the manual definitions. The two modules were always intended to be used together, I just released Schemas separately because it has applications beyond just the ORM-like. It handles the caching and formatting of relation data, and a lot of other things, letting Relations focus on *using* those relationships. If you don't want any automatic guesswork, just define your schema manually (https://github.com/tattersoftware/codeig...tervention) - you could even run the Schema command to generate your initial version and then work from that.
(02-18-2020, 04:25 AM)MGatner Wrote: [ -> ]@BasicApp the constructor isn’t essential but the code it runs needs to happen - I could move it to an init() function of some sort but then either you would be responsible for initializing or it would have to be checked on every method call. I’m open to input.

For example, you initialize the parameter $this->width in the constructor to use it later in the code, but if you use the getWidth() function in the code instead of directly accessing the parameter, you can also initialize the parameter in the same function. I understand that this simple example will not solve all problems, but I hope this explains what I mean. In my opinion, the init function does not solve the issue of trait independence.
Pages: 1 2