PDO Prepared Statement Execution - How to get only associative keys? - arrays

This should be a simple thing to solve...
I have got these estatements when a user logs in:
$query = $conn->prepare("SELECT * FROM admins WHERE username = :user AND password = :pass");
$query->bindValue(":user", $user);
$query->bindValue(":pass", md5($pass));
$query->execute();
Now if the user exists, I return the user information from the database, but if not, I return false instead...
if($query->rowCount() > 0) {
$admininfo = $query->fetchAll(PDO::FETCH_ASSOC);
} else {
return false;
}
But when I var_dump the variable $admininfo I get an array with a number key before the actual array... like this:
array (size=1)
0 => <---- I DONT KNOW WHERE THIS COME FROM. I USED PDO::FETCH_ASSOC
array (size=9)
'id' => string '1' (length=1)
'username' => string 'admin' (length=5)
'password' => string '21232f297a57a5a743894a0e4a801fc3' (length=32)
'permissionid' => string '1' (length=1)
'name' => string 'Administrador' (length=13)
'lastname' => string 'Softing' (length=7)
'phonenumber' => null
'cellphonenumber' => null
'info' => null
I will put this information inside the SESSION array, so I want to access it by $_SESSION["admininfo"]["username"] or $_SESSION["admininfo"]["phonenumber"]
but I have to put something like this instead: $_SESSION["admininfo"][0]["phonenumber"].
How can I remove that 0 from the keys? Thank you!

According to the documentation for fetchAll, it will return an array of elements. This is because it is getting all of the rows in the table that match your criteria. In your case, you are only getting back one row, located at index 0. If you know you only want one result, use fetch instead of fetchAll. It will get rid of the 0.

You're using fetchAll. This will give you an array of DB rows -- of all the rows that were matched.
Use fetch in a while loop to go through individual rows one by one.

Related

CakePHP- Iterate Array

How can I Iterate over this ridiculously tedious array?
array (size=6)
0 =>
array (size=1)
'Question' =>
array (size=2)
'id' => string 'q_1' (length=3)
'question_desc' => string 'Is this correct?)' (length=15)
1 =>
array (size=1)
'Question' =>
array (size=2)
'id' => string 'q_10' (length=4)
'question_desc' => string 'Do you weigh less than 45 kilograms OR more than 160 kilograms.' (length=63)
This is a var_dump from a Session data! I need to get the question_desc field from each 'Question' array object.
This array has a purpose to its structure, but I understand your frustration as I shared it before I rtfm-ed!
$flattened_data = array();
foreach($your_main_array as $question)
{
foreach($question['Question'] as $question_param)
{
if($question_param == 'question_desc')
{
$flattened_data[] = $question_param;
// if you want to be really cool you can do this instead
// this will list the array with the question id as the key.
// $flattened_data[$question[id]] = $question_param;
}
}
}
// now flattened data has only what you require
return $flattened_data;
Cakes data form makes a lot more sense once you understand its ORM and how it uses model relations. Its actually a powerful tool for managing your data, but before you need all of that power it does seem like an encumbrance for simple tasks.

Cakephp value from array

I've read many similar topics here but not one helps me with problem.
i'm trying to get sections_id value from query in controller.
$query_id = "SELECT sections_id FROM sections WHERE name='".$table_name."'";
debug($id = $this->Info->query($query_id)); die();
there is debug result
array(
(int) 0 => array(
'sections' => array(
'sections_id' => '14'
)
)
)
and i tried in controller get value of id typing $id['sections']['sections_id'], or
$id['sections_id'] and many other types, nothing works. Do you have any idea ?
use $id[0]['sections']['sections_id'] to access it
For one result use
$data[0]['sections']['sections_id']
If query returns more than one result the use below code:
foreach($id as $data){
echo $data['sections']['sections_id']
}
Look for array index's carefully! Iinjoy

what it the find list error

I tyed get with the method $this>model->find() an array with ids of my model that have this form:
Array ( [0] => 2, [1] => 3) (value are the IDs)
and I try $this->model->find('list') I thought that would work too but for some strange reason I have done:
$this->model->find('list',array('recursive' => -1 ,'fields' => array('model.type_id'),'conditions'=>$cond));
and the query result is:
SELECT `model`.`round_id`, `model`.`type_id` FROM `database`.`model` AS `X` WHERE `X`.`Round_id` = '1'
If I make this query to the database returns two values ​​but cakephp returns only one:
Array ( [1] => 2 )
i do not know that may be going
I would use
$ids = $this->Model->find('list', array('fields' => array('id')));
if you really need the 0 based integer keys, you can still do:
$ids = array_values($ids);
but that is not necessary IMO.
Update:
After your question update the whole meaning of your question itself changed:
If you specify only id, they keys and values will both be filled with it.
Using 'fields' => array('round_id', 'type_id') you have round_id filling the keys, and type_id filling the values for find(list).
find(list) returns always a list (key + value row). If you don't want that use find(all) then.

Select validation between fields

What am I trying to do?
I have three fields (1 hidden, an id) and the user must complete one of the other two in order to pass validation.
So the user should fail validation if both fields are empty, but pass if one is completed.
1 2 3
A 0 B True
A B 0 True
A 0 0 False
I'm using CakePHP v2.1.3 so have access to the new validation rule enhancements.
The problem
I can't seem to find a reliable way to check both fields at the same time. I have so far tried looking at $this->data from the model and have found that validation is only passing a single instance of the data at a time. So there doesn't seem to be a way to compare the fields.
What I have so far
/**
* Custom validation to see if either of the two fields are set, if neither are, then we fail, if at least one is, we pass
* #param array $check
* #return boolean
*/
public function checkAttributes($check){
var_dump($check);
var_dump($this->data);
echo "<hr>";
// Check for an id value picked from a list
if(#is_numeric($check['attribute_value_id']) && isset($this->data['AdvertAttributeValue']['attribute_value_id'])){
return true;
}
// Check for a date value selected
if(#is_array($check['attribute_value_text']) && isset($this->data['AdvertAttributeValue']['attribute_value_text'])){
return true;
}
// Check for a text value
if(#is_string($check['attribute_value_text']) && isset($this->data['AdvertAttributeValue']['attribute_value_text'])){
return true;
}
return false;
}
This doesn't seem to do the trick as I think it can't check $this->data because the instance of it doesn't contain all the relevant fields.
The data
I should also mention that I am passing a large numeric array in. So these fields appear multiple times on the page, currently 12 dimensions. So accessing them directly through $this->data will be hard as they are not named dimensions, but are $this->data['Model'][<num>]['field'] = value
Validation
public $validate = array(
'attribute_value_id'=>array(
'notempty'=>array(
'rule'=>'checkAttributes',
'message'=>'Please select a value for your attribute',
'required'=>true,
),
),
'attribute_value_text'=>array(
'notempty'=>array(
'rule'=>'checkAttributes',
'message'=>'You must enter text for this attribute',
'required'=>true,
),
)
);
Data dump
Here I'll show the output of the var_dump() above. I have two validation rules in my Model, one for attribute_value_id and also one for attribute_value_text
// An id field selected from a list
array // $check
'attribute_value_id' => string '1' (length=1)
array // $this->data
'AdvertAttributeValue' =>
array
'attribute_value_id' => string '1' (length=1)
'id' => string '' (length=0)
// A text field
// Validating first time around on the id field
array // $check
'attribute_value_id' => string '' (length=0)
array // $this->data
'AdvertAttributeValue' =>
array
'attribute_value_id' => string '' (length=0)
'id' => string '' (length=0)
'attribute_value_text' => string '50' (length=2)
// Validating second time around on the text field
array // $check
'attribute_value_text' => string '50' (length=2)
array // $this->data
'AdvertAttributeValue' =>
array
'attribute_value_id' => string '' (length=0)
'id' => string '' (length=0)
'attribute_value_text' => string '50' (length=2)
// A date field
array // $check
'attribute_value_id' => string '' (length=0)
array // $this->data
'AdvertAttributeValue' =>
array
'attribute_value_id' => string '' (length=0)
'id' => string '' (length=0)
'attribute_value_text' =>
array
'month' => string '06' (length=2)
'day' => string '28' (length=2)
'year' => string '2012' (length=4)
The saveAll() method just calls saveMany() or saveAssociated() as appropriate. These methods will, by default, attempt to validate all of the data before saving any of it (via a call to validateMany()). However, as you can see in the source, that function validates each item individually, so the validation code won't have access to other records.
As I understand it, you need to cross-validate between multiple records before you save them. Although I've never done that, it sounds like a case for validation in the controller. You can make calls to Model::validate() or Model::validateAll() to ensure internal consistency of records. Then your controller can also implement whatever logic is necessary for your cross-record validation. Once that's done, you can make the save call with validation disabled:
$this->myModel->saveAll($this->request->data, array('validate'=>false));
Note that before you do any of this, you'll have to set your data to the model:
$this->myModel->set($this->request->data);
I realize this puts a lot of extra code in the controller that should ideally be in the model. I suppose it's possible that it could be done via one of the model callbacks, but I'm not sure how.
You can make use of Model::$data or Model::beforeValidate().

cakephp saveMany using $fieldList (no form)

I have this $data array: (built on a shell, not a form)
(debugged here)
array(
(int) 0 => array(
(int) 0 => 's511013t',
(int) 1 => 'id3422',
(int) 2 => '1'
),
(int) 1 => array(
(int) 0 => 's511013t',
(int) 1 => 'id3637',
(int) 2 => '1'
)
)
And using saveMany :
$this->Dir->saveMany($data, array( 'validate' => 'false', 'fieldList' => array('name','dir_dataname', 'project_id')));
Saving fails with no error.
I'm not sure if my $data array is well formatted, (I'm confused whether it should have another level) I built it from sql selects, etc. However it does contain all info I need saved, single model.
I'm running all this from a Shell and it does work to save a single record provided the field names everytime:
// this works
$this->Dir->save(array('name' => $data[0][0], 'project_id' => $data[0][2], 'dir_dataname' => $data[0][1]));
Already read Saving your data, and I'd really like to use saveMany and a fieldList due to my custom $data format. (I wouldn't like to have to insert field names on my $data).
(no sql_dump to show since is pretty cumbersome to get it from a shell task)
I've spent all evening trying to figure it out, can you point me in the right direction, Please?
IMHO, the keys in each arrays are not valid fields in your database table. They should represent the same name as your table field.
When you build the array from sql, the output should look like these - an associative array:
array(
(int) 0 => array(
(string) name => 's511013t',
(string) dir_dataname => 'id3422',
(string) project_id => '1'
),
(int) 1 => array(
(string) name => 's511013t',
(string) dir_dataname => 'id3637',
(string) project_id => '1'
)
)
Cake2.0 Docs
$this->Dir->saveMany($data);
You can get the log via
debug($this->Dir->getDataSource()->getLog());
It looks as if you are using fieldList incorrectly. fieldList is a list of fields that are to be whitelisted for saving to the database, not a "mapping" like you are using.
You need to specify field => value pairs in the array for each record, not numerical indexes. I may be wrong, but I've never seen that and it doesn't look to be that way according to docs.

Resources