findall() in yii return array and i want it to return object how - yii

i have w function called update that i want to update a specific record in database according to module id (m_id) and key (key)
here is the function
public function updateRecord($module,$key,$newData){
$id = $this->module($module);
$model = new Form;
$criteria = new CDbCriteria();
$criteria->condition = "`m_id` = 1 AND `key` = 'txt'";
// $model = Yii::app()->db->createCommand("SELECT * FROM `tbl_setting` WHERE `m_id` = 1 AND `key` = 'txt'")->query();
die(var_dump($model->findAll($criteria)));
// $model = Yii::app()->db->createCommand("SELECT * FROM `tbl_setting` WHERE `m_id` = 1 AND `key` = 'txt'")->execute();
$model->m_id = $id ;
$model->attributes = $newData;
$model->save();
//die(print_r($model['m_id']));
//if(isset($_POST['save'])){
//$model['m_id'] = $id;
//}
}
every time i try to use this function it give me error that $model is not an object so it can't execute
$model->m_id = $id ;
i check out the type of findAll() and it gives an array
i checkout all find() methods and only findByPk() that give an object
and i want to choose according to the $criteria and i don't know what to do any help ?! :)

findAll will always return an array. With objects if there are record found, or an empty array on no result. find only returns 1 record, or NULL if nothing is found:
http://www.yiiframework.com/doc/api/1.1/CActiveRecord#find-detail
Your code will be save when you do it like this:
if(!is_null($model)) {
$model->m_id = $id ;
$model->attributes = $newData;
$model->save();
} else {
echo 'No record found';
}

Related

How can I add to an existing value in sql table

How can i add a value to an existing value in SQL example a value 4 in a column how can i add 2 to it to make it 6 not to update to 2 but to add the previous value and the new value to together here is my class php file
<?php
class data
{
public $d_count;
public $id;
private $conn;
private $table_name;
public function __construct($db)
{
$this->conn = $db;
$this->table_name= "tbl_data";
}
public function updateCount()
{
// $query = "UPDATE tbl_data SET d_count = ?, date_updated = ? WHERE id = ?";
$query = "UPDATE tbl_data SET d_count '+1' = ?, date_updated = ? WHERE id = ?";
$obj = $this->conn->prepare($query);
$this->d_count = htmlspecialchars(strip_tags($this->d_count));
$this->date_updated = htmlspecialchars(strip_tags($this->date_updated));
$this->id = htmlspecialchars(strip_tags($this->id));
$obj->bind_param("sss", $this->d_count, $this->date_updated, $this->id);
if ($obj->execute()) {
return true;
}
return false;
}
}
The line I commented out is what i used to test the code and it works fine but now i need to add the old value + new value together here is the code am using to update the table
<?php
$data = new data($connection);
if($_SERVER['REQUEST_METHOD'] === "POST"){
$newDCount = json_decode(file_get_contents("php://input"));
if(!empty($newDCount->d_count))
$data->id= $newDCount->id;
$data->d_count = $newDCount->d_count;
$data->date_updated = date('Y-m-d H:i:s', time());
if($apiata->updateCount()){
http_response_code(200);
echo json_encode(array(
"status" => 200,
"message" => "Success"
));
}
else
{
http_response_code(200);
echo json_encode(array(
"status" => 500,
"message" => "Failed"
));
}
}
To update the d_count to add to the existing d_count value, the query should look like:
$sql = 'UPDATE catalog SET d_count = d_count + ?, date_updated = ? WHERE id = ?';
The other handling should be ok as-is.

Why does CGridView fail to filter if we use `$criteria->condition` and/or `$criteria->params`?

I have the following:
public function search() {
$criteria = new CDbCriteria();
$criteria->compare('id',$this->id);
$criteria->compare('entity_id',$this->entity_id);
$criteria->compare('name',$this->name,true);
(etc...)
if (Yii::app()->user->role == SiteUser::ROLE_AUTHOR) {
$userId = Yii::app()->user->getId();
$entity = Entity::model()->find("user_id = $userId");
$criteria->condition = 'entity_id=:entity_id';
$criteria->params = array(':entity_id'=>$entity->id);
}
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
When I apply this:
if (Yii::app()->user->role == SiteUser::ROLE_AUTHOR) {
$userId = Yii::app()->user->getId();
$entity = Entity::model()->find("user_id = $userId");
$criteria->condition = 'entity_id=:entity_id';
$criteria->params = array(':entity_id'=>$entity->id);
}
the user can only see on CGridView is own records. Nice.
But, for some reason, the filter doesn't work.
If I comment those lines:
$criteria->condition = 'entity_id=:entity_id';
$criteria->params = array(':entity_id'=>$entity->id);
The filter works. But, obviously, the user will see ALL users records.
Update:
If instead of using condition and params properties I use compare() method, like this:
$criteria->compare('entity_id',$entity->id);
It works.
Why does it work with compare, and NOT with condition and params?
When you use this
if (Yii::app()->user->role == SiteUser::ROLE_AUTHOR) {
$userId = Yii::app()->user->getId();
$entity = Entity::model()->find("user_id = $userId");
$criteria->condition = 'entity_id=:entity_id';
$criteria->params = array(':entity_id'=>$entity->id);
}
what happens is the condition property is reset (due to the fresh assignment), the compare function you have used earlier appends the comparison to the the condition see http://www.yiiframework.com/doc/api/1.1/CDbCriteria#compare-detail for information on how this works, therfore when you do a fresh assignment it clears all the existing conditions.
Therefore Either you can use a new criteria object like below
if (Yii::app()->user->role == SiteUser::ROLE_AUTHOR) {
$userId = Yii::app()->user->getId();
$entity = Entity::model()->find("user_id = $userId");
$criteria2= new CDbCriteria();
$criteria2->condition = 'entity_id=:entity_id';
$criteria2->params = array(':entity_id'=>$entity->id);
$criteria->mergeWith($criteria2);
}
or you can move the logic for SiteUser::ROLE_AUTHOR before the compare statements

Get raw sql from Phalcon query builder

Is it possible to extract raw sql query from the query builder instance in Phalcon? Something like this?
$queryBuilder = new Phalcon\Mvc\Model\Query\Builder();
$queryBuilder
->from(…)
->where(…);
$rawSql = $queryBuilder->hypotheticalGetRawQueryMethod();
By error and trial the below seems to working. Would be great if someone could confirm if there's a better way.
$queryBuilder = new Builder();
$queryBuilder->from(…)->where(…);
$intermediate = $queryBuilder->getQuery()->parse();
$dialect = DI::getDefault()->get('db')->getDialect();
$sql = $dialect->select($intermediate);
Edit: As of 2.0.3 you can do it super simple, see comment for full details:
$modelsManager->createBuilder()
->from('Some\Robots')
->getQuery()
->getSql()
you can use getRealSqlStatement() (or similar function name) on the DbAdapter. See http://docs.phalconphp.com/en/latest/api/Phalcon_Db_Adapter.html
According to documentation you can get this way the resulting sql query.
Or wait, this might not work on querybuilder. Otherwise you can setup low level query logging: http://docs.phalconphp.com/en/latest/reference/models.html#logging-low-level-sql-statements
$db = Phalcon\DI::getDefault()->getDb();
$sql = $db->getSQLStatement();
$vars = $db->getSQLVariables();
if ($vars) {
$keys = array();
$values = array();
foreach ($vars as $placeHolder=>$var) {
// fill array of placeholders
if (is_string($placeHolder)) {
$keys[] = '/:'.ltrim($placeHolder, ':').'/';
} else {
$keys[] = '/[?]/';
}
// fill array of values
// It makes sense to use RawValue only in INSERT and UPDATE queries and only as values
// in all other cases it will be inserted as a quoted string
if ((strpos($sql, 'INSERT') === 0 || strpos($sql, 'UPDATE') === 0) && $var instanceof \Phalcon\Db\RawValue) {
$var = $var->getValue();
} elseif (is_null($var)) {
$var = 'NULL';
} elseif (is_numeric($var)) {
$var = $var;
} else {
$var = '"'.$var.'"';
}
$values[] = $var;
}
$sql = preg_replace($keys, $values, $sql, 1);
}
More you can read there
The following is the common solution:
$result = $modelsManager->createBuilder()
->from(Foo::class)
->where('slug = :bar:', ['bar' => "some-slug"])
->getQuery()
->getSql();
But you might not expect to see the query without its values, like in:
die(print_r($result, true));
Array
(
[sql] => SELECT `foo`.`id`, `foo`.`slug` FROM `foo` WHERE `foo`.`slug` = :bar
[bind] => Array
(
[bar] => some-slug
)
[bindTypes] =>
)
So, this simple code might be useful:
public static function toSql(\Phalcon\Mvc\Model\Query\BuilderInterface $builder) : string
{
$data = $builder->getQuery()->getSql();
['sql' => $sql, 'bind' => $binds, 'bindTypes' => $bindTypes] = $data;
$finalSql = $sql;
foreach ($binds as $name => $value) {
$formattedValue = $value;
if (\is_object($value)) {
$formattedValue = (string)$value;
}
if (\is_string($formattedValue)) {
$formattedValue = sprintf("'%s'", $formattedValue);
}
$finalSql = str_replace(":$name", $formattedValue, $finalSql);
}
return $finalSql;
}
If you're using query builder then like given below then getPhql function can serve the purpose as per phalcon 3.4.4 version.
$queryBuilder = new Builder();
$queryBuilder->from(…)->where(…)->getQuery();
$queryBuilder->getPhql();
if (!function_exists("getParsedBuilderQuery")) {
/**
* #param \Phalcon\Mvc\Model\Query\BuilderInterface $builder
*
* #return null|string|string[]
*/
function getParsedBuilderQuery (\Phalcon\Mvc\Model\Query\BuilderInterface $builder) {
$dialect = Phalcon\Di::getDefault()->get('db')->getDialect();
$sql = $dialect->select($builder->getQuery()->parse());
foreach ($builder->getQuery()->getBindParams() as $key => $value) {
// For strings work fine. You can add other types below
$sql = preg_replace("/:?\s?($key)\s?:?/","'$value'",$sql);
}
return $sql;
}
}
Simple function that im using for debugging.

Can the the default conditions operator be changed from OR to AND on the Taggable extension?

$tagged = Os :: model()-> withTags("windows, windows7, windowsXp")-> find();
I want to retrieve the records that are tagged with any of the following
windows, windows7, windowsXp.
By default the tags are generating a condition which are AND-ed. I want to use the OR operator for the tags. So if the record contains windows, windows7 but not windowsXp it won't be retrieved.
I've managed to find a workaround, by editing the getFindByTagsCriteria() in the ETaggableBehavior.php that comes in the extension folder.
/**
* Get criteria to limit query by tags.
* #access private
* #param array $tags
* #return CDbCriteria
*/
protected function getFindByTagsCriteria($tags) {
$criteria = new CDbCriteria();
$pk = $this->getOwner()->tableSchema->primaryKey;
if(!empty($tags)){
$conn = $this->getConnection();
$criteria->select = 't.*';
if(count($tags) >0){
$criteria -> join .= "
JOIN {$this->getTagBindingTableName()} bt
ON t.{$pk} = bt.{$this->getModelTableFkName()}
JOIN {$this->tagTable} tag0
ON tag0.{$this->tagTablePk} = bt.{$this->tagBindingTableTagId} AND (";
for($i = 0, $count = count($tags); $i < $count; $i++){
$tag = $conn->quoteValue($tags[$i]);
$criteria->join .= " tag0.`{$this->tagTableName}` = $tag OR";
}
$criteria -> join = rtrim($criteria -> join, "OR");
$criteria -> join .= ")";
}
}
if($this->getScopeCriteria()){
$criteria->mergeWith($this->getScopeCriteria());
}
return $criteria;
}
I would really appreciate any other way without having to modify the plugin itself.
What I'd do here is set the withTags() method in your model to take an array value, for example something like this:
/**
* #param array $tags List of tags to search for
* #return named scope
*/
public function withTags($tags)
{
$condition = '1';
$params = array();
foreach($tags as $key=>$value)
{
$condition.=' OR tag = :tag'.$key;
$params[':tag'.$key] = $value;
}
$this->getDbCriteria()->mergeWith(array(
'condition'=>$condition,
'params'=>$params,
));
return $this;
}
This way you should be able to call your named scope like so:
$tags = array('windows', 'windows7', 'windowsXp'),
$tagged = Os::model()->withTags($tags)->findAll();
Sam from Yii development team helped me solve this by adding two more functions to the ETaggableBehavior.php
/**
* Get criteria to limit query to match any of tags specified
* #access private
* #param array $tags
* #return CDbCriteria
*/
protected function getFindByAnyTagsCriteria($tags) {
$criteria = new CDbCriteria();
$pk = $this->getOwner()->tableSchema->primaryKey;
if(!empty($tags)){
$conn = $this->getConnection();
foreach($tags as &$tag) {
$tag = $conn->quoteValue($tag);
}
unset($tag);
$tags = implode(', ', $tags);
$criteria->select = 't.*';
$criteria->join .=
"JOIN {$this->getTagBindingTableName()} bt ON t.{$pk} = bt.{$this->getModelTableFkName()}
JOIN {$this->tagTable} tag ON tag.{$this->tagTablePk} = bt.{$this->tagBindingTableTagId} AND tag.`{$this->tagTableName}` IN ($tags)";
}
}
if($this->getScopeCriteria()){
$criteria->mergeWith($this->getScopeCriteria());
}
return $criteria;
}
/**
* Limit current AR query to have any of tags specified.
* #param string|array $tags
* #return CActiveRecord
*/
public function taggedWithAnyOf($tags) {
$tags = $this->toTagsArray($tags);
if(!empty($tags)){
$criteria = $this->getFindByAnyTagsCriteria($tags);
$this->getOwner()->getDbCriteria()->mergeWith($criteria);
}
return $this->getOwner();
}

How do i write update number of download bought function in controller of magento

i want to update number_of_download_bougt. So How will SQL be in a controllers?
i wrote:
public function updatedownloadAction($db_magento, $id, $numberdownload)
{
// $id = $this->getRequest()->getParam('id', 0);
$db_magento = Mage::getModel('downloadable/link_purchased_item')->load($id);
$db_magento->query("UPDATE downloadable_link_purchased_item d
SET d.number_of_downloads_bought = '$numberdownload'
WHERE d.item_id = '$id'");
}
but it's error
Use the setNumberOfDownloadsUsed function to set the number purchased.
$id = $this->getRequest()->getParam('id', 0);
$linkPurchasedItem = Mage::getModel('downloadable/link_purchased_item')->load($id, 'link_hash');
$linkPurchasedItem->setNumberOfDownloadsUsed($linkPurchasedItem->getNumberOfDownloadsUsed()+1);
if ($linkPurchasedItem->getNumberOfDownloadsBought() != 0 &&
!($linkPurchasedItem->getNumberOfDownloadsBought() - $linkPurchasedItem->getNumberOfDownloadsUsed())) {
$linkPurchasedItem->setStatus(Mage_Downloadable_Model_Link_Purchased_Item::LINK_STATUS_EXPIRED);
}
$linkPurchasedItem->save();