Pull data from wordpress database - unknown format - mysql

I need help pulling data from the field with unknown format of data structure. I am using a wordpress quiz plugin and i want to pull data from its backend table.
Data stored in answer_data is:
a:4:{
i:0;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:17:"Kieran Trippier ";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}
i:1;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:11:"Hugo Lloris";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}
i:2;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:14:"Moussa Dembele";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}
i:3;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:14:"Jan Vertonghen";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:1;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}
}
while looking at the structure of the table, data type of answer_data is longtext but has utf8_general_ci alongside it. I dont know what this means.
From this data i want to pull, quiz answers i.e.Kieran Trippier,Hugo Lloris,Moussa Dembele and Jan Vertonghen.
Any help or hint will be very much appreciated.
EDIT 1:
Array (
[0] => WpProQuiz_Model_AnswerTypes Object ( [_answer:protected] => Kieran Trippier [_html:protected] => [_points:protected] => 1 [_correct:protected] => [_sortString:protected] => [_sortStringHtml:protected] => [_mapper:protected] => )
[1] => WpProQuiz_Model_AnswerTypes Object ( [_answer:protected] => Hugo Lloris [_html:protected] => [_points:protected] => 1 [_correct:protected] => [_sortString:protected] => [_sortStringHtml:protected] => [_mapper:protected] => )
[2] => WpProQuiz_Model_AnswerTypes Object ( [_answer:protected] => Moussa Dembele [_html:protected] => [_points:protected] => 1 [_correct:protected] => [_sortString:protected] => [_sortStringHtml:protected] => [_mapper:protected] => )
[3] => WpProQuiz_Model_AnswerTypes Object ( [_answer:protected] => Jan Vertonghen [_html:protected] => [_points:protected] => 1 [_correct:protected] => 1 [_sortString:protected] => [_sortStringHtml:protected] => [_mapper:protected] => ) )
how to get values from this array?

That is some form of serialization. It seems to be an array a of 4 elements, each of which is further structure. The plugin understands; you probably don't need to understand it.
utf8_general_ci is the "Collation" to be used for comparing the LONGTEXT strings. It implies CHARACTER SET utf8, which is the 3-byte subset of UTF-8 (aka, MySQL's utf8mb4). This allows you to include characters from most languages around the world.
One would hope that the plugin provides a way to dissect this structure, rather than leaving you guessing. Furthermore, the plugin could change the structure without notice.
Here's the hint: See PHP's serialize() and unserialize().
Using the unserialized result:
$foo seems to be an array of 'objects' of class WpProQuiz_Model_AnswerTypes. One of the 'properties' of that object seems to be $_answer. So, see if this gives you the list of answers:
foreach($foo as $obj) {
echo $obj->_answer, "\n";
}
Or, to grab the answers into an array $answers:
$answers = array();
foreach($foo as $obj) {
$answers[] = $obj->_answer;
}

Related

Issues trying to access an associative array converted from JSON in Laravel

I'm working on a Laravel project that implements react-jsonschema-form and I need to convert the values saved in the database to an associative array so I can pluck certain values from it. However I am getting strange results when doing so.
Here is the code I use to grab the JSON data from the table and then convert to an array:
$form = Form::where('id', $formId)->get();
$converted = json_decode($form[0]->form_data, true);
$formArray = print_r($converted, 1);
return $formArray;
For testing purposes I am simply rendering the data in the browser.
The result from the above return is:
Array
(
[1] => Array
(
[1.1] => New
[1.2] => Ms
[1.3] => Isobel Fleming
[1.4] => Array
(
[uprn] => 52375918
[address_1] => Fake Street
[address_2] =>
[address_3] =>
[town_city] => BRISTOL
[postcode] => BS1 3KE
)
[1.5] => 0129711011
[1.6] => 0800999111
[1.7] => 0781100022
[1.8] => isobelfleming#jourrapide.com
)
)
which is great. However when I try and access anything from it like:
return $formData[1][1.1]
I get:
String offset cast occurred
If I try using a string:
return $formData[1]['1.1']
I get:
Illegal string offset '1.1'
So I am not sure what to do to access this data. The problem is, although it's not ideal to have the associate keys with decimals in them, this is the way the schema is set up and it's several thousand lines long - this is just a snippet of the form data.
Is there anything that can be done in order to get the data from this array?
I figured it out. It seems like the following line was the problem:
print_r($converted, 1);
It didn't need to be printed as an array, I should have just used the $converted variable to access the data like so:
return $converted[1]['1.1'];

CakePHP 1.3 not saving to database but sql statement is correct and insertID is increased correctly

I already searched many forums for my really strange issue, but I still can't figure out whats going wrong during my save process... The issue: Cake says, my data was saved, creates an autoincrement-ID but no record is stored in the database.
The environment
I have a cake-1.3.13 app running for some time and now needed to add another database table, which is of course related to other tables. My problem is saving records for the habtm-relation table, which looks like this:
CREATE TABLE IF NOT EXISTS `employees_projects_rejectreasons` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`employees_project_id` int(10) unsigned NOT NULL,
`rejectreason_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `employees_project_id` (`employees_project_id`,`rejectreason_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=6;
I scaffolded the simple model only with basic validation criteria.
<?php
class EmployeesProjectsRejectreason extends AppModel {
var $name = 'EmployeesProjectsRejectreason';
var $validate = array(
'employees_project_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'rejectreason_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'EmployeesProject' => array(
'className' => 'EmployeesProject',
'foreignKey' => 'employees_project_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Rejectreason' => array(
'className' => 'Rejectreason',
'foreignKey' => 'rejectreason_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
I created several records for Rejectreasons and EmployeesProjects, so I have some valid entries here in the database. Now I want to link them together by creating a new record in the given employees_projects_rejectreasons table. I try to do this from another controller (the EmployeesProjectsController). Here is my latest attempt to save the data:
$this->EmployeesProject->EmployeesProjectsRejectreason->create();
$eprData = array(
'EmployeesProjectsRejectreason' => array(
'employees_project_id' => (int)$id,
'rejectreason_id' => (int)$rrId
)
);
if($this->EmployeesProject->EmployeesProjectsRejectreason->save($eprData)) {
debug('successfully saved EPR with ID '.$this->EmployeesProject->EmployeesProjectsRejectreason->__insertID);
} else {
debug('could not save EPR with employees_project_id='.$id.' and rejectreason_id='.$rrId);
}
Now what happens
After I make an attempt to save a record, my debug gives me the following success report:
successfully saved EPR with ID 4
So the save() call returned true, a new ID was created by the auto_increment function of mySQL. So far so good. But when I check my database, there was no record created. But the auto_increment_counter was increased by 1, as if a record was stored, but it wasn't.
Running the app with debug-level 2, I can see the generated SQL-statement from cake, which looks perfectly fine to me:
INSERT INTO `employees_projects_rejectreasons` (`employees_project_id`, `rejectreason_id`) VALUES (3, 3)
If I run this statement directly on the sql server, the record ist inserted correctly.
What I already tried
I already tried different approaches with the save procedure. I tried working with setters instead of a data-array:
$this->EmployeesProject->EmployeesProjectsRejectreason->set('employees_project_id', $id);
as well, but it made no difference. After I wrote a custom save-method in the EmployeesProjectsRejectreason-Model, calling it from the controller, but it always produced the same result.
I tried
deleting the model-cache
restarting the server-instances and the server itself
Deleting the table and creating it again
disabling validation in the model
removing the unique foreign-key index
Saving with hard-coded and existing ids as foreign key
Some more strange behaviour
The last tests with hard-coded IDs in my controller code confronted me with more riddles: If I try storing existent foreign_key-IDs, the data is not saved as before. But if both IDs are hardcoded and NOT EXISTING (I used invented IDs 345 AND 567, which are definetely not existing in the database) a record was finally inserted!
Moreover I scaffolded Models, Views and Controllers for the new tables. When I run the scaffolded view "myApp/employees_projects_rejectreasons/add" and add a new record, everything works just fine.
I'm just not able to save the record from other controllers. Since I already have a huge headache, solving this problem, I highly appreciate any hint for a solution!!
Thanks in advance guys!
I finally found a solution to solve the issue. I still don't know, why the save code before did not work, but here is how I changed my code to make it work:
From my form, the data array comes in the following format:
Array
(
[EmployeesProject] => Array
(
[id] => 10
[user_id] => 0
[additional_information] => some comment text
[state] => absage
[Rejectreason] => Array
(
[0] => 1
[1] => 8
)
)
)
I searched for some solutions to save habtm relations in cakePHP directly with one call, but that does not seem to be possible in cake-1.3. So I created this pretty simple save routine in my EmployeesProjectController, which works perfectly fine for me:
if (!empty($this->data)) {
if ($this->EmployeesProject->save($this->data)) {
if(array_key_exists('Rejectreason', $this->data['EmployeesProject'])) {
foreach($this->data['EmployeesProject']['Rejectreason'] as $key => $rrId) {
$this->EmployeesProject->EmployeesProjectsRejectreason->create();
$this->EmployeesProject->EmployeesProjectsRejectreason->set('rejectreason_id', $rrId);
$this->EmployeesProject->EmployeesProjectsRejectreason->set('employees_project_id', $this->data['EmployeesProject']['id']);
if($this->EmployeesProject->EmployeesProjectsRejectreason->save()) {
}
}
}
}
}
Thanks #Yoggi for supporting me solving this issue!

CakePHP 2.3: Conditionally retrieve unique model information based on another model's use of it

I'm trying to create an AJAX form whereby the content of a select field populates based on the choice of a preceding select field (you see this a lot with 'country' populating 'state/province'). In my case, I want users to be able to choose their province only if active accounts exist in it.
The Javascript I can write no problem. Fetching the data is where I'm... not so much stuck as doing too much work. CakePHP likes to build select fields with options in an array of the form
$options = array(select_option_value => display_text)
My strategy, though functional, must be more convoluted than cake intended (this a is segment of a controller method).
$provinceData = $this->Account->find('all',array('recursive' => 0,
'joins' => array(
array(
'table' => 'provinces',
'type' => 'LEFT',
'conditions' => array('Account.province_id = provinces.id')
)),
'fields'=>array('provinces.id', 'provinces.name', 'provinces.abbrev'),
'conditions' => array('registration > 2')));
$provinces = array();
foreach($provinceData as $pd) {
/*note: lowercase, plural below b/c can't get 'alias' => 'Province'
to work in joins array above : ( */
$id = $pd['provinces']['id'];
$name = $pd['provinces']['name'];
$provinces[$id] = $name;
}
$this->set(compact('provinces'));
Can anyone point out a more appropriate way to do this? I assume there must be a MySQL query that can do this, but I'm pretty bad at writing elaborate MySQL queries in the first place, let alone via Cake's convention (and, for you MySQL gurus out there, I'm happy to do this from a Model->query(//MySQL code) call instead!
Any and all help truly appreciated.
Assuming the relationship Account belongsTo Province you can try this code:
$accounts = $this->Account->find(
'all',
array(
'fields' => array('Account.province_id', 'Province.name'),
'conditions' => array('Account.registration > 2'),
'group' => 'Account.province_id'
)
);
$provinces = Hash::combine($accounts, '{n}.Account.province_id', '{n}.Province.name');
$this->set(compact('provinces'));
edit: missed bracket and a period instead of an underscore . Now should work

Is there a name for storing data where each line either has a semi-colon or curly braces?

I am trying to understand how a Wordpress plugin works with data, when I pull it from MySQL it comes out like this:
a:1:{s:9:"home-team";a:6:{s:2:"id";s:9:"home-team";s:4:"slug";s:9:"home-team";s:4:"type";s:6:"select";s:4:"name";s:9:"Home Team";s:11:"description";s:0:"";s:4:"data";a:4:{s:7:"options";a:3:{s:60:"wpcf-fields-select-option-3892e2c3ad45e24dc7f47ff2ba880c33-2";a:2:{s:5:"title";s:13:"Chicago Bears";s:5:"value";s:1:"1";}s:60:"wpcf-fields-select-option-09fbd82bfa4142df6439c8e15d96dbfc-1";a:2:{s:5:"title";s:15:"New York Giants";s:5:"value";s:1:"2";}s:60:"wpcf-fields-select-option-7c7df972f933545b37c41ca249c686b4-1";a:2:{s:5:"title";s:15:"Oakland Raiders";s:5:"value";s:1:"3";}}s:8:"validate";a:1:{s:8:"required";a:3:{s:6:"active";s:1:"1";s:5:"value";s:4:"true";s:7:"message";s:22:"This Field is required";}}s:19:"conditional_display";a:2:{s:8:"relation";s:3:"AND";s:6:"custom";s:0:"";}s:16:"disabled_by_type";i:0;}}}
Is there a name for the way this is stored? To me it looks a little bit like JSON, but of course this is not JavaScript. Also, is there a way to clean it up easily (by using an online tool), so the first few lines would look like this:
a:1: {
s:9:"home-team";
a:6: {
s:2:"id";
s:9:"home-team";
s:4:"slug";
s:9:"home-team";
s:4:"type";
s:6:"select";
s:4:"name";
etc.. etc.. etc...
That's the PHP serialize format.
See : http://php.net/manual/en/function.serialize.php
Not sure how to get the formatted version exactly like you have it (but you could probably put that together easily), but here is another way to get an idea of what is in the serialized string:
$test_string= 'a:1:{s:9:"home-team";a:6:{s:2:"id";s:9:"home-team";s:4:"slug";s:9:"home-team";s:4:"type";s:6:"select";s:4:"name";s:9:"Home Team";s:11:"description";s:0:"";s:4:"data";a:4:{s:7:"options";a:3:{s:60:"wpcf-fields-select-option-3892e2c3ad45e24dc7f47ff2ba880c33-2";a:2:{s:5:"title";s:13:"Chicago Bears";s:5:"value";s:1:"1";}s:60:"wpcf-fields-select-option-09fbd82bfa4142df6439c8e15d96dbfc-1";a:2:{s:5:"title";s:15:"New York Giants";s:5:"value";s:1:"2";}s:60:"wpcf-fields-select-option-7c7df972f933545b37c41ca249c686b4-1";a:2:{s:5:"title";s:15:"Oakland Raiders";s:5:"value";s:1:"3";}}s:8:"validate";a:1:{s:8:"required";a:3:{s:6:"active";s:1:"1";s:5:"value";s:4:"true";s:7:"message";s:22:"This Field is required";}}s:19:"conditional_display";a:2:{s:8:"relation";s:3:"AND";s:6:"custom";s:0:"";}s:16:"disabled_by_type";i:0;}}}';
$unser = unserialize( $test_string);
print_r ( $unser );
Which will display:
Array
(
[home-team] => Array
(
[id] => home-team
[slug] => home-team
[type] => select
[name] => Home Team
[description] =>
[data] => Array
(
[options] => Array
(
[wpcf-fields-select-option-3892e2c3ad45e24dc7f47ff2ba880c33-2] => Array
(
[title] => Chicago Bears
[value] => 1
)
[wpcf-fields-select-option-09fbd82bfa4142df6439c8e15d96dbfc-1] => Array
(
[title] => New York Giants
[value] => 2
)
[wpcf-fields-select-option-7c7df972f933545b37c41ca249c686b4-1] => Array
(
[title] => Oakland Raiders
[value] => 3
)
)
[validate] => Array
(
[required] => Array
(
[active] => 1
[value] => true
[message] => This Field is required
)
)
[conditional_display] => Array
(
[relation] => AND
[custom] =>
)
[disabled_by_type] => 0
)
)
)
That's the way WordPress stores arrays and objects in the database. From the article WordPress serializes options and meta for you
In the most basic use case, serialization is a way to store arrays and objects directly in the database, which can only store numbers, text, and dates. Serialization takes an array and turns it into a serialized string. For example:
$data = array( 'apple', 'banana', 'orange' );
echo serialize( $data );
// Result is a string we can unserialize into an array:
// a:3:{i:0;s:5:"apple";i:1;s:6:"banana";i:2;s:6:"orange";}
WordPress has a few helper functions that we use instead of serialize() and unserialize() — maybe_serialize() and maybe_unserialize(). The first only serializes data that needs to be serialized — arrays and objects — and the second only unserializes data that is already serialized. (We have a lot of handy functions like these.)
You mention "when I pull it from MySQL it comes out like this", so you're probably not using the bundled functions to pull the data, like get_option(), get_post_meta() and get_user_meta(). Those functions take care of unserializing the data.
Worth noting that you should use a tool like WordPress (and others) Search and Replace Tool to search/replace inside the database. As it takes care of replacing strings inside serialized data.
You cannot simply change:
a:3:{i:0;s:5:"apple";i:1;s:6:"banana";i:2;s:6:"orange";}
to
a:3:{i:0;s:5:"grapefruit";i:1;s:6:"banana";i:2;s:6:"orange";}
Because it should be s:10:"grapefruit";, being 10 the number of characters in the string.

cakephp COUNT items per month in a year

How do you use cakephp to count, for example the number of posts, made every month in a year?
Preferably using Model->find('count') and get the data in an array.
I just did something similar, using only CakePHP (no direct queries). It works in CakePHP 2, haven't tested in 1.x.
The code for your example would be something like this:
$params = array(
'recursive' => -1,
'fields' => array('id', 'MONTH(created)')
'group' => array('YEAR(created)', 'MONTH(created)')
);
$numberOfPosts = $this->Model->find('count', $params);
This comes close
Query
$data = $this->Post->query("SELECT COUNT(id),MONTH(created) FROM posts GROUP BY YEAR(created), MONTH(created);");
Return
Array
(
[0] => Array
(
[0] => Array
(
[COUNT(id)] => 1
[MONTH(created)] => 3
)
)
[1] => Array
(
[0] => Array
(
[COUNT(id)] => 2
[MONTH(created)] => 4
)
)
)
When using cake, I prefer to stay as close to the framework as possible. This means that I try to avoid writing queries directly in the controllers because this results in the model code being everywhere. Therefore I recommend one of two solutions
1: (and what I do with more complicated stuff): Create a view for the calculation that you want to do and create a model to match.
2: Use a query as mentioned before, but put it in the model class, not the application class.