Zend/db/Sql/ query syntax - sql

I am starting with Zend Framework 2 , I want to make a routing choice with the role of My user and I must write getRoleByID($id) ,
then
How can'I write
" Select 'role' from user where ('id' = $id) " with Zend\Db\Sql

Example Using Select:
$select = new \Zend\Db\Sql\Select('user');
$select->columns(array('role'));
$where = new Where();
$where->equalTo('id', $id);
$select->where($where);
/**
* Simple example of executing a query...
*/
$stmt = $this->getSql()->prepareStatementForSqlObject($select);
$results = $stmt->execute();
/* #var $results \Zend\Db\Adapter\Driver\Pdo\Result */
if( ! $results->count()) {
// do something, none found...
}
$row = $results->current();
return $row['role'];
// if you had multiple results to iterate over:
//$resultSet = new \Zend\Db\ResultSet\ResultSet();
//$resultSet->initialize($results);
//$array = $resultSet->toArray();
//foreach($resultSet as $row) { /* ... */ }

Related

Symfony 3.4 - I have issue using knp-paginator-bundle

I have the following controller
/**
*
* #Route("/searchname" , name="search_student_name")
*
*/
public function SearchStudentName(Request $request, SessionInterface $sessionName)
{
$params = $request->request->all();
$SName = $params['txtSearchName'];
if (isset($SName)){
$sessionName->set('SName', $SName);
}
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery("SELECT s FROM AppBundle:Student s WHERE s.name LIKE :Name ORDER BY s.name");
$query->setParameter('Name', '%'.$sessionName->get('SName').'%');
$students = $query->getArrayResult();
$paginator = $this->get('knp_paginator');
$result = $paginator->paginate(
$students,
$request->query->get('page', 1)/*page number*/,
50/*limit per page*/
);
return $this->render('student/index.html.twig', array(
'students' => $result,
));
}
The first page was displayed correctly.
But When I am trying to go to other page
app_dev.php/student/searchname?page=2
I have the following error:
NotFoundHttpException
HTTP 404 Not Found
AppBundle\Entity\Student object not found by the #ParamConverter annotation.
I have the indexAction which works fine for any page:
the only difference is $students = $em->getRepository('AppBundle:Student')->findAll();
and the use of session to save the name
/**
* Lists all student entities.
*
* #Route("/", name="student_index")
* #Method("GET")
*/
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$students = $em->getRepository('AppBundle:Student')->findAll();
/**
* #var $paginator \Knp\Component\Pager\Paginator
*/
$paginator = $this->get('knp_paginator');
$result = $paginator->paginate(
$students,
$request->query->get('page', 1)/*page number*/,
50/*limit per page*/
);
return $this->render('student/index.html.twig', array(
'students' => $result,
));
}
Can someone help me how to solve this issue?
Session value
Maybe $sessionName->get('SName') is empty or null ?, you can try put a default value for the session like this:
$sessionName->get('SName', 'something default');

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.

PHP PDO dynamically updating db table with multiple records to a specific user ID

/* Newbie need some help; I am creating a class to auto update my apps db record when instructed to, but I am consistently getting this message below, and for the heck of it, I just not seeing what I am doing wrong. Can someone please look at my codes for me? Thank you.
Warning: PDOStatement::bindParam() expects at least 2 parameters, 1 given in……..on line 331; that where the "else if(is_string($val)){" is located.
*/
// vars given
// DBDriver: MySQL
$myTable = 'seeYou';
$loginDate = NULL;
$ip = $_SERVER['REMOTE_ADDR'];
$date = #date('m/d/Y \a\\t h:i a');
$_id =1;
// data array
$idata = array("last_logged_in"=>$loginDate,
"login_date"=>$date,
"ip_addr"=>$ip
);
class name
{
///------------ other methods here---------///
/**
*--------------------------------------------
* Method - PDO: SET FIELD VALUE PLACEHOLDER
*--------------------------------------------
* #return fields with prefix as placeholder
*/
protected function set_fieldValPlaceHolders(array $data)
{
$set = '';
foreach($data as $field => $value)
{
$set .= $field .'= :'.$field . ',';
}
// remove the last comma
$set = substr($set, 0, -1);
return $set;
}
public function save($data=NULL, $_id = NULL, $rows= NULL, $dbTable= NULL)
{
//----------------- some other codes goes here ----------------//
$id = (int)$_id;
// update row with a specific id
if (isset($id) !== NULL && $rows === NULL)
{
$set = $this->set_fieldValPlaceHolders($data);
$sql = "UPDATE {$dbTable} SET {$set} WHERE user_id = :uid";
try
{
// Build the database statement
$_stmt = $this->_dbConn->prepare($sql);
$_stmt->bindValue(':uid',$id, PDO::PARAM_INT);
foreach ($data as $field => $val)
{
if(is_int($val)){
$_stmt->bindValue(':'.$field.'\', '.$val.', PDO::PARAM_INT');
}
else if(is_string($val)){
$_stmt->bindValue(':'.$field.'\', '.$val.', PDO::PARAM_STR');
}
else if(is_bool($val)){
$_stmt->bindValue(':'.$field.'\', '.$val.', PDO::PARAM_BOOL');
}
else if(is_null($val)){
$_stmt->bindValue(':'.$field.'\', '.$val="null".', PDO::PARAM_NULL');
}
else {
$_stmt->bindValue(':'.$field.'\', '.$val.', NULL');
}
$result = $_stmt->execute();
$num = $_stmt->rowCount();
}
}
catch(PDOException $e)
{
die('Error! The process failed while updating your record. <br /> Line #'.__LINE__ .' '.$e);
}
if ($result === true)
{
return true;
}
}
Check your bindValue calls: You give 1 parameter (a long string). It needs at least two. Check all the '
for example, it should be:
$_stmt->bindValue(':'.$field, $val, PDO::PARAM_INT);

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 only show fields that have values, and hide fields that do not have values?

I am trying to get this code to show only fields that have values, any fields that don't have values are not meant to be displayed. It doesnt seem to be working
Any idea what I am doing wrong?
My simple test form is here http://www.healthybrighton.co.uk/wse/node/1844
/**
* Build a table of submitted values
*
* #param $form_vals array Submitted form data
* #param $select_mapping array Map select components to their value|label chocies
* #return HTML of the themed table
*/
function _format_form_state($form_vals = array(), $select_mapping) {
$output = '';
$header = array();
$rows = array();
if (!empty($form_vals)) {
foreach ($form_vals as $component_name => $component_value) {
$rows = array_merge(
$rows,
_add_component_row(
$component_name,
$component_value,
0,
$select_mapping
)
);
}
}
$output .= theme('table', $header, $rows);
return $output;
}
/**
* Build a table of submitted values
*
* #param $select_mapping array Map select components to their value|label chocies
* #param $values array Submitted form data
* #return HTML of the themed table
*/
function _format_form_state($select_mapping, $values = array()) {
$header = array(t('First'), t('Second'), t('Third'), t('Fourth'));
$rows = array();
foreach ($values as $cname => $cval) {
$rows[] = array($cname, $cval, 0, $select_mapping);
}
return theme_table($header, $rows);
}
$select_mapping should be first argument in function.
Argument with default value should not be preceded by argument without a default value.