cakephp checking for duplicate rows - php

I have been at this for 5 days now. I read all the answers I could here, I have tried any options I could I cannot find how to fix this cache issue.
I am using cakephp 2.4.4 which could be upgraded but I did not see my issue in any of the change.log
Percona MYSQL 5.6 Innodb
We have a model that we call in a loop to insert rows
App::import('Model', 'TableA');
$TableA = new TableA();
foreach($rows as $row){
$TableA->InsertRow($row);
}
Then we have the Model for TableA
I added a Unique Index on TableA.Sku to avoid duplicate entry
class TableA extends AppModel {
var $name = 'TableA';
var $cacheQueries = false;
var $validate = array();
function InsertRow($data){
$this->clear();
try {
$result = $this->find('first', array(
'fields' => array(
'TableA.id',
),
'conditions' => array(
'TableA.Sku' => $data['Sku'],
),
));
pr($result);
if(!isset($result['TableA']['id'])){
$data['TimeStamp'] = strtotime("now");
$this->save($data);
}
return TRUE;
}
catch (Exception $e) {
pr($e);
$resultNow = $this->find('first', array(
'fields' => array(
'TableA.id',
),
'conditions' => array(
'TableA.Sku' => $data['Sku'],
),
));
pr($resultNow);
}
}
}
The first loop $Rows has multiple time the same sku following each other
the first loop insert the row
the 2nd loop gives:
array
(
)
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'tue026991015' for key 'Sku'
INSERT INTO `ki`.`TableA` (`Sku`, `TimeStamp`) VALUES ('tue026991015', 1453858976)
Array
(
[TableA] => Array
(
[id] => 31951
)
)
I am also running in Debug Mode 2
In the 2nd loop the query should return the id and the loop should not try to insert the row but it is not.
I added var $cacheQueries = false; on top of the Model to avoid cashing. I am at a loss as to why this behavior is happening and how to avoid any mysql cashing for this function.

It happens when the user clicks "refresh" data or happens when you fill out the form and add user data gives? Which method you use to collect the GET or POST data?

Related

php CI $this->cart->insert($data) get null value

I get stack in script. I used Code Igniter ver. 3.1.10. I use cart library in my controller
here my controller
public function add_to_cart()
{
$idit=$this->input->post('id_item');
$product=$this->Salesmodel->get_item($idit);
$i=$product->row_array();
$data = array(
'id' => $i['id_item'],
'name' => $i['name_item'],
'main_price' => $i['main_price'],
'sell_price' => $i['sell_price'],
);
$this->cart->insert($data);
$rows = count($this->cart->contents()); // I want to find out rows count and result is null
echo $i['id_item']; //get value, not null
echo $rows; // get '0'
}
model.php
function get_item($idit)
{
$rslt=$this->db->query("SELECT * FROM tb_item where id_item='$idit'");
return $rslt;
}
but in that script i always get null row count of the cart.
I have to add this script in config.php :
$config['sess_use_database'] = TRUE;
I also created a new table with a name
ci_session
but that returns the same result, my cart always has null row count and null data. Please help me with an error in the script that I made.
Thanks in advance
In order to save into the cart properly, these 4 array index are required :
id - Item identifier.
qty - Item quantity.
price - Item price.
name - Item name.
And the 5th index are options, which you could store all the additional attribute you need (should be an array though).
So you could modify the $data array like this :
$data = array(
'id' => $i['id_item'],
'qty' => 1, // here I just manually set it to 1
'name' => $i['name_item'],
'price' => $i['main_price'], // here I changed 'main_price' index to 'price'
'options' => array('sell_price' => $i['sell_price']) // moved the 'sell_price' array here
);

laravel Insert or update related records

I'm having trouble updating and creating related records depending on if they exist or not. I want to update the ingredient if they exist, if not insert the ingredient into the database and relate it to the current meal.
public function update($id)
{
$meal = Meal::find($id);
$meal->name = Input::get('name');
// create ingredients
$ingredients = Input::get('ingredient');
$meal_ingredients = array();
foreach($ingredients as $ingredient)
{
$meal_ingredients[] = new Ingredient(array(
'name' => $ingredient['name'],
'unit' => $ingredient['unit'],
'quantity' => $ingredient['quantity']
));
}
//save into the DB
$meal->save();
$meal->ingredients()->saveMany($meal_ingredients);
// redirect
Flash::success('Votre repas a bien été mis à jour!');
return Redirect::to('/meals');
}
Step 1 : Get Meal
$meal = Meal::find($id);
Step 2 : Get Ingredients of Meal (create relation for this)
$ingredients = $meal->ingredients;
Step 3 : Compare Input to current and add does not exist
$new_ingredients = array();
foreach($ingredients as $ingredient)
{
if(!in_array($ingredient->toArray(), Input::get('ingredient')) {
$new_ingredients[] = new Ingredient(array(
'name' => $ingredient['name'],
'unit' => $ingredient['unit'],
'quantity' => $ingredient['quantity']
));
}
}
Step 4 Update
$meal->ingredients->saveMany($new_ingredients);
Ensure you got the relation between meal and ingredient correctly
You can use the firstOrNew() method. You pass it an array of data, and it will return the first record that matches that data, or if no record is found, a new instance of the class with the searched fields already set.
foreach($ingredients as $ingredient)
{
$meal_ingredients[] = Ingredient::firstOrNew(array(
'name' => $ingredient['name'],
))->fill(array(
'unit' => $ingredient['unit'],
'quantity' => $ingredient['quantity']
));
}

Include single item from related table

I have a table called items and a table called item_pics.
item_pics has an item_id, file_name and a rank field (among others).
What I'm looking for is for each item my index page's $items array to contain the file_name from the item_pics matching the item's item_id with the lowest rank. So I can access like (or something like) this in my Items/index.ctp:
foreach ($items as $item):
$img = $item['Item']['ItemPic']['file_name'];
...
I'm pretty new to CakePHP, this is my first project. I thought that this within the Item model would cause item_pics data to be pulled (although I figured all related item_pics for each item would get pulled rather than just the one with the lowest rank):
public $hasMany = array(
'ItemPic' => array(
'className' => 'ItemPic',
'foreignKey' => 'item_id',
'dependent' => false
)
}
but I can see that no item_pics data is loaded (at the bottom of items/index):
SELECT `Item`.`id`, `Item`.`title`, `Item`.`description`, `Item`.`created`, `Item`.`modified`, `Item`.`type`, `Project`.`id`, `Project`.`item_id`, `Project`.`title`, `Project`.`description`, `Project`.`rank`, `Project`.`created`, `Project`.`modified`
FROM `laurensabc`.`items` AS `Item`
LEFT JOIN `laurensabc`.`projects`
AS `Project`
ON (`Project`.`item_id` = `Item`.`id`)
WHERE `Item`.`type` IN (1, 2)
LIMIT 20
also, while I would like projects to be joined in the view pages, I don't really need them in the index page.
I've done some searching and haven't been able to find exactly what I'm looking for. I suppose I could do a query within the index view item loop, but I'm trying to make sure I do things the right way... the CakePHP way. I assume I need to change something about my model relationships but I haven't had any luck.
CakePHP - Associations - HasMany, this makes it seem like I could order by rank and limit 1. But this didn't work... and even if it did, I wouldn't want that to affect the view pages but rather just the index page.
My Controller looks like this:
public function index($type = null) {
$this->Item->recursive = 0;
$conditions = array();
if ($type == "sale") {
$conditions = array(
"Item.type" => array(self::FOR_SALE, self::FOR_SALE_OR_RENT)
);
} else if ($type == "rent" ) {
$conditions = array(
"Item.type" => array(self::FOR_RENT, self::FOR_SALE_OR_RENT)
);
} else {
$conditions = array("Item.type !=" => self::HIDDEN);
}
$paginated = $this->Paginator->paginate($conditions);
debug($paginated);
$this->set('items', $paginated);
$this->set('title', ($type == null ? "Items for Sale or Rent" : "Items for " . ucwords($type)));
}
I have also tried this on my controller, but it doesn't seem to do anything either:
$this->paginate = array(
'conditions' => $conditions,
'joins' => array(
array(
'alias' => 'ItemPic',
'table' => 'item_pics',
'type' => 'left',
'conditions' => array('ItemPic.item_id' => 'Item.id'),
'order' => array('ItemPic.rank' => 'asc'),
'limit' => 1
)
)
);
$paginated = $this->paginate($this->Item);
First, set containable behavior in AppModel (or if you don't want it on each model, put it on Item model):
public $actsAs = array('Containable');
Then, on your find query:
$items = $this->Item->find('all', array(
'contain' => array(
'ItemPic' => array(
'fields' => array('file_name'),
'order' => 'rank',
'limit' => 1
)
)
));
Then the result array you can access it like:
foreach ($items as $item):
$img = $item['ItemPic']['file_name'];
Edit: Then you should put it on the paginate query:
$this->paginate = array(
'conditions' => $conditions,
'contain' => array(
'ItemPic' => array(
'fields' => array('file_name'),
'order' => 'rank',
'limit' => 1
)
)
);
In this case, I would probably order by rank and limit 1 as you said, and make that a dynamic association just for the index page (See http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#creating-and-destroying-associations-on-the-fly). So use $this->Item->bindModel(array('hasMany' => array('ItemPic' => $options))); (which I believe should replace your current settings for HasMany ItemPic, but you may have to unbindmodel first)
Associations created through bindModel will go through for the next query only, then it'll revert to your normal settings, unless you specifically set an option to keep using the new association.
As for why it's not getting ItemPics with Items, or why trying to order by rank and limit 1 didn't work for you, I can't really say without seeing more of your code.

PHP. How to take data from 2 mysql tables instead of 1

Learning php and I am losing my mind trying to solve this for days now. Please help.
This is a code which goes thought a table COUPON, take data with a condition met, and download it afterwards. In this table COUPON I have USER_ID as number but I want to have a user name also, which is kept in another table USER.
How can I go to another table (USER) and take names (REALNAME) by this USER_ID which is the same in both tables?
if ( $_POST ) {
$team_id = abs(intval($_POST['team_id']));
$consume = $_POST['consume'];
if (!$team_id || !$consume) die('-ERR ERR_NO_DATA');
$condition = array(
'team_id' => $team_id,
'consume' => $consume,
);
$coupons = DB::LimitQuery('coupon', array(
'condition' => $condition,
));
if (!$coupons) die('-ERR ERR_NO_DATA');
$team = Table::Fetch('team', $team_id);
$name = 'coupon_'.date('Ymd');
$kn = array(
'id' => 'ID',
'secret' => 'Password',
'date' => 'Valid',
'consume' => 'Status',
);
$consume = array(
'Y' => 'Used',
'N' => 'Unused',
);
$ecoupons = array();
foreach( $coupons AS $one ) {
$one['id'] = "#{$one['id']}";
$one['consume'] = $consume[$one['consume']];
$one['date'] = date('Y-m-d', $one['expire_time']);
$ecoupons[] = $one;
}
down_xls($ecoupons, $kn, $name);
After this, I want to try to do the same thing using only SQL queries.
You would need to JOIN the tables in the SQL query
SELECT something FROM coupons as coupons JOIN user as user ON coupons.id=user.id
You should use join when you want to retrieve details from two tables.
Join table COUPON and table USER based on user_id . This should yield results you want.

insert multiple rows in a saveall in cakephp

i'm newbie in Cake and wodering how to insert multiple rows in a single saveall function,
i got this table,
CREATE TABLE IF NOT EXISTS `dates` (
`date` varchar(10) COLLATE utf8_unicode_ci NOT NULL
)
what i'm trying to do is let user select start date and end date using JQuery calander, once submit all the dates between this range will be saved into database, i already got the array of dates eg:
`array(
(int) 0 => '5/8/2013',
(int) 1 => '6/8/2013',
(int) 2 => '7/8/2013',
(int) 3 => '8/8/2013',
)
`
then my controller looks like this:
public function index(){
if ($this->request->is('post')) {
$this->Date->create();
$data = array();
$data['dates']=array();
$startDate = $this->request->data['Date']['from'];
$endDate = $this->request->data['Date']['to'];
$datesBlocked = $this->loopDates($this->request->data['Date']['from'],$this->request->data['Date']['to']);
$data['dates'][] = $this->request->data['Blockdate']['from'];
$data['dates'][] = $this->request->data['Blockdate']['to'];
/*foreach($datesBlocked as $data) {
$data['dates'][] = $data;
}*/
if($this->Date->saveAll($data)) {
$this->Session->setFlash(__('done'));
if ($this->Session->read('UserAuth.User.user_group_id') == 1) {
// $this->redirect("/manages");
}
}
}
public function loopDates($from,$to){
$blockdates = array();
$start = strtotime($from);
$end = strtotime($to);
debug($start);
$counter = 0;
for($t=$start;$t<=$end;$t+=86400) {
$d = getdate($t);
$blockdates[$counter++] = $d['mday'].'/'.$d['mon'].'/'.$d['year'];
}
debug($blockdates);
return $blockdates;
}
issue was i can't get foreach work, if i uncomment the foreach, i got error said Illegal string offset 'dates' , so i commented that and try to only add the start date and end date to the array to see if that works, then i got another error said.
`array(
'dates' => array(
(int) 0 => '08/05/2013',
(int) 1 => '09/05/2013'
)
)
`
Notice (8): Array to string conversion [CORE\Cake\Model\Datasource\DboSource.php, line 1005]Code
cuz i'm trying to insert 2 values into one field...i know it should be sth like
`array(
'dates' => array( (int) 0 => '08/05/2013',
)
'dates' => array((int) 1 => '09/05/2013'
))
`but can't figure out how to do it. Any help would be much appreciate!!!!
The structure you'll want your array to save multiple dates using saveAll() is this:
array(
'Date' => array(
0 => array(
'date' => '08/05/2013',
),
1 => array(
'date' => '09/05/2013',
)
),
)
I know that this is a little late, but to write multiple rows in a loop, you have to proceed the save with a create().
eg:
foreach($items as $lineItem){
$this->Invoice->create();
$this->Invoice->save(array(
'user_id'=>$property['User']['id'],
'invoice_id'=>$invId['Invoices']['id'],
'item_id'=>$lineItem['item_number'],
'quantity'=>$lineItem['quantity'],
'price'=>$lineItem['mc_gross']
);
}
Just thought it was worth mentioning, hopefully it will help someone.

Categories