How to update multiple rows from a single query using eloquent/fluent? - laravel

I was learning about How to insert multiple rows from a single query using eloquent/fluent and I found the answer here
Can somebody share any documentation about how to update bulk rows in single query?
My queries are below.
Update tblrole set role = 'Super Admin' where RoleID = 1;
Update tblrole set role = 'Super Admin A' where RoleID = 2;
Update tblrole set role = 'Super Admin B' where RoleID = 3;
Update tblrole set role = 'Super Admin C' where RoleID = 4;

You can solve the issue using a single MySQL query. It can be implemented in Laravel Eloquent using DB::raw() method.
**UPDATE** tblrole **SET** role =
**CASE**
WHEN RoleID = 1 THEN 'Super Admin'
WHEN RoleID = 2 THEN 'Super Admin A'
WHEN RoleID = 3 THEN 'Super Admin B'
WHEN RoleID = 4 THEN 'Super Admin C'
**END**
**WHERE** RoleID in (1,2,3,4);

You cannot do anything like this in simple way. You can easily update multiple rows with same value but if you want to update role column with different values it will be tricky.
In fact it doesn't make much sense to do it like this but if you really want it and you think it's the best solution you can try to play with raw queries using technique described here https://stackoverflow.com/a/25674827/3593996

You might find inspiration from this mass insert or update gist:
/**
* Mass (bulk) insert or update on duplicate for Laravel 4/5
*
* insertOrUpdate([
* ['id'=>1,'value'=>10],
* ['id'=>2,'value'=>60]
* ]);
*
*
* #param array $rows
*/
function insertOrUpdate(array $rows){
$table = \DB::getTablePrefix().with(new self)->getTable();
$first = reset($rows);
$columns = implode( ',',
array_map( function( $value ) { return "$value"; } , array_keys($first) )
);
$values = implode( ',', array_map( function( $row ) {
return '('.implode( ',',
array_map( function( $value ) { return '"'.str_replace('"', '""', $value).'"'; } , $row )
).')';
} , $rows )
);
$updates = implode( ',',
array_map( function( $value ) { return "$value = VALUES($value)"; } , array_keys($first) )
);
$sql = "INSERT INTO {$table}({$columns}) VALUES {$values} ON DUPLICATE KEY UPDATE {$updates}";
return \DB::statement( $sql );
}
Ref: https://gist.github.com/RuGa/5354e44883c7651fd15c
I don't think I need to provide any explanation as each chunk of code in the function speaks of itself.

Related

Codeigniter Call to undefined method CI_DB_mysqli_result::fetch_assoc()

hello i want to update the row by clicking on edit button, but it giving me this error, kindly help
function updateUser()
{
$data = stripslashes(file_get_contents("php://input"));
$mydata = json_decode($data, true);
$id = $mydata['sid'];
//retrieve specific info
$sql = "SELECT * FROM admin WHERE id = {$id}";
$result = $this->db->query($sql);
$row = $result->fetch_assoc();
echo json_encode($row); //returning json formate
}
Use $result->row_array(); instead of $result->fetch_assoc();
To prevent sql injection, you may also want to bind the $id separately instead of concatenating it into the query, like this:
$sql = "SELECT * FROM admin WHERE id = ?";
$result = $this->db->query($sql, array($id));
$row = $result->row_array();
See also: https://codeigniter.com/userguide3/database/queries.html#query-bindings

Get the total amount and store it on another table. (Codeigniter)

my target is to total all the (commtype = IN) betAmount only and store it on my "comCurrentBalance" users table. Then, with my SQL update it'll be subtracted the user input's amount to the total value of betAmount from "agent_commmission_history" table. I provided a screenshot below for my problem and my target. Any help will be appreciated.
Controller:
public function comm($userID=0) {
$this->commissions->commOut($userID);
redirect(base_url() . "commission/commi");
}
Model:
function commOut($data) {
$ref= $this->session->userdata('uid') + date ('his');
$id = $this->session->userdata('uid');
$data = array(
'userID' => $id,
'transactionSource' => 'Commi',
'refNumber' => $ref ,
'amount' =>$this->input->post("amount"),
"transType" =>"out",
);
$sqlInsertLedger = "INSERT INTO transaction_ledger (transactionSource, transType, refNumber, userID, amount, currentBalance, previousBalance, remarks, createdBy)
select '".$data['transactionSource']."', '".$data['transType']."', '".$data['refNumber']."', ".$data['userID'].", ".$data['amount'].", sum(TU.currentPoints + ".$data['amount'].") as totalPoints, TU.currentPoints,
'funded by agent', '".$this->session->userdata('uid')."'
from users TU where TU.userID=?";
$Q = $this->db->query($sqlInsertLedger, $data['userID']);
//update user table
$sqlUpdate = "update users set commCurrentBalance = commCurrentBalance - ?, currentPoints = currentPoints + ? where userID = ?"; // ***Current points is already adding and comCurrentBalance is subtracting based on user's input. However, my target is to total the betamount before subtracting happens.*****
$Q = $this->db->query($sqlUpdate, array($data['amount'], $data['amount'], $data['userID']));
}

Laravel : How can i get old and new value by updateOrCreate

I want update or create in data base
but i want get the old value and updated value because i want to compare between these two value
for example
this item in table user
name = Alex and Order = 10
so now i want update this person by
name = Alex and Order = 8
Now After updating or creating if not exist
just for update i want get
Old order 10 | And new Order 8
I want compare between these order
i have tryin getChange() and getOriginal() but two the function give me just the new value.
Please Help
You can get the old value using getOriginal if you have the object already loaded.
For example :
$user = User::find(1);
$user->first_name = 'newname';
// Dumps `oldname`
dd($user->getOriginal('first_name'));
$user->save();
However in case of updateOrCreate, you just have the data. I am not sure about a way to do it using updateOrCreate but you can do simply do :
$user = User::where('name', 'Alex')->first();
$newOrder = 10;
if($user){
$oldOrder = $user->getOriginal('order');
$user->order = $newOrder;
$user->save();
}
Is the name unique in the table? Because if it is not you will have updates on multiple rows with the same data.
So the best approach is to use the unique column which is probably the ID.
User::updateOrCreate(
[ 'id' => $request->get('id') ], // if the $id is null, it will create new row
[ 'name' => $request->get('name'), 'order' => $request->get('order') ]
);
Solution
$model = Trend::where('name', $trend->name)->first();
if ($model) {
$model->old_order = $model->getOriginal('order');
$model->order = $key + 1;
$model->save();
} else {
Trend::where('order', $key + 1)->delete();
$new = new Trend();
$new->name = $trend->name;
$new->old_order = $key + 1;
$new->order = $key + 1;
$new->tweet_volume = $trend->tweet_volume;
$new->save();
}

Magento Changing Default Payment Method

I have a function that runs raw SQL queries to our database in Magento. What the function does is changes the customer's default credit card to a value passed to the function. My question is how would I rewrite the function utilizing Magento models. The current function works, but we'd rather have it not be directly interfacing with SQL.
Here is the function:
public function setDefaultPayment($value)
{
$customerId = $this->_getSession()->getCustomer()->getId();
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$read = $write->query("SELECT entity_type_id FROM eav_entity_type WHERE entity_type_code='customer'");
$row = $read->fetch();
$entity_type_id = $row['entity_type_id'];
$read = $write->query("SELECT attribute_id FROM eav_attribute WHERE attribute_code='default_payment' AND entity_type_id = $entity_type_id");
$row = $read->fetch();
$attribute_id = $row['attribute_id'];
$read = $write->query("SELECT * FROM customer_entity_int WHERE entity_type_id='$entity_type_id' AND attribute_id='$attribute_id' AND entity_id='$customerId'");
if ($row = $read->fetch()) {
$write->update(
'customer_entity_int',
array('value' => $value),
"entity_type_id='$entity_type_id' AND attribute_id='$attribute_id' AND entity_id='$customerId'"
);
} else {
$write->insert(
'customer_entity_int',
array(
'entity_type_id' => $entity_type_id,
'attribute_id' => $attribute_id,
'entity_id' => $customerId,
'value' => $value
)
);
}
}
If I read you code right, you want to update the customer attribute default_payment with a value given.
For that you need to:
Load the customer by id
Set the new value for the customer attribute default_payment
Save the customer
public function setDefaultPayment($value)
{
$customerId = $this->_getSession()->getCustomer()->getId();
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$customer = Mage::getModel('customer/customer')->load($customerId);
$oldValue = $customer->getDefaultPayment(); // optional, just for checking
$customer->setDefaultPayment($value);
$customer->save();
}

How to show same product attribute sort on compare page Magento

i am not sure why the sorting of a product attribute on compare page is not working same as on product page. Like on product page the atribute sort is
on product page
1 name
2 new attribute
3 new attribute1
4 color
but on comapre page when i am comp[aring the 2 products has same attributes the attribute sort order becomes
on compare page
1 name
2 color
3 new attribute
4 new attribute1
I have googled a lot to find answer but unable to find. Please help me to fix this issue.
Below are the functions which i find
public function getComparableAttributes()
{
if (is_null($this->_comparableAttributes)) {
$this->_comparableAttributes = array();
$setIds = $this->_getAttributeSetIds();
if ($setIds) {
$attributeIds = $this->_getAttributeIdsBySetIds($setIds);
$select = $this->getConnection()->select()
->from(array('main_table' => $this->getTable('eav/attribute')))
->join(
array('additional_table' => $this->getTable('catalog/eav_attribute')),
'additional_table.attribute_id=main_table.attribute_id'
)
->joinLeft(
array('al' => $this->getTable('eav/attribute_label')),
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . (int) $this->getStoreId(),
array('store_label' => $this->getConnection()->getCheckSql('al.value IS NULL', 'main_table.frontend_label', 'al.value'))
)
->where('additional_table.is_comparable=?', 1)
->where('main_table.attribute_id IN(?)', $attributeIds);
$attributesData = $this->getConnection()->fetchAll($select);
if ($attributesData) {
$entityType = Mage_Catalog_Model_Product::ENTITY;
Mage::getSingleton('eav/config')
->importAttributesData($entityType, $attributesData);
foreach ($attributesData as $data) {
$attribute = Mage::getSingleton('eav/config')
->getAttribute($entityType, $data['attribute_code']);
$this->_comparableAttributes[$attribute->getAttributeCode()] = $attribute;
}
unset($attributesData);
}
}
}
return $this->_comparableAttributes;
}
/**
* Load Comparable attributes
*
* #return Mage_Catalog_Model_Resource_Product_Compare_Item_Collection
*/
public function loadComparableAttributes()
{
$comparableAttributes = $this->getComparableAttributes();
$attributes = array();
foreach ($comparableAttributes as $attribute) {
$attributes[] = $attribute->getAttributeCode();
}
$this->addAttributeToSelect($attributes);
return $this;
}
bUt i cant understand how to filter it by sort order .Please suggest
check the modifications in function below:
the file used is vendor/magento/module-catalog/Model/ResourceModel/Product/Compare/Item/Collection.php
But this is not the best way to do it. you need to override it as per Magento Standards.
I am working on it, will update shortly.
public function getComparableAttributes()
{
if ($this->_comparableAttributes === null) {
$this->_comparableAttributes = [];
$setIds = $this->_getAttributeSetIds();
if ($setIds) {
$attributeIds = $this->_getAttributeIdsBySetIds($setIds);
$select = $this->getConnection()->select()->from(
['main_table' => $this->getTable('eav_attribute')]
)->join(
['additional_table' => $this->getTable('catalog_eav_attribute')],
'additional_table.attribute_id=main_table.attribute_id'
)->joinLeft(
['al' => $this->getTable('eav_attribute_label')],
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . (int)$this->getStoreId(),
[
'store_label' => $this->getConnection()->getCheckSql(
'al.value IS NULL',
'main_table.frontend_label',
'al.value'
)
]
)
->joinLeft( //add sort order to sort the attributes as per backend sort. -- Abid
['as' => $this->getTable('eav_entity_attribute')],
'as.attribute_id = main_table.attribute_id'
)
->where(
'additional_table.is_comparable=?',
1
)->where(
'main_table.attribute_id IN(?)',
$attributeIds
)
->order('as.sort_order') //sort by sort_order -- Abid
;
$attributesData = $this->getConnection()->fetchAll($select);
if ($attributesData) {
$entityType = \Magento\Catalog\Model\Product::ENTITY;
$this->_eavConfig->importAttributesData($entityType, $attributesData);
foreach ($attributesData as $data) {
$attribute = $this->_eavConfig->getAttribute($entityType, $data['attribute_code']);
$this->_comparableAttributes[$attribute->getAttributeCode()] = $attribute;
}
unset($attributesData);
}
}
}
return $this->_comparableAttributes;
}
On product page attributes are sorted like in attribute set.
On compare page attributes are not sorted at all.
You can rewrite function getComparableAttributes in class Mage_Catalog_Model_Resource_Product_Compare_Item_Collection and implement your own sort logic.
But note, that this function differs in different Magento versions. You can try to use free extension ET Advanced Compare or take part of code from this extension (code is available on bitbucket.org. link i on extension page)

Resources