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 get all the related lineitem rows and save with main model

Hello,

I have a web page with Employee Id/Name etc and then the employees salary components as lineitems on the same web page. The Employee & Employee Component models are related by one->many relationship. User can modify the employee or component details (lineitems) on this web page as all fields are input boxes. How do I retrieve all the lineitem rows using php and invoke save of employee and all related records. The php code below gets just one lineitem row. I believe I will have to use jquery/javascript & ajax. Even if I use that, how do I pass the lineitem info to the PayEmpComponents class before save() is called. I believe I have to get all the employee components as lineitems and set them to empComp[0], empComp[1].... I have searched a lot on the internet but still am unclear how to do it. If somebody can give a code snippet that will be a big help. Some of my edit Action code in the controller looks like below:

            $employee->setHrEmpIid($this->request->getPost("hr_emp_iid", 'striptags'));
            $employee->setHrEmpId($this->request->getPost("hr_emp_id", 'striptags'));
            $employee->setHrEmpFname($this->request->getPost("hr_emp_fname", 'striptags'));
            $employee->setHrEmpLname($this->request->getPost("hr_emp_lname", 'striptags'));
            $employee->setHrEmpGender($this->request->getPost("hr_emp_gender", 'striptags'));
            $employee->setHrEmpDob($this->request->getPost("hr_emp_dob", 'striptags'));
            $employee->setHrEmpMob($this->request->getPost("hr_emp_mob", 'striptags'));
            $employee->setHrEmpDoj($this->request->getPost("hr_emp_doj", 'striptags'));

            //foreach (empComp)
            {
                $empComp = new PayEmpComponents() ;
                $empComp->setHrEmpIid($this->request->getPost("empComp_hr_emp_iid", 'striptags')) ;
                $empComp->setPayEmpCompoIid($this->request->getPost("empComp_pay_emp_compo_iid", 'striptags')) ;
                $empComp->setPayCompoIid($this->request->getPost("empComp_pay_compo_iid", 'striptags')) ;
                $empComp->setPayCompoPercent($this->request->getPost("empComp_pay_compo_percent", 'striptags')) ;
            }
            $employee->PayEmpComponents = $empComp ;

            if (!$employee->save()) {
                $this->flash->error($employee->getMessages());
            } else {
.....

Thanks in advance

First, refractor your code, why you just don't use:

$employee->assign($this->request->getPost(), $whitelist);

OR:

$employee->save($this->request->getPost(), $whitelist);

You remove so much boilerplate code this way.

Well basically yea, you need to use foreach and put them into array.



16.3k
edited Jun '16

@Wojciech Thanks for your inputs. If what you wrote works then it will help a lot in reducing my code. I read how to use whitelist & checked. Doesn't seem to work.

$whitelistEmp = ['hr_emp_iid', 'hr_emp_id', 'hr_emp_fname', 'hr_emp_lname', 'hr_emp_gender', 'hr_emp_dob', 'hr_emp_mob', 'hr_emp_doj', 'hr_payroll_basis', 'co_user_iid' ] ;
$employee->assign($this->request->getPost(), $whitelistEmp);
echo (new \Phalcon\Debug\Dump([], true))->variables($this->request->getPost()) ;//  exit();
echo (new \Phalcon\Debug\Dump([], true))->variables($employee) ;  exit();

I debugged, see the output, all the fields from getPost() on $employee are NULL

employee, create

var 0 Array (12) (
  [co_comp_iid] => Numeric string (1) "1"
  [co_location_iid] => Numeric string (1) "1"
  [hr_emp_iid] => Numeric string (1) "3"
  [hr_emp_id] => Numeric string (1) "3"
  [hr_emp_fname] => String (3) "EF3"
  [hr_emp_lname] => String (3) "EL3"
  [hr_emp_gender] => String (1) "M"
  [hr_emp_dob] => String (10) "2000-10-10"
  [hr_emp_mob] => String (0) ""
  [hr_payroll_basis] => String (1) "B"
  [hr_emp_doj] => String (10) "2010-10-10"
  [co_user_iid] => Numeric string (1) "1"
)

var 0 Object Baseapp\Models\HrEmployeeM extends Phalcon\Mvc\Model (
...
  ->*hr_emp_iid (public) = NULL
  ->*hr_emp_id (public) = NULL
  ->*hr_emp_fname (public) = NULL
  ->*hr_emp_mname (public) = NULL
  ->*hr_emp_lname (public) = NULL
  ->*hr_emp_gender (public) = NULL
  ->*hr_emp_dob (public) = NULL
  .....

Any suggestions. I faced other issues also but lets resolve this first.

To be honest i have no clue what's happening here. It should set correct values in model. Can you just check it with create method ?



16.3k

@Wojciech. I found the issue why assign was not working. The parameters for assign are not the same as for save. The second parameter is a column map. If a column map is present in the model then it can be null as I understand. Below works:

$employee->assign($this->request->getPost(), null, $whitelist);

My other issue is a bit complex. I have used a column name defined as arrays in my view volt file. This is to support multiple rows of data. I had to search hard to find ways to support multiple rows.

{% for d1 in empComponents %}
<tr>
    <td align="left">{{ text_field("pay_emp_compo_iid[]", "size" : 10, 'value' : d1.pay_emp_compo_iid ) }}</td>
    <td align="left">{{ text_field("pay_compo_iid[]", "size" : 10, 'value' : d1.pay_compo_iid ) }}</td>
    <td align="right">{{ text_field("pay_compo_amt[]", "size" : 20, 'value' : d1.pay_compo_amt, 'style' : "text-align:right;" ) }}</td>
    <td align="right">{{ text_field("pay_compo_monthly_amt[]", "size" : 20, 'value' : d1.pay_compo_monthly_amt, 'style' : "text-align:right;" ) }}</td>
    <td align="right">{{ text_field("pay_compo_percent[]", "size" : 10, 'value' : d1.pay_compo_percent, 'style' : "text-align:right;" ) }}</td>
    <td align="left">{{ text_field("pay_compo_perc_amt[]", "size" : 1, 'value' : d1.pay_compo_perc_amt ) }}</td>
</tr>
{% endfor %}

Now if I use assign it places the whole array in a single object:

$whitelistEmpComps = [ 'pay_compo_iid', 'pay_compo_amt', 'pay_compo_monthly_amt', 'pay_compo_percent', 'pay_compo_perc_amt' ] ;
$empComp->assign($this->request->getPost(), null, $whitelistEmpComps);

Is there a way to get each of them into a single $empCompo. Any suggestions on how to do it. Or do I have to set each value like I did in my first post.

for ($liIndex = 0 ; $liIndex < $empCompoCount; $liIndex++ )
{
    $empCompo->setPayEmpCompoIid($_POST["pay_emp_compo_iid"][$liIndex], 'striptags') ;
    $empCompo->setPayCompoIid($_POST["pay_compo_iid"][$liIndex], 'striptags') ;
    $empCompo->setPayCompoAmt($_POST["pay_compo_amt"][$liIndex], 'striptags') ;
    $empCompo->setPayCompoMonthlyAmt($_POST["pay_compo_monthly_amt"][$liIndex], 'striptags') ;
    $empCompo->setPayCompoPercent($_POST["pay_compo_percent"][$liIndex], 'striptags') ;
    $empCompo->setPayCompoPercAmt($_POST["pay_compo_perc_amt"][$liIndex], 'striptags') ;
}

Thanks