in my wordpress blog i have a table consist of users and their products seperated by ";" for example :
mytable
----------------------
userid | products
----------------------
1 | camera
2 | books;keyboard;computer
3 | mouse;printer
4 | scanner
now in my script the user will add a new product so i need to check if that user has more than 3 products because in this case i will do nothing and will not add this product for him but if he has less than 3 products i need to add the new product to his products seperated by ";" something like :
$userid = 3;
$newproduct = "ball"
if (pruduct field for that user has more than 2 ";" ) {
do nothing
}else{
$wpdb->update(
'mytable',
array( 'product' => concat(product, ";", $newproduct)),
array( 'userid ' => $userid ),
array( '%s' ),
array( '%d' )
);
so the result in this example would be :
mytable
----------------------
userid | products
----------------------
1 | camera
2 | books;keyboard;computer
3 | mouse;printer;ball
4 | scanner
Despite the data normalization arguments, which are incredibly valid, if for some reason you cannot correct that and must work with what exists.
Select the products column as a string and use the PHP explode() and implode() functions. You'd end up with something like this:
$current_products = explode(';', $user['products']);
// $current_products is now an array of the user's products.
if !(count($current_products) >= 3) {
$current_products[] = $new_product;
}
$user_products = implode(';', $current_products);
// Insert $user_products into your table via UPDATE
The implode and explode functions convert strings to and from arrays based on given delimiters.
In WordPress, the right way to do this is with the user_meta table. With respect, your proposed way is not a good way.
You can set these values into the user_meta table with code like this.
$meta_key = '_my_products'; /* be sure to choose a unique key prefix */
add_user_meta( $userid, $meta_key, 'football', false );
add_user_meta( $userid, $meta_key, 'basketball', false );
You can get them back with code like this
$vals = get_user_meta( $userid, $meta_key, false );
foreach ($vals as $value) {
echo $i;
}
There are other functions for updating and deleting user_meta items. They work well. Read this. https://codex.wordpress.org/Function_Reference/get_user_meta
Related
I am trying to extract data from a Wordpress database so I can get it into a new database, but having a few issues figuring things out. This is just a small sample of how some of the Wordpress tables are like.
wp_posts
id | post_type | post_status |
----------------------------------
1 | portfolio | published | ... other data
wp_postmeta
id | post_id | meta_key | meta_value |
-----------------------------------------------------------------------
1 | 1 | item_submission_title | Some title | ... other data
2 | 1 | item_technology | a:1:{i:0;s:4:"2372";} |
3 | 1 | item_description | Some description |
wp_terms
id | term_id | name |
--------------------------------
1 | 2372 | Some name | ... other data
So essentially, I have to get all id's from wp_posts where post_type is portfolio and post_status is publish.
Using these id's I then need to get the meta_value for the 3 meta_key's shown in my wp_postmeta table.
The item_technology meta_value is serialized, so I need to then unserialize it. I then need to get its id (2372) and use this to obtain further data from the wp_terms table.
There is a lot more I need to do, but achieving the above will give me the understanding of how best to do this. I have a feeling I can somehow use joins here, but not sure.
At the moment, my attempt is very ineffecient and incomplete. This is what I currently have.
$conn = Database::getInstance();
$ids = getIDs($conn);
$dataArray = array();
foreach ($ids as $row) {
$data = getData($conn, $row['id']);
$dataArray[] = $data;
}
function getIDs($conn) {
$query = "SELECT `id` FROM `wp_posts` WHERE `post_type` = \"portfolio\" and `post_status` = \"publish\"";
$sql = $conn->dbc->prepare($query);
$sql->execute();
$row = $sql->fetchAll();
return $row;
}
function getData($conn, $id) {
$query = "SELECT `meta_value` FROM `wp_postmeta` WHERE `post_id` = $id AND `meta_key` = \"item_submission_title\"";
$sql = $conn->dbc->prepare($query);
$sql->execute();
$row = $sql->fetchAll();
return $row;
}
What would be the best way to achieve what I am after?
Thanks
Considering that you have a WordPress Database, I'll assume you also have a WordPress install attached to it. If not, you should, in order to make sure you get the data you want in the manner you want without having to recreate code that deals with the multitude of WP specific "idiosyncrasies".
So the first thing you'll do is "bootstrap" WordPress so you can obtain the DB connection and all of the WordPress functionality in one east step. So let's say you create a file in the WordPress root directory...
<?php
// This includes gives us all the WordPress functionality
require_once( dirname(__FILE__) . '/wp-load.php' );
// Set parameters to gather posts
$args = array(
'posts_per_page' => -1,
'offset' => 0,
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'portfolio',
'post_status' => 'publish',
'suppress_filters' => true
);
// Retrieve matching posts
$posts_array = get_posts( $args );
// Loop through posts to get Meta values
foreach ( $posts_array as $post )
{
$item_submission_title = get_post_meta( $post->ID, 'item_submission_title', true );
$item_technology = maybe_unserialize( get_post_meta( $post->ID, 'item_technology', true ) );
$item_description = get_post_meta( $post->ID, 'item_description', true );
// Do something with this information
...
}
Of course, you might now need to get it into the other DB. WordPress can also accommodate that with a simple and powerful interface...
$otherDB = new wpdb( 'username', 'password', 'database', 'localhost' );
$table = 'other_table';
$data = array(
'item_submission_title' => $item_submission_title,
'item_technology' => $item_technology,
'item_description' => $item_description,
);
$otherDB->insert( $table, $data );
More functions of the WPDB class can be found here: https://codex.wordpress.org/Class_Reference/wpdb
This code is supposed to check to see if a user is logged in when posting an input, if so, it then checks to see if the ItemID and User ID already have an entry in the table, and if so, it updates that entry rather than creating a duplicate.
This is the output I need from it:
+--------+-------+----------+
| ItemID | Price | user |
+--------+-------+----------+
| 1 | 20 | 27 |
+--------+-------+----------+
This is what I'm getting:
+--------+-------+----------+
| ItemID | Price | user |
+--------+-------+----------+
| 0 | 0 | 27 |
+--------+-------+----------+
Here is the full function if needed : http://pastebin.com/W0UM68UT
if ( is_user_logged_in() ) {
$hf_user = get_current_user_id();
$hf_username = $hf_user->user_login;
global $quanid;
$inputValue = isset($_POST[$quanid]);
global $newdb;
$newdb = new wpdb( 'user', 'pass', 'db', 'localhost' );
$retval = $newdb->get_results("SELECT * FROM $table WHERE ItemID = '$quanid' AND user = '$hf_username' ");
if($retval > 0)
{
//If user exists, update
$newdb->replace($table,array(
'ItemID' => '$quanid',
'Price' => $inputValue,
'user' => $hf_username
)
);
}
else
{
global $table;
global $newdb;
$newdb->insert(
$table,
array(
'ItemID' => $quanid,
'Price' => $inputValue,
'user' => $hf_username
)
);
}
} else {
global $error;
$error = "Error: You must be logged in to submit prices";
return;
}
}
Please don't use globals...
How to avoid using PHP global objects?
Change your SELECT statement to a count for better performance:
SELECT count( 1 ) FROM $table WHERE ItemID = '$quanid' AND user = '$hf_username'
On to your question:
It appears your global $quanid; and isset($_POST[$quanid]); return unexpected values so you should see where they're set. Try using:
var_dump right below these two lines:
global $quanid;
$inputValue = isset($_POST[$quanid]);
var_dump( $quanid );
var_dump( $inputValue );
var_dump( $_POST);
die;
I'm trying to figure out how to make this code work. Basically i have used MySQL to fetch an associative array containing multiple values.
example database: database name = Products
----------------------------------------------------------------.
| name | overcategory | category | subcategory |
| Talon | null | stud welding | capacitor discharge |
| cdss m3x40 | studs/bolts | cd-studs | stainless steel |
----------------------------------------------------------------.
I used the sentence SELECT name, overcategory, category, subcategory FROM Products WHERE 1 = 1;
In the actual database there are more entries, but they are not relevant for this question.
The result i want to output as a menu on the left hand side of the screen.
<nav>
<h1> "$overcategory" </h1>
<h2> "$category" </h2>
<h3> "$subcategory" </h3>
$productname
$productname3
<h1> "$overcategory2" </h1>
<h2> "$category2" </h2>
<h3> "$subcategory2" </h3>
$productname2
</nav>
i was thinking of doing this by creating a multidimensional array that would look something like this:
$testArray = array(
''=>array(
'Boltsveiseapparater'=>array(
'Kondensator'=>array(
'Talon',
'LBS-75'
),
'Arc'=>array(
'LBH-410',
'LBH-800'
)
)
),
'Pinner/bolter'=>array(
'CD-pinner'=>array(
'rustfri'=>array(
'cdss m3x35',
'cdss m3x40'
),
'stål'=>array(
'cdms m3x35',
'cdms m6x35'
),
'Alu'=>array(
'cdal m3x10',
'cdal m8x80'
)
),
'Bossinger'=>array(
'Stål'=>array(
'M6x10 5x8',
'M5x12 4x10'
),
'Alu'=>array(
'M6x10 5x8',
'M5x12 4x10'
),
'Rustfri'=>array(
'M6x10 5x8',
'M5x12 4x10'
)
)
)
);
I have no idea how to do this by looping through the results. is there any way of doing this without making a giant array of doom? if not, can someone assist me in decyphering this conundrum.
Thank you in advance.
BM.
You could let mysql sort the result set:
SELECT name, overcategory, category, subcategory FROM Products ORDER BY overcategory,category,subcategory;
Then you can simply loop over the result. Whenever the overcategory, category, subcategory changes you output a new header.
If you sort each of the columns of your results in your SQL query, you can just loop through each result and compare it with the last entry and adjust your output based on that.
SELECT name, overcategory, category, subcategory FROM Products ORDER BY overcategory, category, subcategory, name;
Otherwise, here is one way of handling your nested array:
<?php
echo "\n";
echo "<nav>\n";
foreach ($testArray as $overcategory_name => $category_data) {
echo "\t<h1>$overcategory_name</h1>\n";
foreach ($category_data as $category_name => $subcategory_data) {
echo "\t\t<h2>$category_name</h2>\n";
foreach ($subcategory_data as $subcategory_name => $product_name_data) {
echo "\t\t\t<h3>$subcategory_name</h3>\n";
foreach ($product_name_data as $product_name) {
echo "\t\t\t\t$product_name\n";
}
}
}
}
echo "</nav>\n";
How about -
$res = mysql_query('SELECT name, overcategory, category, subcategory FROM Products WHERE 1 = 1 ORDER BY overcategory,category,subcategory, name;');
$aMenu = array();
while($row = mysql_fetch_assoc($res)) {
$aMenu[$row['overcategory']][$row['category']][$row['subcategory']][] = $row['name'];
}
A more significant issue to be looking into is your table structure. Assuming that the overcategory, category and subcategory are part of a hierarchy then you should only be storing the leaf node to which the product belongs, and that should probably be stored as an integer that is a FK to a categories(id, name, parent_id) table. I tend to opt for nested sets for product catalogs but it depends on the requirements.
Furthermore, it is common for an individual product to be represented in more than one category, in which case you would need to move the category relationship to a join table products_categories(product_id, category_id).
Just a little food for thought.
I've created a table which approximates to this:
Fruit | Date Purchased | Amount Purchased
----------------------------------------------
Apples | 01-01-10 | 5
Oranges | 01-01-10 | 7
Apples | 02-01-10 | 3
Oranges | 02-01-10 | 2
etc....
I need to end up with the data in the following format though:
Apples (
(01-01-10, 5),
(02-01-10, 3)
)
Oranges (
(01-01-10, 7),
(02-01-10, 2)
)
etc...
The types of fruit are not fixed - more will be added over time, so this would be need to be taken into account.
I've been stuck on this for quite a while now, so any pointers or tips would be really appreciated.
I to lazy to figure out the correct HTML tag to do the tab, but the following code should help you out.
SELECT CONCAT(
s.Fruit, ' (<br/>', '<tab/>',
GROUP_CONCAT(s.DatePlusAmount SEPARATOR ',<br/><tab>'),
'<br/>)<br/>') as FruitLine FROM
(
SELECT Fruit, CONCAT(PDate, ',', IFNULL(sum(amount),0)) AS DatePlusAmount
FROM table1
GROUP BY DATE
) s
GROUP BY Fruit
No loops in php needed.
You can loop through all all your records and add every row to the appropriate array:
Something like:
$fruits = array();
while ($row = get_new_database_row) /* depends on mysql, mysqli, PDO */
{
$fruits[$row['fruit']][] = array($row['date'], $row['amount']);
}
Edit: Based on your codeigniter comments, you either need result_array() or you need to change $row['fruit'] to $row->fruit, $row['date'] to $row->date, etc.
I would do this in two queries:
$sql = "SELECT * FROM tabledata";
$rs = mysql_query($sql);
while( false !== ($r = mysql_fetch_assoc($rs2)))
{
$arr_fruit[ $r['fruit'] ][ $r['date_purchase'] ] = $r['amout'];
}
at this point, you'll end up having associative array that you can further process.
I leave that as an exercise. Come back again when you have problem. But, be sure to bring some code.
I have a table like this:
id | roll_no | name
---------------------
1 | 111 | Naveed
2 | 222 | Adil
3 | 333 | Ali
If I have data like this:
$fields = array( "id" , "roll_no" ) and $values = array( "1,111", "2,222" );
It means I have to write a sql query to get records from table where (id != 1 and roll_no != 111) and (id != 2 and roll_no != 222). It means 3rd record will be fetched.
If I have data like this:
$fields = array( "id" ) and $values = array( "2", "3" );
It means I have to write a sql query to get records from table where (id != 2) and (id != 3). It means 1st record will be fetched.
Q: How to write a general single query using php to get data from table using above two data arrays.
Thanks
select * from dummy where concat_ws (',', id, roll_no) not in ('1,111', '2,222')
Complete solution:
$tableName = "test";
$fields = array( "id" , "roll_no" );
$values = array( "1,111", "2,222" );
$fieldsStr = implode(',', $fields);
$valuesStr = implode("','", $values);
$sql = "SELECT *
FROM $tableName
WHERE concat_ws(',', $fieldsStr ) NOT IN ( '$valuesStr' )";
You will probably always have to explode the Array in PHP and pass the values as a string into the query (sprintf) so you probably can, and should, do all in PHP.
One thing that catches my eye is that you are always using ID's. Are the ID's a unique or primary field? If so just forget about the roll_no as your query will be faster using just ID's.
Complete solution with the help of accepted answer.
$tableName = "test";
$fields = array( "id" , "roll_no" );
$values = array( "1,111", "2,222" );
$fieldsStr = implode(',', $fields);
$valuesStr = implode("','", $values);
// Get all records from remote table
$sql = "SELECT * FROM $tableName WHERE concat_ws(',', $fieldsStr ) NOT IN ( '$valuesStr' )";