I want to have a result like this, to expand all nodes and make a defined treeview.
var defaultData = [
{
text: 'Parent 1',
href: '#parent1',
tags: ['4'],
nodes: [
{
text: 'Child 1',
href: '#child1',
tags: ['2'],
nodes: [
{
text: 'Grandchild 1',
href: '#grandchild1',
tags: ['0']
},
{
text: 'Grandchild 2',
href: '#grandchild2',
tags: ['0']
}
]
},
{
text: 'Child 2',
href: '#child2',
tags: ['0']
}
]
},
{
text: 'Parent 2',
href: '#parent2',
tags: ['0']
},
{
text: 'Parent 3',
href: '#parent3',
tags: ['0']
},
{
text: 'Parent 4',
href: '#parent4',
tags: ['0']
},
{
text: 'Parent 5',
href: '#parent5' ,
tags: ['0']
}
];
I've create a table like this, is it correct?
and how to query them in order to have result as above by json_encode the result?
First of all, you need to fix your table. It is highly irregular and text values will not work well with matching in any language. Try a table like this:
------------------------------
| id | parent | desc |
------------------------------
| 1 | 0 | parent 1 |
------------------------------
| 2 | 0 | parent 2 |
------------------------------
| 3 | 0 | parent 1 |
------------------------------
| 4 | 0 | parent 2 |
------------------------------
| 5 | 0 | parent 1 |
------------------------------
| 6 | 1 | child 1 |
------------------------------
| 7 | 1 | child 2 |
------------------------------
| 8 | 6 | Grandchild 1 |
------------------------------
| 9 | 6 | Grandchild 2 |
------------------------------
id and parent should be integer fields and desc can be text/varchar. Root or top level items should have a parent value of zero (0).
Then you can use a script similar to:
$db = new mysqli('127.0.0.1', 'your_db_user', 'your_secure_password', 'your_db_schema');
if( $mysqli->connect_error ) {
echo 'Something went wrong: ' . $mysqli->connect_error;
}
$json = [];
function sanitize_id($id) {
return preg_replace( '/[^a-z0-9]/', '', strtolower($id) );
}
function recursive( $parentId, &$json ) {
global $mysqli;
if ($stmt = $mysqli->prepare("SELECT * FROM your-table WHERE parent = ?")) {
// Bind parent id to query
$stmt->bind_param('i', $parentId);
$results = $stmt->execute();
// Loop over results
while ( $result = $results->fetch_assoc() ) {
// Add result to JSON structure at referenced location
$json[] = [
'text' => $result['desc'],
'href' => '#' . sanitize_id($result['desc']),
'tags' => ['0'], // Are the tags another field?
'nodes' => []
];
// Rerun recusive function to check for and add any children
recursive( $result['id'], $json['nodes'] );
}
$stmt->close();
}
};
recursive(0, $json);
echo json_encode( $json );
$db->close();
Related
In my WordPress database I have three tables wp_companies which stores some company info and wp_product_types which stores a bunch of product types that a company can assign them selves then I have wp_company_products which is used to assign product types to a company using ids.
Heres an example of how the database looks:
wp_companies
id | company_name | member_type | logo
-----------------------------------------------------------------
1 | Google | full | https://via.placeholder.com/150
-----------------------------------------------------------------
2 | Crunchyroll | full | https://via.placeholder.com/150
wp_products
id | product_name |
----------------------
1 | Car Insurance |
----------------------
2 | House Insurance |
----------------------
3 | Life Insurance |
wp_company_products
id | company_id | product_id
----------------------------
1 | 1 | 2
----------------------------
2 | 2 | 1
----------------------------
3 | 1 | 3
Here's my current MySQL query that simply shows the data in wp_companies
add_action('rest_api_init', function() {
register_rest_route('custom-routes/v1', 'members', array(
'methods' => 'GET',
'callback' => 'get_members'
) );
});
function get_members($data) {
global $wpdb;
$query = $wpdb->get_results( "SELECT company_name, member_type, logo, site_url FROM {$wpdb->prefix}companies ORDER BY RAND()" );
foreach ( $query as $member ) {
$member_data[] = array(
"company_name" => $member->company_name,
"member_type" => $member->member_type,
"logo" => $member->logo,
);
}
return $member_data;
}
This displays my data like so on my api end point:
[
{
"company_name":"Google",
"member_type":"full",
"logo":"https://via.placeholder.com/150",
},
{
"company_name":"Crunchyroll",
"member_type":"full",
"logo":"https://via.placeholder.com/150",
}
]
But what I want is to combine the wp_companies and wp_company_products tables so that my data is displayed something like this on the api end point:
[
{
"company_name":"Google",
"member_type":"full",
"logo":"https://via.placeholder.com/150",
"products": [
"House Insurance",
"Life Insurance"
]
},
{
"company_name":"Crunchyroll",
"member_type":"full",
"logo":"https://via.placeholder.com/150",
"products": [
"Car Insurance",
]
}
]
How can I structure my MySQL query to be able to achieve this?
Please try this
function get_members($data) {
global $wpdb;
$query = $wpdb->get_results( "SELECT company_name, member_type, logo, site_url FROM {$wpdb->prefix}companies ORDER BY RAND()" );
foreach ( $query as $member ) {
$productQuery = $wpdb->get_results( "SELECT product_name FROM wp_products WHERE id IN (SELECT product_id from wp_company_products WHERE compony_id = '{$member->id}') " );
$products = array();
foreach ( $productQuery as $prduct ) {
array_push($products ,$prduct->product_name);
}
$member_data[] = array(
"company_name" => $member->company_name,
"member_type" => $member->member_type,
"logo" => $member->logo,
"products" => $products
);
}
return $member_data;
}
I have a Select2 list which I want to populate with a nested structure for the data:
Level 1
Condition 1
Condition 2
Level 2
Condition 3
Condition 4
etc
The JSON needs to be in the following format:
data: [{
'text': 'Level 1',
'children': [{
'id': 1,
'text': 'Condition 1'
}, {
'id': 2,
'text': 'Condition 2'
}, ],
'text': 'Level 2',
'children': [{
'id': 3,
'text': 'Condition 3'
}, {
'id': 4,
'text': 'Condition 4'
}, ]
}]
The JQuery Select2:
$.ajax( {
url: "scripts/get_conditions.php",
dataType: 'json'
} ).then( function ( response ) {
$( "#condition_tree" ).select2( {
placeholder: "Select a Condition...",
allowClear: true,
width: 'resolve',
containerCssClass: "show-hide",
data: response
} );
} );
Currently using the following PHP and MySQL which I am unsure of how to change to produce the required results:
$query = 'SELECT * FROM mcondition ORDER BY mcondition_name ASC';
$result = $connection->query( $query );
$presentations = array();
while ($row = mysqli_fetch_array($result)) {
$mconditions[] = array("id"=>$row['mcondition_pk'], "text"=>$row['mcondition_name']);
}
echo json_encode($mconditions);
?>
And the mcondition table:
+---------+-----------+------------------------------+
| mcondition_pk | mcondition_name | mcondition_level |
+---------+-----------+------------------------------+
| 1 | Condition 1 | Level 1 |
+---------+-----------+------------------------------+
| 2 | Condition 2 | Level 1 |
+---------+-----------+------------------------------+
| 3 | Condition 3 | Level 2 |
+---------+-----------+------------------------------+
| 4 | Condition 4 | Level 2 |
+---------+-----------+------------------------------+
Note PHP version is 5.3.3, no chance of upgrading at present.
Use the level name as key of a two-dimensional array to gather your data under, add each row’s data to the children under the appropriate key.
// fake mysql row data
$data = [
['mcondition_pk' => 1, 'mcondition_name' => 'Condition 1', 'mcondition_level' => 'Level 1'],
['mcondition_pk' => 2, 'mcondition_name' => 'Condition 2', 'mcondition_level' => 'Level 1'],
['mcondition_pk' => 3, 'mcondition_name' => 'Condition 3', 'mcondition_level' => 'Level 2'],
['mcondition_pk' => 4, 'mcondition_name' => 'Condition 4', 'mcondition_level' => 'Level 2'],
];
$temp = [];
// foreach loop over fake data, replace that with your original `while(…)` again
foreach($data as $row) {
$temp[$row['mcondition_level']]['text'] = $row['mcondition_level'];
$temp[$row['mcondition_level']]['children'][] = [
'id' => $row['mcondition_pk'],
'text' => $row['mcondition_name']
];
}
// replace the associative keys with simple numeric ones again
$temp = array_values($temp);
echo json_encode($temp);
Similar too:
PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE
I want to do the same with:
PDO::FETCH_OBJ
Means I want to pick each row as an object named by the first value.
Example:
id name url
1 Test www.test.de
2 Test2 www.test2.de
Select name, id, url FROM whatever;
$processes = $result->fetchAll(PDO::FETCH_OBJ);
returns the objects idexed from 0 - x
fetchAll(PDO::FETCH_ASSOC | PDO::FETCH_GROUP)
Returns it nearly like I want just 2 downsides:
test {
0: [
'id': 1,
'src': 'www.test.de'
]
}
First is I want to keep name in the object (could douple select (select name, name ...) and I have the unecessary array inside.
So any idea how I get it to this:
test [
'name': 'test',
'id': 1,
'src': 'www.test.de'
]
test2 [
'name': 'test2',
'id': 2,
'src': 'www.test2.de'
]
You can use this:
$dbh = new PDO('mysql:dbname=my;host=localhost', 'root', '');
$sth = $dbh->prepare("SELECT name, id, name, url FROM data");
$sth->execute();
var_dump($sth->fetchAll(PDO::FETCH_OBJ | PDO::FETCH_GROUP | PDO::FETCH_UNIQUE));
The output will be like this:
array(3) {
'test 1' =>
class stdClass#6 (3) {
public $id =>
string(1) "4"
public $name =>
string(6) "test 1"
public $url =>
string(13) "www.gmail.com"
}
'test 2' =>
class stdClass#4 (3) {
public $id =>
string(1) "2"
public $name =>
string(6) "test 2"
public $url =>
string(14) "www.google.com"
}
'test 3' =>
class stdClass#5 (3) {
public $id =>
string(1) "3"
public $name =>
string(6) "test 3"
public $url =>
string(21) "www.stackoverflow.com"
}
}
But be noticed: if you add duplicate values into the name column, you will get values of last record with the same name. In my example above I have table with this dataset:
select * from data;
+----+--------+-----------------------+
| id | name | url |
+----+--------+-----------------------+
| 1 | test 1 | www.ya.ru |
| 2 | test 2 | www.google.com |
| 3 | test 3 | www.stackoverflow.com |
| 4 | test 1 | www.gmail.com |
+----+--------+-----------------------+
4 rows in set (0,00 sec)
So you have data from record with ID = 4 in object named "test 1".
I'm new in Yii2. I am using the DepDrop widget provide by Kartik. Now, I can pick data from column1, however, the related data in column2 doesn't show up. I can't even click on it.
Here is partial of the content of mysql table.
ID | name | sub_ID | category
1 | up | 11 | T-shirt
1 | up | 12 | jet
2 | shoe | 21 | nike
2 | shoe | 22 | adidda
Here is my _form.php code
<?= $form->field($model, 'category')->dropDownlist(
ArrayHelper::map(itemcategory::find()->all(), 'ID', 'name'), ['id' => 'cat_id', 'prompt' => 'Select…']
);?>
<?= $form->field($model, 'subcategory')->widget(
DepDrop::classname(), [
'options' => ['id' => 'subcategory', 'placeholder' => 'Select…'],
'pluginOptions' => [
'depends' => ['cat_id'],
'url'=>\yii\helpers\Url::to(['/positemcategory/Subcat'])
]
]
)?>
Here is my model ItemCategory.php code
public function getSubCatList($cat_id)
{
$data = self::find()->where(['ID' => $cat_id])->select(['sub_ID AS id', 'subcategory AS name'])->asArray()->all();
return $data;
}
And here is the controller Itemcategory.php code
public function actionSubcat()
{
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$cat_id = $parents[0];
// $out = \app\models\ItemCategory::getSubCategoryList($cat_id);
$out = self::getSubCatList($cat_id);
echo Json::encode(['output'=>$out, 'selected'=>'']);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}
I want to let user pick the item by its name, and save only the ID in another table in mysql instead of the full name.
Use ArrayHelper of Yii2.
$out = self::getSubCatList($cat_id);
echo Json::encode(['output'=>ArrayHelper::map($out,'id','name'),'selected'=>'']);
As a result you will get array with id as key and name as value.
author id | name
1 Mike
2 Dive
3 Stiv
book id | title
1 ABC
2 War
book_author id_book | id_author
1 1
1 2
2 3
app/models/Book.php
public function getAuthors()
{
return $this->hasMany(Authors::className(), ['id' => 'id_author'])->viaTable('book_author',['id_book' => 'id']);
}
In view:
foreach (Books::findAll([1, 2]) as $book)
{
echo sprintf('%s | %s',
$book->title,implode(', ',
$book->getAuthors()));
}
Always returned implode(): Invalid arguments passed in $book->getAuthors()));
getAuthors() - doesn't choose author, why?
Need:
ABC | Mike, Dive
War | Stiv
$book->getAuthors() get object arrays. You should get simple array. Try this code:
foreach (Books::findAll([1, 2]) as $book)
{
$authors = ArrayHelper::toArray($book->getAuthors()->all(), [
'app\models\Authors' => [
'name', 'id'
]
]);
echo sprintf('%s | %s',
$book->title,implode(', ',
ArrayHelper::map($authors, 'id', 'name')));
}