How to change the search action in wordpress search bar? - mysql

Create a new post and publish it.
The title is my test for search, content in it is as below:
no host route
Check what happen in wordpress database.
select post_title from wp_posts
where post_content like "%no%"
and post_content like "%route%"
and post_content like "%to%"
and post_content like "%host%";
The post named my test for search will not be in the select's result.
Type no route to host in wordpress search bar,and click enter.
The post named my test for search shown as result.
I found the reason that the webpage contain to ,in the left upper side corner ,there is a word Customize which contains the searched word to.
How to change such search action in wordpress serach bar?
I want to make the search behavior in wordpress saerch bar, for example ,when you type no route to host, equal to the following sql command.
select post_title from wp_posts where post_content like "%no%route%to%host%";
All the plugins in my wordpress.
CodePen Embedded Pens Shortcode
Crayon Syntax Highlighter
Disable Google Fonts
Quotmarks Replacer
SyntaxHighlighter Evolved

There's this addition to the SQL WHERE clause on wp-includes/class-wp-query.php:1306:
<?php
// wp-includes/class-wp-query.php:~1306
foreach ( $q['search_terms'] as $term ) {
//...
$like = $n . $wpdb->esc_like( $term ) . $n;
$search .= $wpdb->prepare( "{$searchand}(({$wpdb->posts}.post_title $like_op %s) $andor_op ({$wpdb->posts}.post_excerpt $like_op %s) $andor_op ({$wpdb->posts}.post_content $like_op %s))", $like, $like, $like );
// ...
Therefore, I'd hook into the pre_get_posts, and supply the words of the query as explicit "search_terms", since they get added into that clause, with the LIKE modifier just as you said were looking for!
So, we might do something like this:
<?php
// functions.php
function fuzzify_query(\WP_Query $q) {
if (true === $q->is_search()
&& true === property_exists($q, 'query')
&& true === key_exists('s', $q->query)
) {
$original_query = $q->query['s'];
$words = explode(' ', $original_query);
$fuzzy_words = array_map(
function($word) {
return '%'.$word.'%';
},
$words
);
$q->query_vars['search_terms'] = $fuzzy_words;
return $q;
}
return $q;
}
add_action('pre_get_posts', 'fuzzify_query', 100); // Or whatever priority your fuzziness requires!

Related

MySQL - Using LIKE ? With Multiple Columns Search

I've had a look around Stackoverflow and can't seem to find what I am looking for.
I have a dynamically updating AJAX search form which shows location data from database.
The issue I am having is with this query here:
$sql = "SELECT location FROM location_data WHERE location LIKE ? LIMIT 10";
Let me explain what is happening first. There are 3 different columns in a database table, one called location, one called CRS and one called tiploc.
I would like to display results like the following:
Select location FROM location_data WHERE location(textbox) is LIKE ?(what the person typed in) OR CRS is LIKE ? or TIPLOC is LIKE ?
Now i've only tried it with CRS so far, and ive done the following query:
$sql = "SELECT location FROM location_data WHERE location OR CRS LIKE ? LIMIT 10";
The above only displays the CRS result (exact match) and doesn't provide any suggestions for location, only shows CRS. Does anyone know how I can amend my query, so that it searches both location and CRS and TIPLOC, LIKE on location, but exact match only on CRS and TIPLOC?
if(isset($_REQUEST['term'])){
// Prepare a select statement
$sql = "SELECT location FROM location_data WHERE location LIKE ? LIMIT 10";
if($stmt = mysqli_prepare($link, $sql)){
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "s", $param_term);
// Set parameters
$param_term = $_REQUEST['term'] . '%';
// Attempt to execute the prepared statement
if(mysqli_stmt_execute($stmt)){
$result = mysqli_stmt_get_result($stmt);
// Check number of rows in the result set
if(mysqli_num_rows($result) > 0){
// Fetch result rows as an associative array
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)){
echo "<p>" . $row["location"] . "</p>";
}
} else{
echo "<p>No matches found</p>";
}
} else{
echo "ERROR: Could not able to execute $sql. " . mysqli_error($link);
}
}
// Close statement
mysqli_stmt_close($stmt);
}
// close connection
mysqli_close($link);
Now heres the on page search, the field I am pulling input from is called "location".
--Code for JS AJAX Search--
<script type="text/javascript">
$(document).ready(function(){
$('.search-box input[type="text"]').on("keyup input", function(){
/* Get input value on change */
$(".result").show();
var inputVal = $(this).val();
var resultDropdown = $(this).siblings(".result");
if(inputVal.length >2){
$.get("backend-search.php", {term: inputVal}).done(function(data){
// Display the returned data in browser
resultDropdown.html(data);
});
} else{
resultDropdown.empty();
}
});
// Set search input value on click of result item
$(document).on("click", ".result p", function(){
$(this).parents(".search-box").find('input[type="text"]').val($(this).text());
$(this).parent(".result").empty();
});
});
$(document).click(function(){
$(".result").hide();
});
</script>
You need to repeat the LIKE expression for each column.
$sql = "SELECT location
FROM location_data
WHERE location LIKE ? OR CRS LIKE ? OR TIPLOC LIKE ?
LIMIT 10";
And since there are now 3 placeholders in the query, you need to fill them all in with the binding:
mysqli_stmt_bind_param($stmt, "sss", $param_term, $param_term, $param_term);
For every individual expression in OR, you have to specify their comparison conditions. Note the location LIKE ? instead of LOCATION OR:
$sql = "SELECT location
FROM location_data
WHERE location LIKE ?
OR CRS LIKE ?
OR TIPLOC LIKE ?
LIMIT 10";
Note: LIMIT clause without ORDER BY is non-deterministic in nature, since MySQL stores an unordered dataset. It basically means that, any 10 rows can be returned by MySQL (if not using ORDER BY).

Query two combined fields with one value

I have a table name 'user' for example. I have field 'name' and field 'family' in this table.
I use jQueryUI auto-complete for top search in my site for search people just like Facebook.
Example of jQueryUI I use (half code):
$( "#mainsearch" ).bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "ui-autocomplete" ).menu.active ) {
event.preventDefault();
}
})
And I have PHP files get search result code like this:
$name = $_GET['term'];
$results = array();
$s = qselectall("select * from user where(name LIKE '%$name%' or family LIKE '%$name%' ) limit 15",$db);
while($f = mysqli_fetch_array($s,MYSQLI_ASSOC)){
if($userid != $f['id']){
$name = $f['name'].' '.$f['family'];
$url = $siteurl.$f['username'].'/';
array_push($results, array('id' => $f['id'],'value' => $name,'url' => $url));
}
}
echo json_encode($results);
But it has 1 problem.
User's cannot search with name and family.
They must insert name OR family just in input box for it to work.
Is there any SQL code for search LIKE where( name and family = $text) ?
EXAMPLE:
We have someone with name 'alex' and with last name 'alexian'.
So user search for 'alex alexian' but they get no results why?
Because not name and not family in table = 'alex alexian'.
So they must search 'alex' or 'alexian' for it to work.
Try this:
SELECT * FROM user
WHERE concat_ws(' ',name,family)
LIKE '%$name%';
The concat_ws function concatenates multiple columns 'with separator' (_ws). In this case, the separator is a space (' '). See the MySQL documentation for further information.
Demo: http://www.sqlfiddle.com/#!2/aac0f/8

Trim long html for preview without breaking html tags

I was put in front of this problem when working on a blog post preview list.
They need to shorten the content but not break any html tags by leaving them open.
I have heard that reg ex is not a good option. I am looking for something simple and working.
I appreciate your help in advance as always (SO ended up being a very nice place to come over with problems like that :-)
Wordpress has a function for generating excerpts built-in to the blogging platform which generates an excerpt from the actual blog post.
You didn't specify which language you were looking to use for the trim function so here is the Wordpress version. It can be easily modified and re-purposed to use outside of Wordpress if need be.
wp_trim_words() function reference
/**
* Generates an excerpt from the content, if needed.
*
* The excerpt word amount will be 55 words and if the amount is greater than
* that, then the string ' […]' will be appended to the excerpt. If the string
* is less than 55 words, then the content will be returned as is.
*
* The 55 word limit can be modified by plugins/themes using the excerpt_length filter
* The ' […]' string can be modified by plugins/themes using the excerpt_more filter
*
* #since 1.5.0
*
* #param string $text Optional. The excerpt. If set to empty, an excerpt is generated.
* #return string The excerpt.
*/
function wp_trim_excerpt($text = '') {
$raw_excerpt = $text;
if ( '' == $text ) {
$text = get_the_content('');
$text = strip_shortcodes( $text );
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
$excerpt_length = apply_filters('excerpt_length', 55);
$excerpt_more = apply_filters('excerpt_more', ' ' . '[…]');
$text = wp_trim_words( $text, $excerpt_length, $excerpt_more );
}
return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}

MediaWiki: changing the label of a category at the bottom of the page

In mediawiki, is it possible to change the label of a 'Category' at the bottom of an article.
For example for the following article:
=Paris=
blablablablablabla
[[Category:place_id]]
I'd like to see something more verbose like (the example below doesn't work):
=Paris=
blablablablablabla
[[Category:place_id|France]]
Note: I don't want to use a 'redirect' and I want to keep my strange ids because they are linked to an external database.
I do not think mediawiki is supporting this feature.
However, how about using:
[[Category:France]]
in your page, and set it into the category named with your id? France would just be a subcategory of "place_id", and you could use more terms all linked to the parent category. For this, you just need to edit the category page for "France", inserting:
[[Category:place_id]]
An alternative would be to put your page in both categories, but in this case, the id would still be displayed:
[[Category:place_id]]
[[Category:France]]
You could do this with an OutputPageMakeCategoryLinks hook. Alas, the interface for that hook seems to be a bit inconvenient — as far as I can tell, it's pretty much only good for replacing the standard category link generation code entirely. Still, you could do that is you want:
function myOutputPageMakeCategoryLinks( &$out, $categories, &$links ) {
foreach ( $categories as $category => $type ) {
$title = Title::makeTitleSafe( NS_CATEGORY, $category );
$text = $title->getText();
if ( $text == 'Place id' ) {
// set $text to something else
}
$links[$type][] = Linker::link( $title, htmlspecialchars( $text ) );
}
return false; // skip default link generation
}
$wgHooks['OutputPageMakeCategoryLinks'][] = 'myOutputPageMakeCategoryLinks';
(The code above is based on the default category link generation code in OutputPage.php, somewhat simplified; I assume you're not using language variant conversion on your wiki, so I removed the parts that deal with that. Note that this code is untested! Use at your own risk.)

MySQL question: Appending text to a wordpress post, but only if it's in a certain category

I need to amend (via CONCAT, presumably) something to every wordpress post if it belongs to a certain category (say, category ID 7), but I'm struggling to get it to work.
To test, I'm first trying to select all the relevant posts. So far, I have the following:
SELECT post_title
FROM cruise_wp_posts
LEFT JOIN cruise_wp_term_relationships
ON cruise_wp_term_relationships.object_id = cruise_wp_posts.ID
WHERE term_taxonomy_id = 87;
However, it only lists posts that are only in category 87 - I need all posts that are in category 87 (and possibly other categories too)
I'm a MySQL newbie, and this is really breaking my brain.
Any pointers would be passionately welcomed.
The best way to do it is to filter it in as needed. This way the addition is made everywhere the_content is used and not just in the templates you modify.
<?php
function my_content_concat($the_content) {
if (in_category(7)) {
$the_content .= '<br /><br />foo!';
}
return $the_content;
}
add_filter('the_content', 'my_content_concat', 9);
?>
in_category can take the id, name or slug of your target category.
I put the filter at 9 so that it runs before WordPress texturizes the content. If you don't need that run it at 11.
Why not just use get_the_category( $id ) and ammend the text when you output the post?
$cat = get_the_category( $postID );
if ($cat == 7) {
//Add text here
}