CDbCriteria select multiple table in Yii - yii

i have a sql query and it working:
$sql = "
SELECT P.`name`, P.`price`, P.`year`, P.`slug`, P.`image`, C.`title`, C.`des`
FROM `tbl_category` C, `tbl_products` P
WHERE C.`group_cat` = 1 AND C.`slug` = '/category/".$category."/'
ORDER BY `P.updated_at` DESC
LIMIT 0,".Yii::app()->params['limitPageSizeView']
";
$dbCommand = Yii::app()->db->createCommand($sql);
$data = $dbCommand->queryAll();
now, i want converter this sql to syntax CDbCriteria:
$criteria = new CDbCriteria();
$criteria->select = '???';
$criteria->where= '???';
$criteria->condition = '???';
$criteria->order = '???';
$criteria->limit = '???';
$data = ProductsModel::model()->findAll($criteria);
somebody can help me?

$criteria = new CDbCriteria();
$criteria->select = 'name, price, year, slug, image';
$criteria->order = 'upadated_at';
$criteria->limit = Yii::app()->params['limitPageSizeView'];
$criteria->with = array(
'category' => array(
'together'=>true,
'select'=>array('title','des'),
'condition'=>"group_cat = 1 AND slug = '/category/".$category."/'"
)
);
$data = ProductsModel::model()->findAll($criteria);
this will do left join on, make sure you have relation defined on product for category, if you dont have relation you can add "ON" condition.

Related

Get database records in TYPO3 viewHelper

I want to create a database query in a view helper, this works with the following code:
$uid = 11;
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_test_domain_model_author');
$query = $queryBuilder
->select('*')
->addSelectLiteral(
$queryBuilder->expr()->count('tx_test_domain_model_author.author', 'counter')
)
->from('tx_test_domain_model_author')
->join(
'tx_test_domain_model_author',
'tx_test_publication_author_mm',
'tx_test_publication_author_mm',
$queryBuilder->expr()->eq(
'tx_test_domain_model_author.uid',
$queryBuilder->quoteIdentifier('tx_test_publication_author_mm.uid_foreign')
)
)
->where(
$queryBuilder->expr()->eq(
'tx_test_publication_author_mm.uid_local',
$queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
)
)
->orderBy('tx_test_domain_model_author.uid', 'ASC');
$result = $query->execute();
$res = [];
while ($row = $result->fetch()) {
$res[] = $row;
}
print_r($res);
However, I only get one record, although the counter tells me it would be 3.
What am I doing wrong?
If the counter says its three items, then try change this:
$result = $query->execute();
$res = [];
while ($row = $result->fetch()) {
$res[] = $row;
}
into this:
$result = $query->execute()->fetchAll();
That fetches all rows into an array that you walk throug with:
foreach($result as $row){
...
}
It seems the QueryBuilder works differently, this gives me one result namely the first entry in the table:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_test_publication_author_mm');
$query = $queryBuilder
->select('*')
->from('tx_test_publication_author_mm');
$result = $query->execute()->fetchAll();
foreach($result as $row){
echo $row['field'];;
}
This gives me all results:
$db = mysqli_connect($dbHost, $dbUser, $dbPassword, $dbName) or die (mysql_error ());
$sql = "SELECT * FROM tx_test_publication_author_mm";
foreach ($db->query($sql) as $row) {
echo $row['field'];
}

Codeigniter Active record query

How can I write this procedural query as codeigniter active record query (update_batch mode )
UPDATE products SET current_stock = current_stock + 1 where product_id = 1
You can use update_batch like this:
$products = $this->db->get('products'))->result();
for( $i = 0; $i < count($products); $i++){
$data[] = array(
'product_id' => $product[$i]->product_id,
'current_stock' => $product[$i]->current_stock + 1
);
}
$this->db->update_batch('products', $data, 'product_id');
You can use below query as explained on Codeigniter Query Builder Class:
$this->db->set('current_stock', 'current_stock+1', FALSE);
$this->db->where('product_id', 2);
$result = $this->db->update('products');

CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found YII

Relations of review below:
return array(
'product' => array(self::BELONGS_TO, 'Product', 'product_id'),
'profile' => array(self::BELONGS_TO, 'Profile', 'profile_id'),
'rating' => array(self::BELONGS_TO, 'Rating', 'rating_id'),
'reviewcomments' => array(self::HAS_MANY, 'Reviewcomment', 'review_id'),
'reviewhelpfuls' => array(self::HAS_MANY, 'Reviewhelpful', 'review_id'),
'commentCounts' => array(self::STAT, 'Reviewcomment', 'review_id'),
);
Controller code below:
$criteria = new CDbCriteria();
$criteria->addCondition("t.seoUrl = :seoUrl");
$criteria->addCondition("t.published = 1");
$criteria->params = array("seoUrl"=>$seoUrl);
$data['product'] = Product::model()->find($criteria);
if($data['product']){
$data['product']->hits = $data['product']->hits+1;
$data['product']->save();
} else{
throw new CHttpException(404, "Invalid Request for product");
}
$product_id = $data['product']->id;
$criteria = new CDbCriteria();
$criteria->addCondition("t.product_id = '$product_id'");
if(isset($_GET['rating']))
{
$rating_id = $_GET['rating'];
$criteria->addCondition("t.rating_id = '$rating_id'");
}
$criteria->addCondition('t.status = "approved"');
if(isset($_GET['sort']))
{
$sorting = $_GET['sort'];
if($sorting=='newest')
$criteria->order = "t.postDate DESC";
elseif($sorting=='oldest')
$criteria->order = "t.postDate ASC";
elseif($sorting=='rating_high')
$criteria->order = "t.rating_id DESC";
elseif($sorting=='rating_low')
$criteria->order = "t.rating_id ASC";
}
$data['reviews'] = new CActiveDataProvider('Review', array(
'criteria'=>$criteria,
'pagination'=>array('pagesize'=>4)
));
Now when I am running this code, I am getting CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 't.rating_id' in 'where clause'
Thanks for your help
Intstead of using 't' as alias for your tables, start using getTableAlias(false, false)
In your case it would be:
$criteria->addCondition(Review::model()->getTableAlias(false, false).".rating_id = '$rating_id'");
More importantly this code screams SQL injection
$rating_id = $_GET['rating'];
$criteria->addCondition("t.rating_id = '$rating_id'");
Never use user input without processing it. Yii allows you to bind values which would be escaped for you - no threat of SQL injection(atleast as far as i know). You should be creating your criteria like so:
$criteria->addCondition(Review::model()->getTableAlias(false, false).".rating_id = :rating_id");
$criteria->params = array(
':rating_id' => $rating_id,
);

how to get `dataProvider ` with each product_id

i have order table where in product_id is string Like 10,11,12,13. And have Product table with this id.
how to get dataProvider with each product_id
My code is
public function getProducts($id){
$idarray = explode(',', $id);
$dataProviderProduct = Array();
foreach($idarray as $i=>$id){
$dataProviderProduct[$i]=new CActiveDataProvider('Product',
array( 'criteria'=>array(
'condition'=>'id=:id',
'params'=>array(':id' => $id),
),
'pagination'=>array( 'pageSize'=>10),
)
);
}
return $dataProviderProduct;
}
But this is wrong code
Use addInCondition like this:
$idarray = explode(',', $id);
$criteria = new CDbCriteria();
$criteria->addInCondition('id', $idarray);
$data = ModelName::model()->findAll($criteria);

Zend Framework using regular mysql select call

Is there a way to use a regular mysql select statement with Zend Framework without having to use Zend_Db::factory
Code below is in my Model classes which extends Zend_Db_Table_Abstract
I can currently do this (which works):
$db = Zend_Db::factory('Pdo_Mysql', array(
'host' => 'localhost',
'username' => 'dbuser',
'password' => 'dbuserpass',
'dbname' => "somedbname"
));
$select = "SELECT iv.*
FROM image_variations AS iv
LEFT JOIN images AS i ON (i.image_id = iv.image_id)
LEFT JOIN product_images AS pi ON (pi.image_id = iv.image_id)
WHERE pi.pid = '$pid'
&& iv.image_type_id = '$image_type_id' ";
$stmt = $db->query($select);
$rows = $stmt->fetchAll();
return $rows;
I would like to do this:
$select = "SELECT iv.*
FROM image_variations AS iv
LEFT JOIN images AS i ON (i.image_id = iv.image_id)
LEFT JOIN product_images AS pi ON (pi.image_id = iv.image_id)
WHERE pi.pid = '$pid'
&& iv.image_type_id = '$image_type_id' ";
$stmt = $this->query($select);
$rows = $stmt->fetchAll();
return $rows;
So I dont always have to define db variables in each method and have mysql passwords all over the place. Is there a way to use $this instead of having to instantiate a new $db Zend_DB Factory??
Ok figured it out. The solution is not very elegant buts works and is portable.
My setup consists of multiple DBs, so in Bootstrap.php I have:
protected function _initDatabase() {
$resource = $this->getPluginResource('multidb');
$resource->init();
Zend_Registry::set('db', $resource->getDb('db'));
Zend_Registry::set('shopdb', $resource->getDb('shopdb'));
}
In Application.ini
resources.multidb.db.adapter = PDO_MYSQL
resources.multidb.db.host = 127.0.0.1
resources.multidb.db.username = user
resources.multidb.db.password = userpassword
resources.multidb.db.dbname = dbone
resources.multidb.db.isDefaultTableAdapter = true
resources.multidb.db.default = true
resources.multidb.shopdb.adapter = PDO_MYSQL
resources.multidb.shopdb.host = 127.0.0.1
resources.multidb.shopdb.username = user
resources.multidb.shopdb.password = userpassword
resources.multidb.shopdb.dbname = dbtwo
resources.multidb.shopdb.isDefaultTableAdapter = false
in index.php
$config = new Zend_Config_Ini(APPLICATION_PATH . "/configs/application.ini");
Zend_Registry::set('settings', $config);
Then (the not very elegant bit) in Models add an init() method
protected $db;
public function init() {
$settings = Zend_Registry::get('settings');
$adapter = $settings->production->resources->multidb->shopdb->adapter;
$params = array(
'host' => $settings->production->resources->multidb->shopdb->host,
'username' => $settings->production->resources->multidb->shopdb->username,
'password' => $settings->production->resources->multidb->shopdb->password,
'dbname' => $settings->production->resources->multidb->shopdb->dbname,
);
$this->db = Zend_Db::factory("$adapter", $params);
}
And then you can use $this->db in other methods in the Model class, eg:
public function getProductImages($pid, $image_type_id) {
$select = "SELECT iv.*
FROM image_variations AS iv
LEFT JOIN images AS i ON (i.image_id = iv.image_id)
LEFT JOIN product_images AS pi ON (pi.image_id = iv.image_id)
WHERE pi.pid = '$pid'
&& iv.image_type_id = '$image_type_id' ";
$stmt = $this->db->query($select);
$rows = $stmt->fetchAll();
return $rows;
}
It works but it still seems like there should be an easier way...