Help with Cortex and relationship table

950 views
Skip to first unread message

Anatol Buchholz

unread,
Aug 14, 2015, 12:34:06 PM8/14/15
to f3-fra...@googlegroups.com
Hi there,

this might be super easy, but I cannot see the trees because of the forest.

I´m trying to use ikkez cortex [1] with has-one <> has-many relations.
My goal is to create a relation between authors and news table over a third
one which glues everything together.

Author table looks like:  http://sqlfiddle.com/#!9/0464d7/1
News table looks like: http://sqlfiddle.com/#!9/87273/1
table for relations: http://sqlfiddle.com/#!9/6760f/1

Means author with ID 1 has written News with ID 1-6, 
Author with ID 2 News 7-10.

How do I have to setup field config for both models to respect the third table?

namespace Model;

class newsModel extends \DB\Cortex
{
   
protected
        $db
= 'AppDB1',
        $table
= 'news';
}


namespace Model;

class
authorModel extends \DB\Cortex
{
   
protected
      $db
= 'AppDB1',
      $table
= 'author';
}



@ikkez: Sorry your documentation is great, the problem is me ;)


Thanks!

– Anatol








ikkez

unread,
Aug 14, 2015, 12:51:39 PM8/14/15
to f3-fra...@googlegroups.com
Hi anatol.
You are talking about a one-to-many relation. The news was written by one author. An author as written many news.
As long as you don't have multiple authors that worked on the same news record, you don't want a pivot table (that would be many-to-many)

The one to many relation can be looked up from the docs -> https://github.com/ikkez/f3-cortex/tree/master#setup-the-linkage
Type 1:m, it's also right in the screenshot you'll see there. (it's belongs-to-one <> has-many)

If you still want multiple authors per news, take the M:M type (has-many <> has-many).

Anatol Buchholz

unread,
Aug 14, 2015, 1:25:07 PM8/14/15
to f3-fra...@googlegroups.com

Hi Ikkez,

 
You are talking about a one-to-many relation. The news was written by one author. An author as written many news.

right, thanks for pointing out.
 

The one to many relation can be looked up from the docs -> https://github.com/ikkez/f3-cortex/tree/master#setup-the-linkage
Type 1:m, it's also right in the screenshot you'll see there. (it's belongs-to-one <> has-many)

That´s why I´m confused. In the screenshot on the right side you see:

'news' => array(
   
'has-many' => array ('\NewsModel','author'),
),


you´re describing it as:

'virtualField' => array(
    'relationType' => array('\Namespace\ClassName','foreignKey'),
),

and further:

Defining a foreign key for belongs-to-* is optional.

which means I can skip the left screenshot, right ?

Changing my author model with field config:

namespace Model;
class authorModel extends \DB\Cortex
{
   
protected

     $fieldConf
= array(
       
'news' => array(
        
'has-many' => array ('\Model\NewsModel','news'),
      
),
   
),

    $db
= 'AppDB1',
    $table
= 'author';
}

ends in:

Internal Server Error
array_key_exists
() expects parameter 2 to be array, null given


The reason why I´m confused is, following this documentation steps how are the table linked together

as the relation is in the third table? Further I do not have a foreign key in author or news table as it´s in

rel_author_news.


As said, sorry for asking stupid questions your documentation is great, maybe I´m just sitting for to long in front of my computer …

ikkez

unread,
Aug 14, 2015, 1:51:36 PM8/14/15
to f3-fra...@googlegroups.com
no problem, let's see.

there is no 3rd table for 1:M relations. The primary ID from the one record is saved in an extra field in the other model.
By finding all news that contains the author.id you can resolve the "many" part. The news model itself can use that author.id to find the one author it belongs to.

You still need to define both sides in each model. The default is:

Author
'news' => array(
   
'has-many' => array ('\NewsModel','author'),
), // --------------------------------^ required

News:
'author' => array(
   
'belongs-to-one' => array ('\AuthorModel','id'),
), // -----------------------------------------^ optional

'author' => array(
   
'belongs-to-one' => '\AuthorModel' // short style with id as default fkey
),

That's what I wanted to say with "Defining a foreign key for belongs-to-* is optional."

Anatol Buchholz

unread,
Aug 15, 2015, 7:25:26 AM8/15/15
to f3-fra...@googlegroups.com
Dear Ikkez,

as always thank you!

Now it´s working but there is one question left. I think with your given config 
I can alter multiple tables like:

class rel{
 
function Content(\Base $f3){
 $author
= new \Model\authorModel();
 $author
->load(array('city = ?','Windsor'));

 $news
= new \Model\newsModel();
 $news
->text = 'Hello World';
 $news
->author = $author;
 $news
->save();

 $news
->load();
 echo $news
->author->name;
 
}
}



But my question is what If for example I´d like to have all news from author with ID 2. Where relationship is saved in
table rel_author_news.

Normally I would join them like

SELECT r.*, news.*
FROM rel_author_news r
INNER JOIN news
ON news
.id = r.newsid
WHERE r
.authorid = 2

My question is, with Cortex do I just fire a SQL query to get all news ? Or can I join the tables with field config
and there is something inbuilt? – seems I haven´t yet understood the whole concept but promise I will do further learning
with you documentation ;)

Thanks!

– anatol

Anatol Buchholz

unread,
Aug 15, 2015, 1:21:16 PM8/15/15
to f3-fra...@googlegroups.com
Update:

I tried now something like this:

First get all news Ids from relationship table for a given author id and after that use that array to find all news
in news table:

class news_author_relation{

  public function get_news_ids($authorId){
$f3=Base::instance();
$relation = new \Model\relModel();
$records = $relation->find(array('authorid = ?', $authorId));
$finds = $records->getAll('newsid');

return $finds;
}



  public function get_news(){

$f3=Base::instance();

        $Ids = $this->get_news_ids($f3->get('PARAMS.autorId'));
$news = new \Model\newsModel();
$newstext = $news->find(array('id in (?)',$Ids));
  foreach ($newstext as $obj)
    echo $obj->text . '<br>';
  }
}

$f3
->route('GET /news/@autorId','news_author_relation->get_news');

Is this the way one would go when dealing with relationship tables and cortex? 

ikkez

unread,
Aug 15, 2015, 9:12:43 PM8/15/15
to Fat-Free Framework
If want want to use that 3rd table, you could define it as a many-to-many relation.

Author
'news' => array(
   
'has-many' => array ('\NewsModel','author','rel_author_news'),
),

News:
'author' => array(
   
'has-many' => array ('\AuthorModel','news','rel_author_news'),
)

and then it's just like this

$news = new \Model\newsModel();

$result
= $news->has('author',array('id = ?',2))->find();

Anatol Buchholz

unread,
Aug 16, 2015, 3:42:07 AM8/16/15
to Fat-Free Framework
Hey Ikkez,

this is simply great! I had to rename the columns from "newsid" to "news" in the relationtable but that´s absolutely okay.
Thanks for helping. this is clear now – I just bought you are bear for this ;)

– anatol

bcosca

unread,
Aug 16, 2015, 4:30:37 AM8/16/15
to Fat-Free Framework
@ikkez will appreciate that. Oktoberfest is coming. :)

ikkez

unread,
Aug 16, 2015, 8:37:21 AM8/16/15
to Fat-Free Framework
thanks a lot ;)

Anatol Buchholz

unread,
Aug 16, 2015, 11:16:18 AM8/16/15
to f3-fra...@googlegroups.com
May I add one more question? If I´d like to add a new author and news + it´s relation,
I have to update three tables:

class new_post{
 
function save(\Base $f3){

   $author = new \Model\authorModel();
   $author->name = "bert brecht";
   $author
->mail = "b...@web.com";
   $author
->city = "berlin";
   $author
->save();


   $news
= new \Model\newsModel();

   $news
->title = "A book";
   $news
->text = "Some text";
   $news
->save();


   $relation
= new \Model\relModel();

   $relation
->author = $author->id;
   $relation
->news = $news->id;
   $relation
->save();
 
}
}


I assume there is an easier way to do this with cortex?

Thanks for helping me getting started!

– Anatol

ikkez

unread,
Aug 16, 2015, 1:02:13 PM8/16/15
to Fat-Free Framework
Yes there is. You don't need no relModel at all your can delete that.

if(!$author->news)
$author->news = array($news);
else
$author->news[] = $news;
$author->save();

Anatol Buchholz

unread,
Aug 16, 2015, 5:43:51 PM8/16/15
to f3-fra...@googlegroups.com
Dear Ikkez,

buff!
when you say

You don't need no relModel at all your can delete that.

I think my main problem is I do not really understand how tables are joined in background through configuration fields. 
In other words what is going on behind the scenes, a left join … outer join … a join at all?
I think most likely I have to read/learn more about the concept of ORM to understand this!

Anyway after sneaking more and more into cortex you really wrote a great piece of code!
thanks for this!

- a

@bcosca: An "Oktoberfest Maß" is twice the price :((

ikkez

unread,
Aug 17, 2015, 4:53:50 AM8/17/15
to Fat-Free Framework
don't think about tables. the ORM is here to present a layer of entities and relations between them. When you create two models with a many-to-many relation between them, Cortex knows that it'll need a 3rd table for record references. That table name is autogenerated and created upon setup, but you used a custom name for that here (rel_author_news). Table joins are made when it's possible and reasonable. At the end you usually use the models methods to define your query. check the filter() and has() methods. There are also a lot more features to discover in the API docs. If there is something to improve in the docs, or you have questions, I'm here :)

Anatol Buchholz

unread,
Aug 18, 2015, 6:37:35 AM8/18/15
to f3-fra...@googlegroups.com
Dear Ikkez,

thanks for your reply! The last days I worked through the documentation. What you did is really great and mind blowing!
I think my main problem is/was if configuration field relations are not correct, things will not work as expected, it took some time for
me to show respect to them. 

Further after some time I´ve recognized that cortex is happy if you do not do to much. In other
words it cares about what is needed regarding relations – the moment I setup relationship models I messed things up. 
In a next step I would try to use it in a little project where I will surely need some advise here and there but would open a new
issue for this. 

May I add some general comments and questions here:

Comments:
  • It was a bit hard to follow the documentation as I could not test it due to missing tables. After a while I´ve recognized that your documentation is mainly based on models of fabulog. Which means using the composer-app with slimmed models of fabulog gives you a good basis to follow the documentation. Maybe this could be helpful for other cortex newbies ?
  • Documentation->Configuration I think a comma is missing after
    $table = 'users'
  • Documentation->has 
    $results[0]->title; // '10 Responsive Images Plugins'
    would be easier to follow with an echo before (It took some time after copy and paste to understand why things are not working as expected) 
  • Documentation->Virtual 
    and even reorder you collection on this fields  
    Missing "r"? – reorder your collection …

Questions:
  • $news->copyfrom('POST','title;text');
    Means we can pass in fields which should be copied from POST? In other words the security issue from f3
    SQL Mapper is already solved here?
    – This would be great to see in F3 core!
  • I´m unsure if at some points it would be easier for me to just create a mysql view which joins tables than dealing with configuration fields. But on the other hand with views one would loose the ability to simple switch the underlaying database system.
  • If I´m using fluent mode without ::setup() method Cortex will not be able to create relationship fields/tables as therefore configuration fields are needed, right?
  • I cannot follow your given advise some posts above: 
  • if(!$author->news)
      $author
    ->news = array($news);
    else
      $author
    ->news[] = $news;
      $author
    ->save();
  • Is what you´re doing here described at: many-to-many, bidrectional? My problem is I don´t understand what is happening with the array you are passing in.

Hope that is not to much but 

or you have questions, I'm here :)

… I took you at your word :)))

Thanks!

– anatol

ikkez

unread,
Aug 18, 2015, 9:32:49 AM8/18/15
to f3-fra...@googlegroups.com
hi anatol. thanks for your feedback.
 
I think my main problem is/was if configuration field relations are not correct, things will not work as expected, it took some time for
me to show respect to them. 

Further after some time I´ve recognized that cortex is happy if you do not do to much. In other
words it cares about what is needed regarding relations – the moment I setup relationship models I messed things up.

well every relationship configuration is made with one field definition in each model. That shouldn't be too much and with only 3 relation types (belongs-to-one, has-one, has-many) the config should stay clear and easy to do.
 
I've updated the docs regarding your comments. thx.

Questions:
  • $news->copyfrom('POST','title;text');
    Means we can pass in fields which should be copied from POST? In other words the security issue from f3
    SQL Mapper is already solved here? – This would be great to see in F3 core!
 Indeed. There're multiple ways to define the fields to use, see https://github.com/ikkez/f3-cortex/tree/master#copyfrom
In the F3 mappers you already have the chance to define a callback function to filter the copyfrom fields, but to define them with a simple array would be nice addition yeah :)
  • I´m unsure if at some points it would be easier for me to just create a mysql view which joins tables than dealing with configuration fields. But on the other hand with views one would loose the ability to simple switch the underlaying database system.
One idea I had once was to add a feature that cortex automatically creates the Views. But views don't aid in every situation and it's hard to make this all cross-platform compabile somehow. At the end the cortex runs fine with building it's own queries and adding joins when searching through relations. Like I said above, only 3 relation types shouldn't be too hard to configure, but maybe I'm already too much into it to see the obvious lacks in the docs.
  • If I´m using fluent mode without ::setup() method Cortex will not be able to create relationship fields/tables as therefore configuration fields are needed, right?
right. I added the fluid mode for quick prototyping. Imagine you want to import a big Excel table into your database. The table for that isn't existing yet. Instead of creating the mysql table by hand, copy&pasting lots for fields names, or writing the setup fieldConfig manually, you could just import the excel/csv file into php, create an empty fluid cortex mapper and fill it with one record and all its fields. That'll instantly create the table and dozens of fields that were found in your excel sheet... ready to go, in less than a minute. After your model is working and already contains the fields you need for your CRUD operations, you should consider to disable the fluid mode. You can always add fields later with proper fieldConf & setup() or fluid mode.

  • I cannot follow your given advise some posts above: 
    if(!$author->news)
      $author
    ->news = array($news);
    else
      $author
    ->news[] = $news;
      $author
    ->save();
    Is what you´re doing here described at: many-to-many, bidrectional?
yes, it's many-to-many. You asked for a config that uses your 3 tables. I told you that you actually want a one-to-many relation, with no 3rd table in-between, but I thought that you don't care :D
  • My problem is I don´t understand what is happening with the array you are passing in.
The array should contain other mapper objects, or just their primary key values, so cortex can use those to save the according reference values in the table(s). For a simple belongs-to-one field, you just put one single ID or object into the field of course, and no array.

Anatol Buchholz

unread,
Aug 18, 2015, 10:21:39 AM8/18/15
to Fat-Free Framework
well every relationship configuration is made with one field definition in each model. That shouldn't be too much and with only 3 relation types (belongs-to-one, has-one, has-many) the config should stay clear and easy to do.

I totally agree, 3 relation types are not to much at all. But as said it took a while for me to recognize how important they are 
My fault ;)
 
… to filter the copyfrom fields, but to define them with a simple array would be nice addition yeah :)

+1 for this ! bcoscaaaa!
 
  • I´m unsure if at some points it would be easier for me to just create a mysql view which joins tables than dealing with configuration fields. But on the other hand with views one would loose the ability to simple switch the underlaying database system.
One idea I had once was to add a feature that cortex automatically creates the Views. But views don't aid in every situation and it's hard to make this all cross-platform compabile somehow. At the end the cortex runs fine with building it's own queries and adding joins when searching through relations. Like I said above, only 3 relation types shouldn't be too hard to configure, but maybe I'm already too much into it to see the obvious lacks in the docs.

Well the good thing about F3 and its plugins is it does not force you to develop in one way, means If I decide to use views together with cortex it
would still work for querying data over a view and writing data through it´s relationship tables/coloumns configuration fields. ;)

 
  • I cannot follow your given advise some posts above: 
    if(!$author->news)
      $author
    ->news = array($news);
    else
      $author
    ->news[] = $news;
      $author
    ->save();
    Is what you´re doing here described at: many-to-many, bidrectional?
yes, it's many-to-many. You asked for a config that uses your 3 tables. I told you that you actually want a one-to-many relation, with no 3rd table in-between, but I thought that you don't care :D

Yes at this point I could not imagine how Cortex connects things I was used to have a third table due to "normalization". After studying the docs and after your answers it´s more clear to me. But it will take some time to get used to the methods. As said I will try to get into it with a little project for some friends of mine. I surely will have some more questions later – and will also make a donation to you for sharing this plugin.
 

Thanks!

– a

Anatol Buchholz

unread,
Aug 19, 2015, 3:47:18 AM8/19/15
to f3-fra...@googlegroups.com
Dear Ikkez,

one more basic question which may be super simple.

Two models: fruits + color,

Fruits has:

            'color' => array(
                'belongs-to-one' => '\Model\color',
            ),

color has:
            'fruit' => array(
               
'has-many' => array('\Model\fruit','color'),
           
),

::setup(); perfect sweet cortex doing my work. tables are created with relationship fields.

Now let´s save a fruit:

    $color = new \Model\color();
    $color
->name = "green";
    $color
->save();

    $fruit
= new \Model\fruit();
    $fruit
->name = "Kiwi";
    $fruit
->color = $color;
    $fruit
->save();

In "Fruits" table, Field color has now ID "1" which is the ID of "green" in color table.
In "Color" table, field "fruits" has Null.

Now let´s test it:

 $fruit = new \Model\fruit();
 $fruit
->load(array("name = ?", "kiwi"));
 echo
"A " . $fruit->name . " is " . $fruit->color->name;
 echo
"<hr>";

 $color = new \Model\color();
 $color->load(array("name = ?", "green"));
 $all = $color->castField('fruit');
 echo "> " . $color->name . " is a " . $all[0]['name'];
A) 


ends in:

A Kiwi is green
-
>
green is a

> It´s working in one direction 
– Is there a way to let cortex save also the counterpart relation in one shot where I saved the fruit in code example A) ?


Thank you!

ikkez

unread,
Aug 19, 2015, 5:09:30 AM8/19/15
to Fat-Free Framework
In "Color" table, field "fruits" has Null.

there should be no "fruit" column in the table. That bug was recently patched https://github.com/ikkez/f3-cortex/commit/c7f50e96ebaf0bf050be7284d424417401e0ab8f


> It´s working in one direction 
– Is there a way to let cortex save also the counterpart relation in one shot where I saved the fruit in code example A) ?

Your sample is wrong. Remember that you have multiple fruits using one color. 1:M is this:

echo "> " . $color->name . " fruits are: ";
if ($color->fruit)
foreach($color->fruit as $fruit)
echo $fruit->name.", ";

ikkez

unread,
Aug 19, 2015, 5:16:09 AM8/19/15
to Fat-Free Framework
You can even read that from your fieldConf:

'fruit' => array(
     
'has-many' => array('\Model\fruit','color'),
),

The field $color->fruit "has many" Fruit models... how could "many" be displayed? of course it must be an array here.

Anatol Buchholz

unread,
Aug 19, 2015, 5:45:14 AM8/19/15
to f3-fra...@googlegroups.com
A Kiwi is green
> green fruits are: Kiwi,

Great, great great! It´s of course working that way!
slowly feeds the squirrel … but I´m getting better ;))

thanks!


Now the ship is taking of

A Red Tomato is red
> red fruits are: Red Tomato, Chili,


ikkez

unread,
Aug 19, 2015, 6:38:51 AM8/19/15
to Fat-Free Framework
You can also get red fruits through the fruit model, instead of using the color model. here you can take advantage of the has-filter-method:

$fruitModel = new \Model\Fruit();
$fruits = $fruitModel->has('color',array('name = ?','red'))->find();
if ($fruits) {
echo "> Available fruits, which are red: ".implode(',',$fruits->getAll('name'));
} else {
echo "> There are no red fruits in store.";
}

find() returns a collection. The collection itself can be used as a usual array like foreach($fruits as $fruit), or use one of its helper functions: here ->getAll('name') just returns the name property of every fruit in a simple single array.

Anatol Buchholz

unread,
Aug 19, 2015, 8:24:34 AM8/19/15
to f3-fra...@googlegroups.com
AH-HA! Of course!

And as I read the documentation this way round is even better because

You can also add multiple has-conditions to different relations:

:))

As always, thanks a lot Ikkez!

… hopefully one day I can give back what I´ve learned from you!

Anatol Buchholz

unread,
Aug 21, 2015, 9:32:49 AM8/21/15
to f3-fra...@googlegroups.com
@Ikkez,

I started a little project with Cortex. It´s a website for some friends of mine who are type designers. 
I would have been already further with pure SQL but this seems to be perfect to get into ORM / cortex. 

May I ask some question which are unclear to me.

This is how my current setup looks like:


A Designer XY has designed many font families like "Helvetica", this Family can have many "SubFamilies" like "Condensed"

or "Extended". Each Subfamily has different weights like "regular", "bold", "boldItalic" and so on. The Diagramm shows

configuration fields which can also be seen here:



("Weights" could be more normalized but I would leave it like this for now)


My questions are:
  • Does this configuration layout makes sense to you?

  • Do I need the configuration "family" in "weights" to see to which family weights belong to?
    In other words can I cast all subfamilies and weights a family has without this configuration field as I already have the relation through subfamily?

  • If I´d like to know all things a designer did I would cast his relations down the road

     $designer = new \Model\designer;
     $result
    = $designer->load(array('_id = ?', 1));
       if ($result)
       $json
    = $result->cast(NULL, 3);


    In which case would I use castAll(); cast() seems to do the job.

  • Let´s say I added some designers to one font as they worked as team:

    if(!$family->designer)
      $family->designer = array($designer);
    else
      $family->designer[] = $designer;

    How would I remove one special ID again? For example Family->designer holds IDs "1;2;3" how would I remove '3' later?
    Do I just set the relation again but only with "1" and "2"?

  • Is it possible to add new records in "batch"? Let´s say I´ve uploaded a bunch of files which are "weights". I will receive an assoc array which should go into "weight". Do I just repeat save() and reset() in an foreach loop to iterate through the array? 

  • Let´s say I delete a family. Is it possible to tell Cortex to delete the relations as well, or do I have to take care if something is erased (designer, family, weights) that other models are updated as well?
       $family = new \model\ family;
       $
    family->erase(array('_id = 1'));
    • > mysql has for foreign keys ON DELETE CASCADE.

Buff, that´s a lot. As it´s mostly you who comes to help regarding Cortex I made another donation. 
-> go and get two crates of beer for you and your friends, weekend is coming!!

;))

thanks!

– Anatol

ikkez

unread,
Aug 21, 2015, 10:38:51 AM8/21/15
to f3-fra...@googlegroups.com
  • Does this configuration layout makes sense to you?
absolutely. looks good.
 
  • Do I need the configuration "family" in "weights" to see to which family weights belong to?
    In other words can I cast all subfamilies and weights a family has without this configuration field as I already have the relation through subfamily?
No you don't need that binding. You could go through the subfamilies to get the other part. With the filter propagation added in the last version, you could also filter down the road like $family->has('subfamily.weights',array('style = ?','bold')); to get only families that contains a subfamily that contains a bold style weight. BUT.. 1.) nested filtering on this is still experimental :D, but casting it is no problem and 2.) it would be less expensive to walk throught only 1 binding instead of two.. so you can keep that family <-> weights relation if you need to walk that road more often. The only drawback is that you need to update that relation as well, when you ever plan to move a subfamily to another family
 
  • If I´d like to know all things a designer did I would cast his relations down the road

     $designer = new \Model\designer;
     $result
    = $designer->load(array('_id = ?', 1));
       if ($result)
       $json
    = $result->cast(NULL, 3);


    In which case would I use castAll(); cast() seems to do the job.
yes
  • Let´s say I added some designers to one font as they worked as team:

    if(!$family->designer)
      $family->designer = array($designer);
    else
      $family->designer[] = $designer;

    How would I remove one special ID again? For example Family->designer holds IDs "1;2;3" how would I remove '3' later?
    Do I just set the relation again but only with "1" and "2"?
exactly. Probably you need to foreach through $family->designer and unset($family->designer[$i]) the model you want to drop. If a better way comes into your mind, let me know.

  • Is it possible to add new records in "batch"? Let´s say I´ve uploaded a bunch of files which are "weights". I will receive an assoc array which should go into "weight". Do I just repeat save() and reset() in an foreach loop to iterate through the array? 
yes. There`s currently no mass-insert feature build into cortex or the underlaying F3 mappers.
 
  • Let´s say I delete a family. Is it possible to tell Cortex to delete the relations as well, or do I have to take care if something is erased that other models are updated as well?
Yes that's possible. Entries in the pivot tables for m:m relations are handled out of the box. If you want to delete sub-families and weights when a family is dropped, you need to write an own handler for the delete event. There you can define your delete cascade. Basically it works like this:

$family = new \Model\family();
// setup delete cascade
$family->onerase(function($self){
$sf = new \Model\SubFamily();
$sf->erase(array('family = ?',$self->_id));
$w = new \Model\weights();
$w->erase(array('family = ?',$self->_id));
return true;
});

This is the fastest way, as ->erase($filter) will do a mass-delete. If you want to separate your code a bit more, and put the delete cascade for weights into the SubFamily controller or model, you cannot use a filter for erase(), because F3's mapper isn't calling the erase event for each record it deletes, because it does not know what will be deleted (what the "where" criterial matches). So what you can do to optimize this, if needed: you can extend the models __construct methods, and add a $this->onerase method for each model (family and subfamily).
family model:
public function __construct() {
$this->onerase(function($self){
$subFamilies = $self->SubFamily;
if ($subFamilies)
foreach($subFamilies as $subFamily)
$subFamily->erase();
return true;
});
parent::__construct();
}
and repeat that for your subfamily model, that deletes its weights.
Now once a family is deleted, it should detele the subfamily first, which will trigger the next onerase event and deletes its weights at the very first.
theoretically ;)
 
Buff, that´s a lot. As it´s mostly you who comes to help regarding Cortex I made another donation. 
-> go and get two crates of beer for you and your friends, weekend is coming!!

great !!! thank you very much and thanks for taking the effort to get into play with cortex. I will use your feedback to improve anything I can find =)
best regards.

Anatol Buchholz

unread,
Aug 21, 2015, 11:32:41 AM8/21/15
to Fat-Free Framework
Thanks Ikkez! 

your answers helped me a lot! The mass update would be a nice feature but on the other hand we´re looping all the
time in php, that´s something I can absolutely live with. I will rethink the table layout a bit, I think it´s needed to divide
"weights" and "filename", – no big job as configuration seems to be clear now ;)

Anyway.

I do my best to get into cortex but I´m also a bit afraid loosing PHP/SQL knowledge if I use it to much ;))

I will share further feedback and of course what I did with Cortex, FAL, Sheet, middleware or one of your other
great plugins !

cheers,

- anatol

Anatol Buchholz

unread,
Aug 26, 2015, 10:07:50 AM8/26/15
to Fat-Free Framework
Dear Ikkez,


if I delete an object which has a m-m relation the relationship table should take care of updating itself when something is deleted, right?

Family model:
 'designer' => array(
               
'has-many' => array('\Model\designer','family'),
           
),

Designer model
  'family' => array(
   
'has-many' => array('\Model\family','designer'),
   
),

creates a  relationship table called: designer__family_mm_family__designer
where I have relations between a family with id 3 and designers with ids 1,2,3

Designer | Family
1          3
2          3
3          3

Let´s get rid of that ugly gherkin:

    public function delete() {
        $f3
= \Base::instance();
        $this
->erase(array("_id = ?",3));
       
}

After that the family is gone but the relationship table stays untouched. 
What do I missunderstand?
Thankful for your hint ;)

Cheers,

– anatol

ikkez

unread,
Aug 26, 2015, 11:01:24 AM8/26/15
to Fat-Free Framework
unfortunately this doesn't work when a $filter was set in erase method. to workaround this, use load or findone method, and call ->erase(); on the hydrated record.

Anatol Buchholz

unread,
Aug 26, 2015, 12:25:36 PM8/26/15
to Fat-Free Framework
great ikkez,

thanks a lot!
Reply all
Reply to author
Forward
0 new messages