Wordpress Shortcode that query some value from MySql - mysql

I've a MySql table where I put some value: id, name of opportunity, category of opportunity, commission etc etc. Now I need to create (automatically) a shortcode that call these value win an array, so for example if i write [opportunity id="1"] wordpress display banner of the opportunity in the database that have id=1.
This is my code
function opportunity_banner_shortcode($atts) {
extract(shortcode_atts(array("id" => ''), $atts));
global $table_prefix, $wpdb, $user_level;
$table_name = $table_prefix . "opportunities";
$finds = $wpdb->get_results("SELECT * FROM {$table_name}", ARRAY_A);
if(sizeof($finds)){
foreach($finds as $find)
return "<a href='" . $find["opp_link"].
"'><img src='" . $find["opp_banner_preview"]."'></a> ";
}
}
add_shortcode('opportunity', 'opportunity_banner_shortcode');
Thanks to all

Maybe the query should be
$finds = $wpdb->get_results("SELECT * FROM {$table_name} WHERE id={$id}",
ARRAY_A);

Related

Unique Profile Slug with PHP and PDO

I am using a class to generate a string name profile to slug and next use an SQL command to tell me whats the unique value to use in insert command, the problem is the command isn't working properly, sometimes it is possible to return a value which already exist...
Thats the class I am using to generate the slug: (composer require channaveer/slug)
And this the example code:
use Channaveer\Slug\Slug;
$string = "john doe";
$slug = Slug::create($string);
$profile_count_stmt = $pdo->prepare("
SELECT
COUNT(`id`) slug_count
FROM
`advogados_e_escritorios`
WHERE
`slug_perfil` LIKE :slug
");
$profile_count_stmt->execute([
":slug" => "%".$slug."%"
]);
$profile_count = $profile_count_stmt->fetchObject();
if ($profile_count && $profile_count->slug_count > 0) {
$profile_increment = $profile_count->slug_count + 1;
$slug = $slug . '-' . $profile_increment;
}
echo 'Your unique slug: '. $slug;
// Your unique slug: john-doe-5
This is the content of the table when the script run:
Do you know how can I improve the select command to prevent it to return existing slugs from DB?
Ok finally found a solution... Heres the code for who wants to generate unique profile slugs using PHP - PDO and MySQL
$string = "John Doe";
$string = mb_strtolower(preg_replace('/\s+/', '-', $string));
$slug = iconv('UTF-8', 'ASCII//TRANSLIT', $string);
$pdo = Conectar();
$sql = "
SELECT slug_perfil
FROM advogados_e_escritorios
WHERE slug_perfil
LIKE '$slug%'
";
$statement = $pdo->prepare($sql);
if($statement->execute())
{
$total_row = $statement->rowCount();
if($total_row > 0)
{
$result = $statement->fetchAll();
foreach($result as $row)
{
$data[] = $row['slug_perfil'];
}
if(in_array($slug, $data))
{
$count = 0;
while( in_array( ($slug . '-' . ++$count ), $data) );
$slug = $slug . '-' . $count;
}
}
}
echo $slug;
//john-doe-1
You should check if the slug exists or not from your database. If it already exists then you can append some random string like the following
$slug = Slug::create($string);
$slugExists = "DB query to check if the slug exists in your database then you may return the count of rows";
//If the count of rows is more than 0, then add some random string
if($slugExists) {
/** NOTE: you can use primary key - id to append after the slug, but that has to be done after you create the user record. This will help you to achieve the concurrency problem as #YourCommenSense was stating. */
$slug = $slug.time(); //time() function will return time in number of seconds
}
//DB query to insert into database
I have followed the same for my blog articles (StackCoder) too. Even LinkedIn follows the same fashion.
Following is screenshot from LinkedIn URL

Using DataTables to a table with content from ajax

I am working on this program. The program displays the topics under a specific subject.
My main question is, will the DataTable work in this kind of setup?
This is the code in HTML.
<div class="table-responsive" id="subject_container">
<table id="tbl_subject" class="table table-striped">
<thead>
<tr>
<th>Chapter</th>
<th>Topic</th>
<th>Content</th>
</tr>
</thead>
<tbody id="disp_topics"></tbody>
</table>
</div>
This is the code snippet in jquery:
$(function(){
//this is only for simplification. Subjectid will be coming from a select input.
let subjectid = 1;
get_topics(subjectid);
//this part right here. If this cannot work, is there a way to make it work?
$('#tbl_subject).DataTable();
});
function get_topics(subjectid){
$.ajax({
url: 'includes/subject_handler.php',
method: 'POST',
data: {
key: 'get_topics',
subjectid: subjectid
},
success: function(data){
$('#disp_topics).html(data);
}
});
This is the code of includes/subject_handler.php:
I am using keys since there are other tasks handled by this same script file. Thank you for understanding.
if($_POST['key'] == 'get_topics'){
$subjectid = $_POST['subjectid'];
$data = '';
if(!empty($subjectid)){
$sql = "SELECT topic.subjectid, chapter, topic, content FROM topic INNER JOIN subject
ON subject.subjectid=topic.subjectid WHERE topic.subjectid = ?";
$stmt=$db->prepare($sql);
$stmt->bindValue(1, $subjectid);
$stmt->execute();
if($stmt->rowCount() > 0){
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($rows as $row){
$data .= '<tr>
<td>'.$row['chapter'].'</td>
<td>'.$row['topic'].'</td>
<td>'.$row['content'].'</td>
</tr>';
}
exit($data);
}
}
}
you can use ajax attribute of data table.
$('#tbl_subject').DataTable( {
processing: true,
serverSide: true,
serverMethod: 'post',
ajax: 'includes/subject_handler.php'
columns: [
{data: 'chapter', name: 'chapter'},
{data: 'topic', name: 'topic'},
{data: 'content', name: 'content'},
]
} );
And for backend if you need to access search value you can do like this,
$requestData = $_REQUEST;
$requestData['search']['value']
In your case this is how to use it in where close.
$sql .= " AND ( chapter LIKE '" . $requestData['search']['value'] . "%' ";
$sql .= " OR topic LIKE '" . $requestData['search']['value'] . "%' ";
$sql .= " OR content LIKE '" . $requestData['search']['value'] . "%' )";
And if you need to get sorting data you can get like this,
$requestData['order'][0]['column'] // column name which user sorts
$requestData['order'][0]['dir'] // derection (ASC/DESC)
In your case it will be like this and remember to use $requestData['start'] and $requestData['length'] for pagination to work.
$sql .= " ORDER BY " . $columns[$requestData['order'][0]['column']] . " " . $requestData['order'][0]['dir'] . " LIMIT " . $requestData['start'] . " ," . $requestData['length'] . " ";
You can include this search value and order values inside your sql query inside backend.
And finally you need format the data before send to front end.
$json_data = array(
"draw" => intval($requestData['draw']), // for every request/draw by clientside , they send a number as a parameter, when they recieve a response/data they first check the draw number, so we are sending same number in draw.
"recordsTotal" => intval($totalData), // total number of records
"recordsFiltered" => intval($totalFiltered), // total number of records after searching, if there is no searching then totalFiltered = totalData
"data" => $data // total data array
);
echo json_encode($json_data);
This is much simpler than looks. Need to get total records count from query, and total filtered record count from another query and dataset in json.
I have added previous sql example only to explain. For preventing SQL injection you have to use Prepared Statements.
$sql .= " AND ( chapter LIKE ? OR topic LIKE ? OR content LIKE ?";
$params = array($requestData['search']['value'] . "%", $requestData['search']['value'] . "%", $requestData['search']['value'] . "%");
$stmt = $handle->prepare($sql);
$stmt->execute($params);
And you need to do the same for ORDER BY and LIMIT part of the query.
and inside this tutorial there is a nice example how it works on backend.
You can send data to back end also like this.
ajax: {
url: "Your url",
data: function (d) {
d.var1= 'var 1';
d.var2= 'var 2';
}
},
And access the data in back end like this.
$var1 = $_REQUEST['var1'];
$var2 = $_REQUEST['var2'];
And be careful not to use start and end (E.g.:- d.start= 'var 1';) to pass data to back end since they are used for pagination. This link has a nice example on this.

Query Builder using the like operator and dynamic values

CakePHP Version 3.5.5
What I've got:
I've got search functionality on my index pages which allows a user to search by column and value. The user selects the column from a select list and adds text into an input. I pick up this data with the following which works:
$query = $Users->find()
->where(function ($exp, $q) {
return $exp->like($this->request->getData('column'), $this->request->getData('input') . '%');
})
->andWhere([
'status' => $filter,
'cid_1' => $c1
]);
When using the debugKit it reveals the sql as: (Extract only to help explain)
FROM users Users WHERE (role LIKE :c0 AND status = :c1 AND cid_1 = :c2)',
What I'm trying to do is the following:
$testColumn = $this->request->getData('column');
$testInput = $this->request->getData('input');
$query = $Users->find()
->where(function ($exp, $q) {
return $exp->like($testColumn, $testInput . '%');
})
->andWhere([
'status' => $filter,
'cid_1' => $c1
]);
The $testColumn variable is undefined.
Whe using the debugKit it reveals the sql as: (Extract only to help explain)
FROM users Users WHERE ( LIKE :c0 AND status = :c1 AND cid_1 = :c2)',
IE: The role is not being declared before the LIKE.
What I've tried:
1. return $exp->like("$testColumn", "$testInput" . '%');
Result: Exactly the same - Variable is still undefined.
DebugKit: FROM users Users WHERE ( LIKE :c0 AND status = :c1 AND cid_1 = :c2)',
2. return $exp->like("'$testColumn'", "'$testInput'" . '%');
Result: It added '' before LIKE as can be seen below but I still can't get that variable defined.
DebugKit: FROM users Users WHERE ('' LIKE :c0 AND status = :c1 AND cid_1 = :c2)',
My Question:
Is there a way to use a dynamic value to select the search data.
Update:
Is it that I can't assign getData to a variable in this context.
You can't do this:
$testColumn = $this->request->getData('column');
return $exp->like($testColumn, $testInput . '%');
But you can do this:
$testColumn = $this->request->getData('column');
echo 'testColumn is ' . $testColumn . '<br />';
if ($testColumn === 'role') {
echo 'in column passed ' . '<br />';
}
else {
echo 'in column failed ' . '<br />';
}
Thanks. Z.
////////////////////////////////////////////////////////////////////////////////
Alimon Karim as requested.
I'm using post and my url is: https://localhost/app/users/search
Thanks Alimon, it works.
Replace
->where(function ($exp, $q) {
with
->where(function ($exp, $q) use ($testColumn,$testInput) {

Can't update/change field values in a database

theoretically I'll show you the code that works, I mean, it makes sense but I can not get no change in the table! : \
so, here is the code:
else if ($mode == 'password') {
$generated_password = substr(md5(rand(999,999999)), 0, 8);
change_password($user_data['user_id'],$generated_password);
update_user($user_data['user_id'], array('password_recover' => '1'));
email($email, 'Your new password', "Hi," . $user_data['nome'] . " \n\nYour new password is: " . $generated_password . "");
}
Functions:
function update_user($user_id,$update_data){
$update = array();
array_walk($update_data, 'array_sanitize');
foreach($update_data as $field => $data) {
$update[]='`' .$field. '`=\'' .$data . '\'';
}
mysql_query("UPDATE users SET " . implode(', ',$update) . "WHERE user_id = '$user_id'");
}
function change_password($user_id,$password) {
$user_id = (int) $user_id;
$password = md5($password);
mysql_query("UPDATE users SET password = '$password' WHERE user_id = $user_id");
}
I have not even written the email function because that works. Thanks in advance! :)
You should add some kind of error handling to your code. At least add or die('Error: '.mysql_error()) after each mysql_query() to at least get some idea of what went wrong when the queries are executed.
And if you just take code from somewhere and don't really understand what it does, don't be surprised, if it doesn't do what you want it to do.

Using mySQL/Wordpress to get data from a metadata column

I am using wordpress metadata to store dynamic data.
I've ran into a wall and need some help,I have once piece of meta data that basically is a multidimensional array.
The issue I have is how the metadata is stored I'm having a hard time retrieving what i need.
At the bottom I have included how wordpress stores the data (it's one column)
This is how the first entry looks like before it's stored
shopper_wp_id:3
shopper_status_time:2011-11-29 17:24:49
shopper_status_comment:COMMENTS
shopper_status:declined
shopper_answers:["TEST1","TEST2","TEST3","TEST4","TEST5","TEST6"]
shopper_preapproval_status:maybe
What i need to be able to do is find all the entries where the shopper_wp_id = 3 and the shopper_status = declined
If those 2 values where next to each other but they are separated by a datetime that is ever changing. Any ideas?
a:4:{i:0;a:6:{s:13:"shopper_wp_id";s:1:"3";s:19:"shopper_status_time";s:19:"2011-11-29 17:24:49";s:22:"shopper_status_comment";s:8:"COMMENTS";s:14:"shopper_status";s:8:"declined";s:15:"shopper_answers";a:6:{i:0;s:5:"TEST1";i:1;s:5:"TEST2";i:2;s:5:"TEST3";i:3;s:5:"TEST4";i:4;s:5:"TEST5";i:5;s:5:"TEST6";}s:26:"shopper_preapproval_status";s:5:"maybe";}i:1;a:7:{s:13:"shopper_wp_id";s:4:"2063";s:19:"shopper_status_time";s:19:"2011-11-30 16:37:52";s:22:"shopper_status_comment";s:17:"sgdfsgfgdfdfgfhsh";s:14:"shopper_status";s:4:"paid";s:15:"shopper_answers";a:6:{i:0;s:10:"sdfsadfdfs";i:1;s:11:"dfgdsfgsdfg";i:2;s:10:"sdfgfdsfdg";i:3;s:9:"dgsdfgdfg";i:4;s:10:"sgdfsgfdgd";i:5;s:10:"sdfgfgfgds";}s:26:"shopper_preapproval_status";s:3:"yes";s:13:"blog_post_url";s:17:"http://google.com";}i:2;a:6:{s:13:"shopper_wp_id";s:4:"2916";s:19:"shopper_status_time";s:19:"2011-11-29 20:13:13";s:22:"shopper_status_comment";s:7:"dfbdfdf";s:14:"shopper_status";s:8:"declined";s:15:"shopper_answers";a:6:{i:0;s:15:"cvczxvzxcvzxcbz";i:1;s:11:"zcvfxzbxbxb";i:2;s:8:"zvzxcbzb";i:3;s:10:"zfdbfdbdfb";i:4;s:11:"zdfbdfbfbdf";i:5;s:6:"bfdfdh";}s:26:"shopper_preapproval_status";s:2:"no";}i:3;a:6:{s:13:"shopper_wp_id";s:4:"1614";s:19:"shopper_status_time";s:19:"2011-11-29 20:16:06";s:22:"shopper_status_comment";s:15:"sfdhfsdhsdfhdsh";s:14:"shopper_status";s:8:"declined";s:15:"shopper_answers";a:6:{i:0;s:8:"sdfsdfsd";i:1;s:15:"zvzfbdfbsdfbdbd";i:2;s:15:"dfgdsfhsfdsfhdf";i:3;s:17:"xfbfghfghnfsgnfgn";i:4;s:17:"dsfgshfdshsfdghsg";i:5;s:12:"sdffsdhsdfhh";}s:26:"shopper_preapproval_status";s:2:"no";}}
The string is serialized, so you need to unserialize it, then you can more easily get the information you need using the resulting structure (in this case, an associative array). For example
$data = 'a:4:{i:0;a:6:{s:13:"shopper_wp_id";s:1:"3";s:19:"shopper_status_time";s:19:"2011-11-29 17:24:49";s:22:"shopper_status_comment";s:8:"COMMENTS";s:14:"shopper_status";s:8:"declined";s:15:"shopper_answers";a:6:{i:0;s:5:"TEST1";i:1;s:5:"TEST2";i:2;s:5:"TEST3";i:3;s:5:"TEST4";i:4;s:5:"TEST5";i:5;s:5:"TEST6";}s:26:"shopper_preapproval_status";s:5:"maybe";}i:1;a:7:{s:13:"shopper_wp_id";s:4:"2063";s:19:"shopper_status_time";s:19:"2011-11-30 16:37:52";s:22:"shopper_status_comment";s:17:"sgdfsgfgdfdfgfhsh";s:14:"shopper_status";s:4:"paid";s:15:"shopper_answers";a:6:{i:0;s:10:"sdfsadfdfs";i:1;s:11:"dfgdsfgsdfg";i:2;s:10:"sdfgfdsfdg";i:3;s:9:"dgsdfgdfg";i:4;s:10:"sgdfsgfdgd";i:5;s:10:"sdfgfgfgds";}s:26:"shopper_preapproval_status";s:3:"yes";s:13:"blog_post_url";s:17:"http://google.com";}i:2;a:6:{s:13:"shopper_wp_id";s:4:"2916";s:19:"shopper_status_time";s:19:"2011-11-29 20:13:13";s:22:"shopper_status_comment";s:7:"dfbdfdf";s:14:"shopper_status";s:8:"declined";s:15:"shopper_answers";a:6:{i:0;s:15:"cvczxvzxcvzxcbz";i:1;s:11:"zcvfxzbxbxb";i:2;s:8:"zvzxcbzb";i:3;s:10:"zfdbfdbdfb";i:4;s:11:"zdfbdfbfbdf";i:5;s:6:"bfdfdh";}s:26:"shopper_preapproval_status";s:2:"no";}i:3;a:6:{s:13:"shopper_wp_id";s:4:"1614";s:19:"shopper_status_time";s:19:"2011-11-29 20:16:06";s:22:"shopper_status_comment";s:15:"sfdhfsdhsdfhdsh";s:14:"shopper_status";s:8:"declined";s:15:"shopper_answers";a:6:{i:0;s:8:"sdfsdfsd";i:1;s:15:"zvzfbdfbsdfbdbd";i:2;s:15:"dfgdsfhsfdsfhdf";i:3;s:17:"xfbfghfghnfsgnfgn";i:4;s:17:"dsfgshfdshsfdghsg";i:5;s:12:"sdffsdhsdfhh";}s:26:"shopper_preapproval_status";s:2:"no";}}';
$data = unserialize($data);
foreach ($data as $shopper){
if(isset($shopper['shopper_wp_id']) && $shopper['shopper_wp_id'] == 3){
//do something
}
}
Thanks everyone but i figured it out, not sure it's the best but it seems to be pretty quick..
I ended up using a combination of mySQL's LOCATE and SUBSTRING with a HAVING kicker.
Below is my function and then below that is the SQL that it creates.
function db_get_users_shops_by_shopper_status($shopper_wp_id, $limit = 0, $shopper_status) {
global $wpdb;
if (!is_array($shopper_status)) {
$shopper_status = array($shopper_status);
}
$sql = "
SELECT wp_posts . *,
SUBSTRING(meta_value,
LOCATE('{s:13:\"shopper_wp_id\";s:" . strlen($shopper_wp_id) . ":\"" . $shopper_wp_id . "\";', meta_value),
LOCATE('s:15:\"shopper_answers\";', meta_value))
AS shopper_entity
FROM wp_posts, wp_postmeta
WHERE post_type='shoppertunity'
AND wp_posts.ID = wp_postmeta.post_id AND meta_key = 'shoppers'
AND meta_value LIKE '%s:13:\"shopper_wp_id\";s:" . strlen($shopper_wp_id) . ":\"" . $shopper_wp_id . "\";%'
HAVING shopper_entity LIKE ";
for ($i = 0; $i < sizeof($shopper_status); ++$i) {
if ($i > 0) {
$sql .= " OR shopper_entity LIKE ";
}
$sql .= " '%s:14:\"shopper_status\";s:" . strlen($shopper_status[$i]) . ":\"" . $shopper_status[$i] . "\";%'";
}
if ($limit != 0) {
$sql .= "LIMIT " . $limit;
}
//echo($sql ."<br/><br/>");
$results = $wpdb -> get_results($sql);
return $results;
}
SQL Results
SELECT
`wp_posts`.*,
SUBSTRING(`meta_value`,
LOCATE('{s:13:"shopper_wp_id";s:4:"2063";',
`meta_value`),
LOCATE('s:15:"shopper_answers";', `meta_value`)) AS `shopper_entity`
FROM
wp_posts,
wp_postmeta
WHERE
post_type = 'shoppertunity' AND wp_posts.ID = wp_postmeta.post_id AND meta_key = 'shoppers' AND meta_value LIKE '%s:13:"shopper_wp_id";s:1:"3";%'
HAVING shopper_entity LIKE '%s:14:"shopper_status";s:9:"completed";%' OR shopper_entity LIKE '%s:14:"shopper_status";s:4:"paid";%'