Phalcon: specific column on joined PHQL - phalcon

The below PHQL generates a complex resultset like it should:
$phql = "SELECT User.*, ProductUser.* "
. "FROM ProductUser "
. "INNER JOIN User "
. "WHERE ProductUser.product_id = 5";
Replacing ProductUser.* with an existing column like ProductUser.id causes an error:
MESSAGE: The index does not exist in the row
FILE: phalcon/mvc/model/row.zep
LINE: 67
This is version 2.0.6. Is this a bug or am I making a mistake somewhere? According to the documentation it should be fine.

It was my mistake (expecting the row to always be an object).
I hope this helps someone because looping complex resultsets is not in the documentation.
$result = $this->modelsManager->createQuery($phql)->execute();
if ($result instanceof \Phalcon\Mvc\Model\Resultset\Complex) {
foreach ($result as $rows) {
foreach ($rows as $row) {
if (is_object($row)) {
$modelData = $row->toArray());
// this is what I needed
} else {
$id = $row;
}
}
}
}

First of all you're missing the ON clause in your query.
Anyways, it's easier and more error prone to use Phalcon's query builder for querying:
<?php
// modelManager is avaiable in the default DI
$queryBuilder = $this->modelsManager->createBuilder();
$queryBuilder->from(["product" => 'Path\To\ProductUser']);
// Inner join params are: the model class path, the condition for the 'ON' clause, and optionally an alias for the table
$queryBuilder->innerJoin('Path\To\User', "product.user_id = user.id", "user");
$queryBuilder->columns([
"product.*",
"user.*"
]);
$queryBuilder->where("product.id = 5");
// You can use this line to debug what was generated
// $generatedQuery = $queryBuilder->getPhql();
// var_dump($generatedQuery);
// Finish the query building
$query = $queryBuilder->getQuery();
// Execute it and get the results
$result = $query->execute();
// Now use var_dump to see how the result was fetched
var_dump($result);
exit;

Related

Object of class PDOStatement could not convert to string

I changed my mysqli connection to PDO statment so i have to much error on my page this is the my code pls help us
.
.
.
if ($fn && $ln && $e && $p) { // If everything's OK...
// Make sure the email address is available:
//$q = "SELECT user_id FROM users WHERE email='$e'";
$q = $dbc->query("SELECT user_id FROM users WHERE email='$e'");
$q->execute(array($e));
$r = $q->fetchAll(PDO::FETCH_ASSOC);
//$r = mysqli_query ($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));
if (mysqli_num_rows($r) == 0) { // Available.
// Create the activation code:
$a = md5(uniqid(rand(), true));
Here is your code converted to PDO.
// Make sure the email address is available:
$q = $dbc->query("SELECT user_id FROM users WHERE email=?");
$q->execute(array($e));
$r = $q->fetchColumn();
if (!$r) { // Available.
// Create the activation code:
$a = md5(uniqid(rand(), true));
Three things has been corrected
You have to always use a placeholder tp represent a variable in the query.
To get a single value from the result, fetchColumn have to be used instead of fetchAll
No need for the manual reporting, as PDO can report its errors automatically, if confugired properly, as described in this tutorial I wrote

SilverStripe 3 Left Join Missing argument

I have a data object related to some other data objects and I am trying to build a reporting page for them.
So far I've got the code below in my page controller to display a form where I will begin to select filtering options for the report.
However I am getting this error due to the left join:
[Warning] Missing argument 2 for SQLQuery::addLeftJoin()
It would seem that the raw2sql is outputting this when I've debugged:
\'AgeRangeData\', \'CallEvent.AgeRangeData ID=AgeRangeData.ID)\'
I'm assuming that the backslashes is what is causing the error
public function ReportingFilter(){
$DataObjectsList = $this->dbObject('DataObjects')->enumValues();
$fields = new FieldList(
new DropdownField('DataObjects', 'Data Objects', $DataObjectsList)
);
$actions = new FieldList(
new FormAction("FilterObjects", "Filter")
);
return new Form($this, "ReportingFilter", $fields, $actions);
}
public function FilterObjects($data, $form){
$data = $_REQUEST;
$query = new SQLQuery();
$object = $data['DataObjects'];
$leftJoin = Convert::raw2sql("'" . $object . "', 'CallEvent." . $object . " ID={$object}.ID)'");
$query->selectField("CallEvent.ID", "ID");
$query->setFrom('`CallEvent`');
$query->setOrderBy('CallEvent.Created DESC');
$query->addLeftJoin($leftJoin);
return $query;
}
SQLQuery::addLeftJoin() takes two arguments. The first is the table to join on and the second is the "on" clause.
You want:
$query = new SQLQuery();
$query->addLeftJoin($object, '"CallEvent"."ID" = "' . $object . '"ID"');
You'd need to escape $object appropriately, of course.
NB: Your code looks a little fragile as you're not ensuring that you $object actually has a DB table. I recommend you use ClassInfo::baseDataClass($object). This will have the added benefit that it will also sanitise your class name and ensure it's a real class.

How can I use sql data in header link?

I need to use a variable from SQL. I can print which I wrote the variable. But I can't use
it when it out of while query.
Here is the SQL:
if ($result = $mysqli->query("SELECT * FROM organize WHERE organize.nid=$nid"))
{
// display records if there are records to display
if ($result->num_rows > 0)
{
while ($row = $result->fetch_object())
{
echo $row->nid;
echo $row->omid;
$id=$row->omid;
}
}
// if there are no records in the database, display an alert message
else
{
echo "No results to display!";
}
}
// show an error if there is an issue with the database query
else
{
echo "Error: " . $mysqli->error;
}
And the header under this scripts.
header("Refresh: 10;http://localhost/records.php?mid= $id ");
I know this is not right way. But I show you what I want. Need to use that 'omid' in header inseat of '$id'.
Finally I resolved it. This scripts like the above codes. I didn't understand why It didn't work. Maybe because I should not use
echo $row->nid;
echo $row->omid;
or
$id=$row->omid;
The right usage is as follows:
while ($row = $result->fetch_object())
{
$dd=$row->omid;
}
header("Refresh: 2;http://localhost/records.php?mid= $dd");

Multiple between statements in sql builder

I am creating a fairly large query using laravel 4 sql builder. it roughly looks like, get data from table
where(yada yada)and where age between(yada, yada)or between(yada, yada) and where(yad yada).
But what I want is this.
where(yada yada)and where (age between(yada, yada)or between(yada, yada)) and where(yad yada).
some code:
$query = Subject::grabBasic();// start writing query, which results to grab.
$agelength = sizeof($fromAgeValue);
$count = 0;
$ageflag = 0;
foreach( array_combine($fromAgeValue, $toAgeValue) as $from=>$to ){
$count+=1;
if($ageflag==0){
if(($from!=null)&&($to!=null)){
$query = Subject::addfromAgeToAge($query, $from, $to);
$ageflag=1;
}
}else if(($from!=null)&&($to!=null)){
$query = Subject::orfromAgeToAge($query, $from, $to);
}
}
... keep adding to $query
Subject code:
static function addfromAgeToAge($query, $fromAge, $toAge){
return $query->whereBetween('Age', array($fromAge, $toAge));
}
static function orfromAgeToAge($query, $fromAge, $toAge){
return $query->orWhereBetween('Age', array($fromAge, $toAge));
}
So, is there a way to write the addToAge builder function to take in the arrays of fromage and toage values and create a statement, which when added to the rest of the query, will give the desired results. e-g. the sql query will have parentheses in the correct place.
I would also like to do this without raw queries, I suspect there is a way to do this I just haven't been able to find it.
Thanks,
I buckled and used raw queries :(
Here's what it looks like.
$agecounter = 0;// tells me how many from age to age pairs were filed out coorrectly.
foreach( array_combine($fromAgeValue, $toAgeValue) as $from=>$to ){
if(($from!=null)&&($to!=null)){
$agecounter+=1;
}
}
$agelength = sizeof($fromAgeValue);
$ageflag = 0;
foreach( array_combine($fromAgeValue, $toAgeValue) as $from=>$to ){
if($ageflag==0){
if(($from!=null)&&($to!=null)){
$query = Subject::addfromAgeToAge($query, $from, $to, $agecounter); // ages put in for loop when multiple are added.
$ageflag=1; // add or's
$agecounter -=1;
}
}else if(($from!=null)&&($to!=null)){
$query = Subject::orfromAgeToAge($query, $from, $to, $agecounter);
$agecounter -=1;
}
}
and in my Model:
static function addfromAgeToAge($query, $from, $to, $count){
if($count>1){
return $query->whereRaw('( Age between ? and ?', array($from, $to));
}
return $query-> whereBetween('Age', array($from, $to));
}
static function orfromAgeToAge($query, $from, $to, $count){
if($count==1){
return $query->orWhereRaw(' Age between ? and ?)', array($from, $to));
}
return $query->orWhereRaw(' Age between ? and ?', array($from, $to));//('Age', array($fromAge, $toAge));
}
Hope this helps someone else put ()'s in a query builder.

CodeIgniter: Problem with variable sent to model

I'm inheriting someone else's project and I am trying to familiarize myself with it. I have little experience with CI.
On one of the views there's is a drop down form, on change calls a JS function:
$(document).ready(function()
{
// admin contorller drop down ajax
$("#catagoryDropDownList").change(function()
{
getCatagoriesItems();
});
// initiate table sort
TableSorter.prepareTable($("#dataResultsTable"));
});
// ajax request triggered by catagory drop down menu selection
function getCatagoriesItems()
{
blockPage();
// get base url of current site
var baseurl = $("#site_url_for_ajax").val();
// get adminType
var adminType = $("#admin_type").val();
// get catagory id
var catId = $("#catagoryDropDownList option:selected").attr("id");
var queryString = baseurl + "home/ajaxCatagorySelection/" + catId + "/" + adminType;
$.get(queryString, function(data)
{
var obj = jQuery.parseJSON(data);
// dump data into table when request is successful
$("#dataResultsTable tbody").html(JSONParser.parseHomeDropDownSelectedJSON(obj));
// unblock page when done
$.unblockUI();
});
}
I've logged the two values, catID and adminType, they're both integers, catID will be between 1-10 and adminType = 1. There both references to int values in a database. catID is referencing a field titled 'categoryID'. catID 6 = all. None of the entries in the db have 6 as their value, thus ensuring if you filtered for not equaling 6 you'd get all. They get passed to a function called ajaxCatagorySelection in the controller file home.php. So far, so good. Here's that function:
public function ajaxCatagorySelection($tableName, $id)
{
$vars = new DatabaseRetriever($id);
$resultsArray = $vars->getDataForSpecifiedTable($tableName, $id);
echo json_encode($resultsArray);
}
and that function itself is referencing a model (database_retriever.php) and the class DatabaseRetriever and I'm assuming passing the variables along to the function getDataForSpecifiedTable. I say assuming because the variable names have changed significantly from catID to $tableName and adminType to $id. Here is getDataForSpecifiedTable:
public function getDataForSpecifiedTable($catagoryInfo, $databaseID)
{
// connect to database
$sql = $this->connect($databaseID);
if ($catagoryInfo != 6) {
// build SQL Query and query the database
$result = $sql->query("SELECT fileId, fileTitle, filePath, fileTypeExt, fileDescription, fileModed from admin_files where catagoryId = '" . $catagoryInfo . "' and adminId = '" . $databaseID . "'");
} else {
$result = $sql->query("SELECT fileId, fileTitle, filePath, fileTypeExt, fileDescription, fileModed from admin_files where catagoryId = '" . $catagoryInfo . "' and adminId = '" . $databaseID . "'");
}
// declare array
$items = array();
// retriever rows from database and build array
while ($row = $result->fetch_row())
{
array_push($items, $row);
}
// disconnect from database
$this->disconnect();
// return data in array
return $items;
}
the variable names have changed again but you can tell they are suppose to do what I wrote above by looking at the query. Here's the problem. I added the conditional "if ($catagoryInfo != 6)...", if I don't put the else in there then CI throws out warning errors that no data is being returned. I return $categoryInfo and in the FireBug console I get the correct integer. I've tried the conditional as an integer and a string with both failing. Any ideas what might be happening here?
If database_retriever.php is a model, you should call it like so:
$this->load->model('database_retriever');
$resultsArray = $this->Database_retriever->getDataForSpecifiedTable($tableName, $id);
Also, make sure your model extends Model (or extends CI_Model in CodeIgniter 2).
NOTE: $.getJSON, will auto-parse JSON for you, so you don't need to call parseJSON.