I am able to save associated records in cakephp3 but if you look at the code , the records are not saved all at once with 1 save call.
I did have a problem trying to save all the records at once. If you look at how its done you see the Guardian and Users table are save separately.
The code works and saves the records but saving all at once in 1 save call has been an issue as I got an error on the guardian table.
Guardians have a 1 to many relationship with students
Students and Users have a 1 to 1
Students to subjects and availabilityFotStudents both have a many to many
Code
public function add($gId=0) {
$this->loadModel("Guardians");
$this->loadModel('PaymentTypes');
$this->set("title","Add Student");
$guardians=null;
if ($gId>0){
$guardians =$this->Guardians->get($gId);
}
if ($this->request->is('post')) {
if ( $this->request->data['studenttype']==0){ //enquiry
$this->request->data['students']['address_billing'] = 0;
$this->request->data['students']['student_enq'] = 1;
}
else if ( $this->request->data['studenttype']==1){ //waitlist
$this->request->data['students']['address_billing'] = 1;
$this->request->data['students']['student_enq'] = 0;
}
else if ( $this->request->data['studenttype']==2){ //skip waitlist
$this->request->data['students']['address_billing'] = 4;
$this->request->data['students']['student_enq'] = 0;
}
if ( $this->request->data['students']['tutoring_typest_id']==1){
$this->request->data['students']['group_status']=0;
}
else if ( $this->request->data['students']['tutoring_typest_id']>1){
$this->request->data['students']['group_status']=1;
}
if ($this->request->data['students']['tutoring_typest_id']==3 ){//group only
$this->request->data['students']['address_billing'] = 4;
}
$data = $this->request->data;
// debug($data);
$uname= $this->request->data['Users']['username'];
if ($this->Students->Users->findByUsername($uname)->count()) {
$this->Flash->error(__('Username exists. Please, try again.'));
return $this->redirect(["action"=>"add",$gId]);
}
$userId=0;
$entity = $this->Students->Users->newEntity($this->request->data['Users'],['validate'=>false]);
$entity->role = "student";
$entity['role_id'] = 4;
$entity = $this->Students->Users->save($entity);
// debug( $entity);
$studentUserId = $entity->id;
if($guardians==null) {
$guardians = $this->Guardians->newEntity($this->request->data['guardians'], ['validate' => false]);
}
$guardianEntity = $this->Guardians->save($guardians);
$guardians = $this->Students->newEntity();
$studentData = $this->request->data['students'];
$studentData['subjects'] = $this->request->data['subjects'];
$studentData['availability_for_students'] = $this->request->data['availability_for_students'];
$studentEntity = $this->Students->patchEntity($guardians,$studentData,
[
"validate"=>false,
'associated' => [
"AvailabilityForStudents"=>["validate"=>false],
"Subjects"=>["validate"=>false]
]
]
);
$studentEntity->guardian_id = $guardianEntity->id;
$studentEntity->user_id = $studentUserId;
$studentEntity = $this->Students->save($studentEntity,
[
"validate"=>false,
'associated' => [
"AvailabilityForStudents"=>["validate"=>false],
"Subjects"=>["validate"=>false]
]
]
);
if ($studentEntity) {
$this->Flash->success(__('The student has been saved'));
return $this->redirect(["action"=>"index2"]);
} else {
$this->Flash->error(__('The student could not be saved. Please, try again.'),'flash_alert');
}
}//post
$subjects = $this->Students->Subjects->find('list', array( 'order' => array('Subjects.name' => 'asc') ));
$weekdays = $this->Students->weekDays;
$tutoringTypes = $this->Students->TutoringTypeStudents->find('list');
//$payments = $this->Student->paymentOptions;
$this->PaymentTypes->primaryKey("name");
$payments = $this->PaymentTypes->find( 'list', array(
'fields' => array('PaymentTypes.name','PaymentTypes.name')) );
$referrals = $this->Students->Referrals->find('list');
$tutorGender = $this->Students->Lessons->Tutors->tutorGender;
$this->set('guardians', $guardians);
$this->set(compact('referrals','subjects', 'tutoringTypes', 'weekdays','payments','tutorGender'));
}
you can use Tranactional data save. Where you can run multiple save method. if any save method failed then no data will be save. so it works like "1 save call" which you mentioned
Related
I have an issue with one of API, where this API will create Order information. Each Order represents 1 buyer with multiple items. I want to loop the items in my API method. But, when I try to loop the function, it only stores the first array value, which is not what I want. I want to store a whole array of values to the Database.
Here is the API Code:
$s = $data->ItemIDs;
if($order->CreateOrderInfo()){
echo 'Order created successfully.';
echo "---";
for($i = 0; $i < sizeof($s); $i++){
$order->ItemCode = $s[$i];
$order->GetItemInfo();
if ($order->ItemCode != null){
$item_array = array(
'UserMememberNo' => $order->UserMememberNo,
'Image' => $order->Image,
'Description' => $order->Description,
'Price' => $order->Price,
'ItemBrand' => $order->ItemBrand,
'ItemModel' => $order->ItemModel
);
//GET DATA FOR ITEM TABLE
$order->ItemGUID = $data->ItemGUID;
$order->ItemName = $order->Description;
$order->ItemPrice = $order->Price;
$order->ItemQuantity = $data->ItemQuantity;
$order->ItemVariation1 = $data->ItemVariation1;
$order->ItemVariation2 = $data->ItemVariation2;
$order->ItemVariation3 = $data->ItemVariation3;
$order->ItemVariation4 = $data->ItemVariation4;
$order->ItemVariation5 = $data->ItemVariation5;
}
else{
echo json_encode('No item Found');
}
if($order->CreateItemInfo())
{
echo 'Item created';
}else{
echo 'Unable to create item';
echo '----';
}
}
if($order->CreateBuyerInfo()){
echo 'Buyer information created';
}else{
echo 'Unable to create buyer information';
}
Here is the model. This model is for inserting the values into the Database:
//CREATE FUNCTION FOR ITEM TABLE
public function CreateItemInfo() {
$sqlQuery = "INSERT INTO ".$this->item_info_table."
SET
GUID = :GUID,
ItemGUID = :ItemGUID,
ItemName = :ItemName,
ItemPrice = :ItemPrice,
ItemQuantity = :ItemQuantity,
ItemVariation1 = :ItemVariation1,
ItemVariation2 = :ItemVariation2,
ItemVariation3 = :ItemVariation3,
ItemVariation4 = :ItemVariation4";
$stmt = $this->conn->prepare($sqlQuery);
$this->GUID = htmlspecialchars(strip_tags($this->GUID));
$this->ItemGUID = htmlspecialchars(strip_tags($this->ItemGUID));
$this->ItemName = htmlspecialchars(strip_tags($this->ItemName));
$this->ItemPrice = htmlspecialchars(strip_tags($this->ItemPrice));
$this->ItemQuantity = htmlspecialchars(strip_tags($this->ItemQuantity));
$this->ItemVariation1 = htmlspecialchars(strip_tags($this->ItemVariation1));
$this->ItemVariation2 = htmlspecialchars(strip_tags($this->ItemVariation2));
$this->ItemVariation3 = htmlspecialchars(strip_tags($this->ItemVariation3));
$this->ItemVariation4 = htmlspecialchars(strip_tags($this->ItemVariation4));
$stmt->bindParam(":GUID", $this->GUID);
$stmt->bindParam(":ItemGUID", $this->ItemGUID);
$stmt->bindParam(":ItemName", $this->ItemName);
$stmt->bindParam(":ItemPrice", $this->ItemPrice);
$stmt->bindParam(":ItemQuantity", $this->ItemQuantity);
$stmt->bindParam(":ItemVariation1", $this->ItemVariation1);
$stmt->bindParam(":ItemVariation2", $this->ItemVariation2);
$stmt->bindParam(":ItemVariation3", $this->ItemVariation3);
$stmt->bindParam(":ItemVariation4", $this->ItemVariation4);
if($stmt->execute()) {
return true;
}
return false;
}
A screenshot below shows the issue, where only the first value of the array is successfully inserted to the Database.
Result of Database Insert
i have 1 million data using foreach.
ex table:
table
the data
data
i want to inserting that's data using batch/multipleinsert, but i have problem when i got duplicate data. if data duplicate i want the field amount will sum and update amount field with sum amount duplicated data.
this is my code before
<?php
foreach ($data_transaksi as $key)
{
if($key['STATUS_COA'] != $key['CHART_OF_ACCOUNT_STATUS'])
{
if($key['ACCOUNT_CATEGORY_CODE'] == '9')
{
$amount = round($key['AMOUNT'],2);
}
else
{
$amount = round($key['AMOUNT'],2) *-1;
}
}
else
{
if($key['ACCOUNT_CATEGORY_CODE'] == '9')
{
$amount = round($key['AMOUNT'],2)*-1;
}
else
{
$amount = round($key['AMOUNT'],2);
}
}
$dt_exsis = $this->ledger_model->cek_data_coa_exsis($key['COA_CODE'],$modul,$ID_USER);
if(empty($dt_exsis['id']))
{
//TRYINSERTINGBATCH
// $datainsert[] = '('.$key['COA_CODE'].','.$amount.','.$ID_USER.',"'.$modul.'")';
// $test = $key['COA_CODE'];
$datainput = array(
'COA_CODE' => $key['COA_CODE'],
'AMOUNT' => $amount,
'MODUL' => $modul,
'USER_ID' => $ID_USER
);
$this->ledger_model->save_rows_to_table($datainput,'finance_lapkue_temp');
}
else
{
$amount_fix = $amount + $dt_exsis['AMOUNT'];
$data=array(
'AMOUNT' => $amount_fix
);
$this->ledger_model->edit_rows_to_table_where($data,'finance_lapkue_temp','id',$dt_exsis['id']);
// $q = "UPDATE finance_lapkue_temp set AMOUNT = '$amount_fix' where id = '".$dt_exsis['id']."'";
// $this->db->query($q);
}
// $data_amount[$key['COA_CODE']] += $amount;
}
?>
if i using this code, the proccess so slow
Good option will to pass only data to DB that you want to insert. All the data cleaning task can be done in controller.
// Create a data array and add all info
$data = [];
//if user does not exist add it in array
if (empty($dt_exist($id))) {
$data[$ID_USER] = array(
'COA_CODE' => $key['COA_CODE'],
'AMOUNT' => $amount,
'MODUL' => $modul,
'USER_ID' => $ID_USER
);
}
else {
//if user exist in $data just modify the amount
if (!empty($data[$ID_USER])) {
$data[$ID_USER]['AMOUNT'] += $dt_exsis['AMOUNT'];
}
else {
// if user does not exist in data create add all info
$data[$dt_exsis['ID_USER']] = array(
'COA_CODE' => $dt_exsis['COA_CODE'],
'AMOUNT' => $dt_exsis['amount'],
'MODUL' => $dt_exsis['modul'],
'USER_ID' => $dt_exsis['ID_USER']
);
}
}
This will save multiple calls to DB and at the end you can pass $data and do multiple insert.
I have a table that I have recently edited to add another index using two columns (which combined are required to be unique).
The problem is now I get an error when I go to create a new model record:
Integrity constraint violation: 1062 Duplicate entry ... for key ....
The two columns are titled:
shipment_origin
pro_number
So as an example, the end result would look like: 1-230185
And I have checked, the record is created technically, it just doesn't follow through and the error is returned. So to make it simple, there is no record before hand (so there's no duplicate entry), a record is created in the database and the error is returned (no matter what).
Or is there a way to go about doing this directly through Laravel rather than MySQL?
Update
Here is the public function in my controller:
public function store(Request $request)
{
$this->validate(request(), [
'pro_number' => 'required',
'shipment_origin' => 'required'
/*'piecesNumber' => 'required' (had to remove for now, but must review)*/
]);
$user_id = Auth::id();
$input = $request->all();
//Save Initial Shipment Data
$shipment = new Shipment();
$shipment->pro_number = request('pro_number');
$shipment->shipment_origin = request('shipment_origin');
$shipment->date = request('date');
$shipment->due_date = request('due_date');
$shipment->tractor_id = request('tractor_id');
$shipment->trailer_id = request('trailer_id');
$shipment->driver_id = request('driver_id');
$shipment->notes = request('notes');
$shipment->shipper_no = request('shipper_no');
$shipment->ship_to = request('ship_to');
$shipment->ship_from = request('ship_from');
$shipment->bill_to = request('bill_to');
$shipment->bill_type = request('bill_type');
$shipment->load_date = request('load_date');
$shipment->shipment_status = 1;
$shipment->shipment_billing_status = (isset($request->shipment_billing_status) && !empty($request->shipment_billing_status)) ? $request->shipment_billing_status : 1;
$shipment->created_by = $user_id;
$shipment->cn_billtoName = request('cn_billtoName');
$shipment->cn_billtoAddress1 = request('cn_billtoAddress1');
$shipment->cn_billtoAddress2 = request('cn_billtoAddress2');
$shipment->cn_billtoCity = request('cn_billtoCity');
$shipment->cn_billtoState = request('cn_billtoState');
$shipment->cn_billtoZip = request('cn_billtoZip');
$shipment->cn_billtoEmail = request('cn_billtoEmail');
$shipment->cn_billtoPhone = request('cn_billtoPhone');
$shipment->cn_shiptoName = request('cn_shiptoName');
$shipment->cn_shiptoAddress1 = request('cn_shiptoAddress1');
$shipment->cn_shiptoAddress2 = request('cn_shiptoAddress2');
$shipment->cn_shiptoCity = request('cn_shiptoCity');
$shipment->cn_shiptoState = request('cn_shiptoState');
$shipment->cn_shiptoZip = request('cn_shiptoZip');
$shipment->cn_shiptoEmail = request('cn_shiptoEmail');
$shipment->cn_shiptoPhone = request('cn_shiptoPhone');
$shipment->cn_shipfromName = request('cn_shipfromName');
$shipment->cn_shipfromAddress1 = request('cn_shipfromAddress1');
$shipment->cn_shipfromAddress2 = request('cn_shipfromAddress2');
$shipment->cn_shipfromCity = request('cn_shipfromCity');
$shipment->cn_shipfromState = request('cn_shipfromState');
$shipment->cn_shipfromZip = request('cn_shipfromZip');
$shipment->cn_shipfromEmail = request('cn_shipfromEmail');
$shipment->cn_shipfromPhone = request('cn_shipfromPhone');
$shipment->fuelChargeDesc = request('fuelChargeDesc');
$shipment->fuelChargeAmt = request('fuelChargeAmt');
$shipment->fuelChargeTotal = request('fuelChargeTotal');
$shipment->permitChargeDesc = request('permitChargeDesc');
$shipment->permitChargeAmt = request('permitChargeAmt');
$shipment->permitChargeTotal = request('permitChargeTotal');
$shipment->otherChargeDesc = request('otherChargeDesc');
$shipment->otherChargeAmt = request('otherChargeAmt');
$shipment->otherChargeTotal = request('otherChargeTotal');
$shipment->noCharge = request('noCharge');
$shipment->noSettle = request('noSettle');
$shipment->Total = request('Total');
if ((request('shipment_billing_status') == 2) || (request('shipment_billing_status') == 3)){
$balance = 0.00;
}else{
$balance = request('Total');
}
$shipment->Balance = $balance;
$shipment->freightBillSubtotal = request('freightBillSubtotal');
$shipment->save();
//Save Shipment Details
for ($i = 0; $i < count($request->shipment_details['piecesNumber']); $i++) {
//the first line used to be 'shipment_id' => $shipment->pro_number,
Shipment_Detail::create([
'shipmentID' => $shipment->id,
'pieces_number' => $request->shipment_details['piecesNumber'][$i],
'pieces_type' => $request->shipment_details['piecesType'][$i],
'rate_type' => $request->shipment_details['rateType'][$i],
'charge' => $request->shipment_details['charge'][$i],
'weight' => $request->shipment_details['weight'][$i],
'hazmat' => $request->shipment_details['hazmat'][$i],
'description' => $request->shipment_details['description'][$i] ]);
}
$carrier = \App\Customer::where('carrier','=',1)->get();
foreach($carrier as $car){
$carrierUsers = $car->users;
if ($carrierUsers->count() > 0){
foreach($carrierUsers as $carrierUser){
$carrierUser->notify(new FreightBillNew($shipment));
}
}
}
Session::flash('success_message','Freight Bill Successfully Created'); //<--FLASH MESSAGE
//Return to Register//
return redirect('/shipments/accounts');
}
I have a GridView and 6 filter options placed on radio buttons. When I click a filter, the GridView will change based on the filter being clicked. Here's a picture:
Now, I want to get the total Converted Amount of the table based on the filter chosen. For example, if I choose Draft filter, the table will show all Draft reimbursements and will sum up its Converted Amount and total will be placed at the top right side above the table as shown in the photo.
I tried googling solutions for this one but I find no answer. Here's a snippet of my code in my controller:
$refreshData = false;
if (isset(Yii::$app->request->getBodyParams()['sortby'])) {
$refreshData = true;
$sortby = Yii::$app->request->getBodyParams()['sortby'];
} else {
$sortby = 'Show All';
$dataProvider = new ActiveDataProvider([
'query' => Reimbursement::find()->where(['company_id' => new \MongoId($session['company_id'])])
]);
}
// get all reimbursements
$reimbursements = Reimbursement::findAll(['company_id' => new \MongoId($session['company_id'])]);
if (isset(Yii::$app->request->getBodyParams()['sortby'])) {
if(Yii::$app->request->getBodyParams()['sortby'] != '' && Yii::$app->request->getBodyParams()['sortby'] != 'Show All') {
$refreshData = true;
$reimbursements = Reimbursement::findAll(['company_id' => new \MongoId($session['company_id']), 'status' => Yii::$app->request->getBodyParams()['sortby']]);
// $ids = [];
// foreach ($reimbursements as $i => $model) {
// $ids[] = $model['_id'];
// }
// $command = Yii::$app->db->createCommand('SELECT sum(total) FROM estimate WHERE `_id` IN ('.implode(',',$ids).')'); // please use a prepared statement instead, just a proof of concept
// $sum = $command->queryScalar();
} elseif (Yii::$app->request->getBodyParams()['sortby'] == 'Show All') {
$refreshData = true;
}
}
$dataProvider = new ArrayDataProvider([
'allModels' => $reimbursements,
]);
if($refreshData) {
return $this->renderPartial('_index', [
'dataProvider' => $dataProvider,
]);
}
$dataProvider->pagination->pageSize = 10;
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'rModel' => $rModel,
]);
As you may have noticed I commented some lines of code below if(Yii::$app->request->getBodyParams()['sortby'] != '' && Yii::$app->request->getBodyParams()['sortby'] != 'Show All') condition. I tried that one and it doesn't work.
How do I implement this?
$reimbursements = Reimbursement::find()->where(['company_id' => new \MongoId($session['company_id'])]);
if (isset(Yii::$app->request->getBodyParams()['sortby'])) {
$refreshData = true;
$sortby = Yii::$app->request->getBodyParams()['sortby'];
$reimbursements->andWhere(['status' => Yii::$app->request->getBodyParams()['sortby']]);
} else {
$refreshData = false;
$sortby = 'Show All';
}
$dataProvider = new ActiveDataProvider([
'query' => $reimbursements,
]);
$totalSum = $reimbursements->sum('total');
I'm trying to prevent the user to create the same username. well my real problem is how to loop a list of data from model in controller. Maybe we know how to loop it in view by using this -> data['user'] and in view we can call $user. but how can we do that in controller layer.
here's my code
Controller
$username = strtolower($this->input->post('name'));
$fixUsername = str_replace(" ",".",$username);
$counter = 1;
$list[] = $this->addusermodel->getAllUsername();
for($i=0;$i<sizeof($list);$i++) {
if($list[$i] == $fixUsername) {
$counter = 0;
}
}
if($counter == 0) {
$data['result'] = "The username has already been taken";
$this->load->view('adduserview',$data);
} else {
$data = array(
'Nama' => $this->input->post('name'),
'Username' => $fixUsername."#praba",
'Password' => md5($this->input->post('password')),
'created' => date("Y-m-d h:i:sa"),
'createdBy' => $createdBy,
'lastModified' => date("Y-m-d h:i:sa"),
'lastModifiedBy' => $lastModifiedBy
);
$this->addusermodel->saveUser($data);
//$data['Username'] = $listName;
$data['message'] = "New user successfully added.";
$data['messageContent'] = "The username: ".$fixUsername."#praba". $counter;
$this->load->view('successpageview',$data);
//redirect('successpageview','refresh');
}
my model (is like usual)
function getAllUsername() {
$this->db->select('Username');
$this->db->from('tbluser');
$query = $this->db->get();
return $query->result_array();
}
I think a better approach would be to create another function in your model, which searches your database by ID, or by email, or by another unique field. If the function returns a row - then the user exists. If it returns nothing - then add a new user.