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 use related models in form and create/update records?

My question is: how to use/access related model properties in forms? I have 2 models: "Posts" and "Articles". Articles model depends on Posts model in "hasOne" relationship.

SQL

CREATE TABLE IF NOT EXISTS `posts` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `slug` varchar(255) NOT NULL,  
  `uid` int(11) NOT NULL,
  `shortdesc` varchar(255) NOT NULL,
  `views` int(11) NOT NULL DEFAULT '0',
  `rating` int(11) NOT NULL DEFAULT '0',
  `status` tinyint(2) NOT NULL DEFAULT '0',
  `type` varchar(255) NOT NULL,  
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `posts_articles` (
  `article_id` int(11) NOT NULL AUTO_INCREMENT,
  `post_id` bigint(20) unsigned NOT NULL,
  `banner` varchar(255) NOT NULL,
  `content` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`article_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

MODELS

class Posts extends \Phalcon\Mvc\Model
{
    public function getSource()
    {
        return 'posts';
    }
    public function initialize()
    {
        $this->hasOne('ID', 'Common\\Models\\Articles', 'post_id', array(
            'alias' => 'article',
            'foreignKey' => array(
                'action' => Relation::ACTION_CASCADE
            )
        ));
    }
}

class Articles extends \Phalcon\Mvc\Model
{
    public function getSource()
    {
        return 'posts_articles';
    }
    public function initialize()
    {
        $this->belongsTo('post_id', 'Common\\Models\\Posts', 'ID', array('alias' => 'post'));
    }
}

FORM I wont post whole form since it would take too much space here, but I followed official documentation and form is created correctly, same as form fields. Here is only how Im using form fields. As you can see above, where SQL code is, "content" field belongs to Articles model/table. Form fields in view are called using $form->render("--FORM FIELD NAME--"), for example $form->render("content"). I had tried to use $form->render("article_content") but that didnt do nothing.

// post content field
$post_content = new Textarea('content');
$post_content->addValidators(array(
    new PresenceOf(array(
        'message' => 'Content area cannot be empty'
    ))
));
$this->add($post_content);

CONTROLLER EDIT ACTION When I want to validate form and save/update data only data/form fields from Posts table gets validated and saved. Update action ignores fields from Articles table.

    public function editAction($id)
    {
        $post = Posts::findFirstByID($id);

        $form = new EditPostForm($post, array('edit' => true));
        $this->view->form = $form;
        $data = $this->request->getPost();

        if(!$this->request->isPost())
        {
            if(!$post)
            {
                $this->flash->error('Post was not found');
                return $this->dispatcher->forward(array('controller' => 'posts', 'action' => 'index'));
            }
        }
        // Check if "Update" is pressed
        if($data)
        {
            if(!$form->isValid($data, $post))
            {
                foreach($form->getMessages() as $message)
                {
                    $this->flash->error($message);
                }
            }
            if(!$post->save() == false)
            {
                $form->clear();
                $this->flash->success('Post was updated successfully');
            }
        }
        $this->view->setVar('post', $post);
    }

Problem is, how to access properties of related model in form and how to update/create records that way? Form fields from Posts table are recognized during updating and are saved, while fields from Articles table are not saved for some reason. I think Im doing something wrong with model relationships but I dont know what, since Im still learning how to use PhalconPHP. Code shown here is used by edit action in controller, used for editing articles, like Wordpress.



11.6k

if you've defined a soft relationship, when you retrieve your data, datas from related models are available at i.e. $post->post_articles. Create form elements that match columns names of your related model, populate them from $post->post_articles->columnName.

When saving, get the post datas back to create a new instance or to edit an existing related model instance [[ $postArticle = new Postarticle(); or $postArticle = Postarticle::findFirst($sortingParam); ]] and assign post datas to it. Then just do [[ $post->post_articles = $postArticle; $post->save(); ]] . thank to the soft relation, the two models will be saved