We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

How to update few related records?

Hi,

I create related records in accordance with the documentation:

 $model = new Properties();
 //.....
 $content = [];

  foreach ($this->request->getPost('params') as $param){
      $params = new PropertiesParams();
      $params->sort_id = $param['sort_id'];  
      $params->name = trim($param['name']);

      $content[] = $params;
  }

$model->Params = $content;

//...

if ($model->save()) {
//...           
}

When user is editing these records, I'm updating changes by following way:

$model = Properties::findFirst($id);

//...
$content = [];

foreach ($this->request->getPost('params') as $param){
  $params = new PropertiesParams();
  $params->sort_id = $param['sort_id'];
  $params->name = trim($param['name']);

  $content[] = $params;
}

$model->Params->delete();
$model->Params = $content;

if ($model->save()) {
//..
}

In this case I'm deleting all old records before creating new. How to do this without deleting old records, just update them if it's needed or if user add new record - create it ?

I need to provide editing of all related records, not a single record.

Thanks for your replies.

edited Sep '16

How you know what is old record what not ? name is unique ? In this second example as i understand you got $param['id'] as well or something ?

How you know what is old record what not ? name is unique ? In this second example as i understand you got $param['id'] as well or something ?

Yes, I have $param['id'] and it is unique value

edited Sep '16

Is it id of Property or PropertiesParams ? I don't quite understand your relations. PropertiesParams is many to many intermediate model ?

Is it id of Property or PropertiesParams ? I don't quite understand your relations. PropertiesParams is many to many intermediate model ?

Yes, It's id of PropertiesParams. Relation: Property has many PropertiesParams

edited Sep '16

Something like this:

BEFORE:

Albums
id | arisit_id | name
1 | 1 | Born to Die

Songs
id | albums_id | name
1 | 1 | some name
2 | 1 | some name
3 | 1 | some name
4 | 1 | some name
5 | 1 | some name
6 | 1 | some name
7 | 1 | some name
class Albums extends Model
{
    public function initialize()
    {
        $this->hasMany('id', 'Songs', 'albums_id', ['alias' => 'songs']);
    }
}

class Songs extends Model
{
    public function initialize()
    {
        $this->belongsTo('albums_id', 'Albums', 'id', ['alias' => 'album']);
    }
}

$params = [
    [
        'id' => 1,
        'name' => 'abc',
    ],
    [
        'id' => 2,
        'name' => '123',
    ],
    [
        'id' => null,
        'name' => 'xyz',
    ],
];
$album = Albums::findFirst(1);
$currentSongs = $album->getRelated('songs'); //theere is a bug where we can't use songs alias
$ids = [];
$content = [];
foreach ($params as $param) {
    if (!empty($param['id'])) {
        $song = Songs::findFirst($param['id']);
        $ids[] = $param['id'];
    } else {
        $song = new Songs();
    }
    $song->name = $param['name'];
    $song->artists_id = 1;
    $content[] = $song;
}
$oldSongs = $currentSongs->filter(
    function ($song) use ($ids) {
        if (!in_array($song->id, $ids)) {
            return $song;
        }
    }
);
$album->songs = $content;
foreach ($oldSongs as $oldSong) {
    $oldSong->delete();
}
$album->save();

After:

Songs

1 | 1 | abc
2 | 1 | 123
12 | 1 | xyz

If you don't really want to delete them then just:

$album = Albums::findFirst(1);
$content = [];
foreach ($params as $param) {
    if (!empty($param['id'])) {
        $song = Songs::findFirst($param['id']);
    } else {
        $song = new Songs();
    }
    $song->name = $param['name'];
    $song->artists_id = 1;
    $content[] = $song;
}
$album->songs = $content;
$album->save();

Something like this:

Thank you. I've thought about this option. I was hoping that there are built-in solutions on the ORM level. As I understand it, I need to handle it manually?



145.0k
Accepted
answer
edited Sep '16

Im guessing you can override some methods. ORM shouldn't really do stuff like that.