Создаем кастомный тип записи (Custom Post Type) Articles с кастомными категориями (Custom Taxonomy) Articles Category .

В моем случае все стандартные записи – это Товары, поэтому Статьи выведем через кастомные записи.

В файле функций functions.php регистрируем кастомный тип записи Articles:

Function wptp_create_post_type() { $labels = array("name" => __("Articles"), "singular_name" => __("Articles"), "add_new" => __("New Article"), "add_new_item" => __("Add New Article"), "edit_item" => __("Edit Article"), "new_item" => __("New Article"), "view_item" => __("View Article"), "search_items" => __("Search Articles"), "not_found" => __("No Articles Found"), "not_found_in_trash" => __("No Articles found in Trash"),); $args = array("labels" => $labels, "has_archive" => true, "public" => true, "hierarchical" => false, "menu_position" => 5, "supports" => array("title", "editor", "excerpt", "custom-fields", "thumbnail"),); register_post_type("articles", $args); } add_action("init", "wptp_create_post_type");

Если вы хотите, чтобы в кастомных постах выводились стандартные категории, тогда привяжите их к таксономии Категорий:

"taxonomies" => array("category"),

Если для кастомных постов вы создаете еще и кастомные таксономии, то связывать их надо с созданными таксономиями, если брать пример ниже, то это будут articles_category

"taxonomies" => array("articles_category"),

Затем для кастомного типа записи Articles регистрируем таксономии ‘Article Category’, чтобы разные записи могли принадлежать разным категориям.

Function wptp_register_taxonomy() { register_taxonomy("articles_category", "articles", array("labels" => array("name" => "Article Categories", "singular_name" => "Article Category", "search_items" => "Search Article Categories", "all_items" => "All Article Categories", "edit_item" => "Edit Article Categories", "update_item" => "Update Article Category", "add_new_item" => "Add New Article Category", "new_item_name" => "New Article Category Name", "menu_name" => "Article Category",), "hierarchical" => true, "sort" => true, "args" => array("orderby" => "term_order"), "show_admin_column" => true)); } add_action("init", "wptp_register_taxonomy");

Для кастомной таксономии можно изменить слаг на более красивый, чтобы он не был articles_category , но нужно учесть, чтобы таких слдагов больше не было на других страницах или постах, иначе будут проблемы:

"rewrite" => array("slug" => "blog"),

При изменении слагов необходимо обновить настройки “Постоянных ссылок” в админке, иначе будете получать 404 ошибку вместо нужной страницы.

Больше примеров можно найти и . Но привести весь этот код в порядок помогла , за что автору большая благодарность.

За внешний вид кастомной записи отвечает файл single.php , но чтобы изменить вид кастомной записи можно создать файл single-{post_type}.php – в моем случае будет single-articles.php со своим содержимым.

Теперь нужно вывести кастомные записи на странице. По умолчанию за отображение архива кастомных записей отвечает файл index.php . Но можно создать файл, который будет отвечать за вывод кастомных записей в своей таксономии.

Вариант 1 – самый правильный. Выводим записи в таксономии так же как и в обычной категории.

Для этого создаем файл taxonomy-{taxonomy}.php – в моем случае будет taxonomy-articles_category.php и в нем выводим обычный цикл, как и для стандартных записей в категории:

В файле tax-item.php выводим данные, которые нам нужно получить из каждой записи, например, заголовок, ссылку на запись, миниатюру и excerpt.

В файле pagination.php выводим пагинацию вот такого формата .

Цикл не изменяем, пагинация отлично работает. Это самый оптимальный вариант для отображения Кастомных Таксономий.

Вариант 2 – если нет кастомных таксономий, то можно просто получить все кастомные записи в виде Архива

Для этого в шаблоне создаем файл archive-{post_type}.php – в моем случае будет archive-articles.php , в котором точно так же как и в таксономии выводим обычный цикл, только вместо заголовка Таксономии выводим имя кастомного типа записи :

При этом варианте, если не создана страница архива для кастомной записи, тогда получить список всех кастомных записей можно по прямой ссылке BLOG_URL?post_type={post_type} или в моем случае http://site.com/articles/ .

Вариант 3. Просто выводим все кастомные записи Articles на странице с заданным шаблоном

get_template_part("include/tax-item"); – в файле tax-item.php я вывожу содержимое записи, которое нужно мне для отображения записей внутри цикла (заголовок, миниатюру, дату, цитату и т.д.)

Этот вариант выводит все записи Articles на странице, не зависимо от таксономий (категорий).

А если нам нужно вывести каждую категорию отдельно со своими новостями, тогда используем первый вариант, описанный выше.

При этом, если вы используете плагин Yoast SEO и используете его хлебные крошки:

Тогда при выборе в настройках плагина таксономии “Articles Category” в “Taxonomy to show in breadcrumbs for post types”, в хлебных крошках вы получите ссылку на категорию, к которой принадлежит Новость, при других вариантах вывода кастомных записей это не получалось сделать.

Лучший способ удержать пользователя на сайте, это позволить ему найти, то что он ищет. Если вы делаете для этого удобную систему, то уровень предпочтения вашего сайта будет расти и пользователь обязательно вернётся для того, чтобы найти то, что его интересует.

Я вам покажу как создать простую, но эффективную по функционалу, поисковую форму, которая будет использоваться для поиска статей на сайте. Результаты будут появляться на странице без никаких перезагрузок, что несомненно является лучшим способом подачи информации.

Я создам 2 файла: search.php, который будет содержать HTML и JavaScript. Второй файл, do_search.php будет содержать PHP код. Приступим к созданию первого файла:

PHP, jQuery search demo $(function() { $(".search_button").click(function() { // получаем то, что написал пользователь var searchString = $("#search_box").val(); // формируем строку запроса var data = "search="+ searchString; // если searchString не пустая if(searchString) { // делаем ajax запрос $.ajax({ type: "POST", url: "do_search.php", data: data, beforeSend: function(html) { // запустится до вызова запроса $("#results").html(""); $("#searchresults").show(); $(".word").html(searchString); }, success: function(html){ // запустится после получения результатов $("#results").show(); $("#results").append(html); } }); } return false; }); }); Попробуйте ввести слово ajax
Результаты для

В этом файле мы создали обычную HTML форму, которая посылает POST запрос в бэк энд - файлу do_search.php.

PHP код содержит комментарии, по которым вы с лёгкостью сможете понять работу скрипта. Если в базе данных нашлись совпадения, вы показываете их вашему пользователю, выделяя жирным те слова, которые искал пользователь.

Придадим всему этому немного CSS:

Body{ font-family:Arial, Helvetica, sans-serif; } *{ margin:0;padding:0; } #container { margin: 0 auto; width: 600px; } a { color:#DF3D82; text-decoration:none } a:hover { color:#DF3D82; text-decoration:underline; } ul.update { list-style:none;font-size:1.1em; margin-top:10px } ul.update li{ height:30px; border-bottom:#dedede solid 1px; text-align:left;} ul.update li:first-child{ border-top:#dedede solid 1px; height:30px; text-align:left; } #flash { margin-top:20px; text-align:left; } #searchresults { text-align:left; margin-top:20px; display:none; font-family:Arial, Helvetica, sans-serif; font-size:16px; color:#000; } .word { font-weight:bold; color:#000000; } #search_box { padding:4px; border:solid 1px #666666; width:300px; height:30px; font-size:18px;-moz-border-radius: 6px;-webkit-border-radius: 6px; } .search_button { border:#000000 solid 1px; padding: 6px; color:#000; font-weight:bold; font-size:16px;-moz-border-radius: 6px;-webkit-border-radius: 6px; } .found { font-weight: bold; font-style: italic; color: #ff0000; } h2 { margin-right: 70px; }

Вот вы и научились создавать простейшую поисковую форму, которая работает без перезагрузки страницы. Надеюсь, урок вам понравился.

By Ibrahim Diallo

Published Jul 2 2014 ~ 16 minutes read

Search is an important feature on a website. When my few readers want to look for a particular passage on my blog, they use the search box. It used to be powered by Google Search, but I have since then changed it to my own home-brewed version not because I can do better but because it was an interesting challenge.

If you are in a hurry and just want your site to be searchable, well do what I did before, use Google.

// In search.php file $term = isset($_GET["query"])?$_GET["query"]: ""; $term = urlencode($term); $website = urlencode("www.yourwebsite.com"); $redirect = "https://www.google.com/search?q=site%3A{$website}+{$term}"; header("Location: $redirect"); exit;

What it does is pretty simple. Get the term passed by the user, and forward it to Google search page. Limit the search result to our current domain using the site: keyword in the search query. All your pages that are indexed by Google will be available through search now. If you do want to handle your search in house however, then keep reading.

Homemade Search Solution

Before we go any further, try using the search box on this blog. It uses the same process that I will describe below. If you feel that this is what you want then please continue reading.

This solution is catered to small websites. I make use of LIKE with wild cards on both ends, meaning your search cannot be indexed. This means the solution will work fine for your blog or personal website that doesn"t contain tons of data. Port it to a bigger website and it might become very slow. MySQL offers Full Text Search which is not what we are doing here.

Note: If you have 5000 blog posts you are still fine. .

We will take the structure of this blog as a reference. Each blog post has:

  • A title p_title
  • A url p_url
  • A summary p_summary
  • A post content p_content
  • And catergories category.tagname

For every field that matches with our search term, we will give it a score. The score will be based on the importance of the match:

// the exact term matches is found in the title $scoreFullTitle = 6; // match the title in part $scoreTitleKeyword = 5; // the exact term matches is found in the summary $scoreFullSummary = 5; // match the summary in part $scoreSummaryKeyword = 4; // the exact term matches is found in the content $scoreFullDocument = 4; // match the document in part $scoreDocumentKeyword = 3; // matches a category $scoreCategoryKeyword = 2; // matches the url $scoreUrlKeyword = 1;

Before we get started, there are a few words that do not contribute much to a search that should be removed. Example "in","it","a","the","of" ... . We will filter those out and feel free to add any word you think is irrelevant. Another thing is, we want to limit the length of our query. We don"t want a user to write a novel in the search field and crash our MySQL server.

// Remove unnecessary words from the search term and return them as an array function filterSearchKeys($query){ $query = trim(preg_replace("/(\s+)+/", " ", $query)); $words = array(); // expand this list with your words. $list = array("in","it","a","the","of","or","I","you","he","me","us","they","she","to","but","that","this","those","then"); $c = 0; foreach(explode(" ", $query) as $key){ if (in_array($key, $list)){ continue; } $words = $key; if ($c >= 15){ break; } $c++; } return $words; } // limit words number of characters function limitChars($query, $limit = 200){ return substr($query, 0,$limit); }

Our helper functions can now limit character count and filter useless words. The way we will implement our algorithm is by giving a score every time we find a match. We will match words using the if statement and accumulate points as we match more words. At the end we can use that score to sort our results

Note: I will not be showing how to connect to MySQL database. If you are having problems to efficiently connect to the database I recommend reading this .

Let"s give our function a structure first. Note I left placeholders so we can implement sections separately.

Function search($query){ $query = trim($query); if (mb_strlen($query)===0){ // no need for empty search right? return false; } $query = limitChars($query); // Weighing scores $scoreFullTitle = 6; $scoreTitleKeyword = 5; $scoreFullSummary = 5; $scoreSummaryKeyword = 4; $scoreFullDocument = 4; $scoreDocumentKeyword = 3; $scoreCategoryKeyword = 2; $scoreUrlKeyword = 1; $keywords = filterSearchKeys($query); $escQuery = DB::escape($query); // see note above to get db object $titleSQL = array(); $sumSQL = array(); $docSQL = array(); $categorySQL = array(); $urlSQL = array(); /** Matching full occurrences PLACE HOLDER **/ /** Matching Keywords PLACE HOLDER **/ $sql = "SELECT p.p_id,p.p_title,p.p_date_published,p.p_url, p.p_summary,p.p_content,p.thumbnail, ((-- Title score ".implode(" + ", $titleSQL).")+ (-- Summary ".implode(" + ", $sumSQL).")+ (-- document ".implode(" + ", $docSQL).")+ (-- tag/category ".implode(" + ", $categorySQL).")+ (-- url ".implode(" + ", $urlSQL).")) as relevance FROM post p WHERE p.status = "published" HAVING relevance >

In the query, all scores will be summed up as the relevance variable and we can use it to sort the results.

Matching full occurrences

We make sure we have some keywords first then add our query.

If (count($keywords) > 1){ $titleSQL = "if (p_title LIKE "%".$escQuery."%",{$scoreFullTitle},0)"; $sumSQL = "if (p_summary LIKE "%".$escQuery."%",{$scoreFullSummary},0)"; $docSQL = "if (p_content LIKE "%".$escQuery."%",{$scoreFullDocument},0)"; }

Those are the matches with higher score. If the search term matches an article that contains these, they will have higher chances of appearing on top.

Matching keywords occurrences

We loop through all keywords and check if they match any of the fields. For the category match, I used a sub-query since a post can have multiple categories.

Foreach($keywords as $key){ $titleSQL = "if (p_title LIKE "%".DB::escape($key)."%",{$scoreTitleKeyword},0)"; $sumSQL = "if (p_summary LIKE "%".DB::escape($key)."%",{$scoreSummaryKeyword},0)"; $docSQL = "if (p_content LIKE "%".DB::escape($key)."%",{$scoreDocumentKeyword},0)"; $urlSQL = "if (p_url LIKE "%".DB::escape($key)."%",{$scoreUrlKeyword},0)"; $categorySQL = "if ((SELECT count(category.tag_id) FROM category JOIN post_category ON post_category.tag_id = category.tag_id WHERE post_category.post_id = p.post_id AND category.name = "".DB::escape($key)."") > 0,{$scoreCategoryKeyword},0)"; }

Also as pointed by a commenter below, we have to make sure that the these variables are not empty arrays or the query will fail.

// Just incase it"s empty, add 0 if (empty($titleSQL)){ $titleSQL = 0; } if (empty($sumSQL)){ $sumSQL = 0; } if (empty($docSQL)){ $docSQL = 0; } if (empty($urlSQL)){ $urlSQL = 0; } if (empty($tagSQL)){ $tagSQL = 0; }

At the end the queries are all concatenated and added together to determine the relevance of the post to the search term.

// Remove unnecessary words from the search term and return them as an array function filterSearchKeys($query){ $query = trim(preg_replace("/(\s+)+/", " ", $query)); $words = array(); // expand this list with your words. $list = array("in","it","a","the","of","or","I","you","he","me","us","they","she","to","but","that","this","those","then"); $c = 0; foreach(explode(" ", $query) as $key){ if (in_array($key, $list)){ continue; } $words = $key; if ($c >= 15){ break; } $c++; } return $words; } // limit words number of characters function limitChars($query, $limit = 200){ return substr($query, 0,$limit); } function search($query){ $query = trim($query); if (mb_strlen($query)===0){ // no need for empty search right? return false; } $query = limitChars($query); // Weighing scores $scoreFullTitle = 6; $scoreTitleKeyword = 5; $scoreFullSummary = 5; $scoreSummaryKeyword = 4; $scoreFullDocument = 4; $scoreDocumentKeyword = 3; $scoreCategoryKeyword = 2; $scoreUrlKeyword = 1; $keywords = filterSearchKeys($query); $escQuery = DB::escape($query); // see note above to get db object $titleSQL = array(); $sumSQL = array(); $docSQL = array(); $categorySQL = array(); $urlSQL = array(); /** Matching full occurences **/ if (count($keywords) > 1){ $titleSQL = "if (p_title LIKE "%".$escQuery."%",{$scoreFullTitle},0)"; $sumSQL = "if (p_summary LIKE "%".$escQuery."%",{$scoreFullSummary},0)"; $docSQL = "if (p_content LIKE "%".$escQuery."%",{$scoreFullDocument},0)"; } /** Matching Keywords **/ foreach($keywords as $key){ $titleSQL = "if (p_title LIKE "%".DB::escape($key)."%",{$scoreTitleKeyword},0)"; $sumSQL = "if (p_summary LIKE "%".DB::escape($key)."%",{$scoreSummaryKeyword},0)"; $docSQL = "if (p_content LIKE "%".DB::escape($key)."%",{$scoreDocumentKeyword},0)"; $urlSQL = "if (p_url LIKE "%".DB::escape($key)."%",{$scoreUrlKeyword},0)"; $categorySQL = "if ((SELECT count(category.tag_id) FROM category JOIN post_category ON post_category.tag_id = category.tag_id WHERE post_category.post_id = p.post_id AND category.name = "".DB::escape($key)."") > 0,{$scoreCategoryKeyword},0)"; } // Just incase it"s empty, add 0 if (empty($titleSQL)){ $titleSQL = 0; } if (empty($sumSQL)){ $sumSQL = 0; } if (empty($docSQL)){ $docSQL = 0; } if (empty($urlSQL)){ $urlSQL = 0; } if (empty($tagSQL)){ $tagSQL = 0; } $sql = "SELECT p.p_id,p.p_title,p.p_date_published,p.p_url, p.p_summary,p.p_content,p.thumbnail, ((-- Title score ".implode(" + ", $titleSQL).")+ (-- Summary ".implode(" + ", $sumSQL).")+ (-- document ".implode(" + ", $docSQL).")+ (-- tag/category ".implode(" + ", $categorySQL).")+ (-- url ".implode(" + ", $urlSQL).")) as relevance FROM post p WHERE p.status = "published" HAVING relevance > 0 ORDER BY relevance DESC,p.page_views DESC LIMIT 25"; $results = DB::query($sql); if (!$results){ return false; } return $results; }

Now your search.php file can look like this:

$term = isset($_GET["query"])?$_GET["query"]: ""; $search_results = search($term); if (!$search_results) { echo "No results"; exit; } // Print page with results here.

We created a simple search algorithm that can handle a fair amount of content. I arbitrarily chose the score for each match, feel free to tweak it to something that works best for you. And there is always room for improvement.

It is a good idea to track the search term coming from your users, this way you can see if most users search for the same thing. If there is a pattern, then you can save them a trip and just cache the results using Memcached .

If you want to see this search algorithm in action, go ahead and try looking for an article on the search box on top of the page. I have added extra features like returning the part where the match was found in the text. Feel free to add features to yours.

Did you like this article? You can subscribe to read more awesome ones. .

On a related note, here are some interesting articles.

If there is one thing a web server does everyday it iss connecting to the database. I have been using PHP for many years now, but if you ask me to write a script to fetch data from the database I couldn"t do it without going back to the Ultimate PHP manual to find a few examples first.

A few months ago I updated my PHP version. PHP 5.4 to 5.5 . I never had any problems updating PHP before. I follow its development closely and try to remove my deprecated functions long before they are officially removed. But this time I was caught off guard. It silently broke part of my website for the silliest reason.

Comments(45)

Zaryel Aug 12 2015:

Ian Mustafa Sep 26 2015:

Rob Sep 29 2015:

adeem Feb 11 2016:

Ivan Venediktov Apr 9 2016.

SSY stands for "Siddha Samadhi Yoga" (often expanded as ‘Science of Silence Yoga’) where Siddha means ‘something (i.e., knowledge) that is proven or accomplished’, Samadhi means ‘a state in which the intellect is equanimous’ and Yoga means ‘union with one’s higher self’.

SSY is the fundamental knowledge of life. Our ancient rishis had formulated a unique mode of training called Brahmopadesam, which is an instruction on the science of non-doing and experiencing stillness within and abundance without. It brings about a sea change in one’s outlook towards life and effects remarkable maturity in the individual. SSY is nothing but the present-day version of this ancient science of Brahmopadesam.

SSY as a training programme is offered by Life Yessence Academy (LiYA) , and it is the flagship programme of the institution. Being the flagship programme, it has become synonymous with the name of the organisation. Trainings of this great knowledge are taught in many places in the world by teachers of LiYA. The Indian chapter of LiYA is called Rishi Samskruti Vidya Kendra (RSVK ).

“I am the Body” is the first notion that kills the awakening. SSY is the process
To enter into Samadhi, the state of total detachment. "
-Guruji

Основные задачи:

  • реализовать поиск таким образом, чтобы после ввода поискового запроса в строку, ниже этой строки появились результаты поиска
  • запрос на получение результата должен происходить только после окончания ввода поискового запроса

Окей, поехали!

Примерная вёрстка самого блока с поисковой строкой и div-ником, куда будем добавлять результаты поиска:

Т.к. поиск доступен в шапке сайта, добавим соответствующие скрипты поиска и стилизации результатов:

//подрубаем поиск: $APPLICATION->AddHeadScript("/search/ajax_search.js"); $APPLICATION->AddHeadScript("/search/jquery.mCustomScrollbar.js"); $APPLICATION->SetAdditionalCSS(SITE_TEMPLATE_PATH . "/css/ajax_search.css"); $APPLICATION->SetAdditionalCSS(SITE_TEMPLATE_PATH . "/css/jquery.mCustomScrollbar.min.css");

Теперь посмотрим, что лежит в нашем ajax_search.js:

Function get_result (){ //очищаем результаты поиска $("#search_result").html(""); //пока не получили результаты поиска - отобразим прелоадер $("#search_result").append(""); $.ajax({ type: "POST", url: "/search/ajax_search.php", data: "q="+q, dataType: "json", success: function(json){ //очистим прелоадер $("#search_result").html(""); $("#search_result").append(""); //добавляем каждый элемент массива json внутрь div-ника с class="live-search" (вёрстку можете использовать свою) $.each(json, function(index, element) { $("#search_result").find(".live-search").append(""+element.TITLE+""+element.BODY_FORMATED+""); //console.log (element.BODY_FORMATED); }); //стилизуем скроллинг $(".live-search").mCustomScrollbar({ scrollInertia: 500 }); } }); } var timer = 0; var q = ""; $(document).ready(function() { $("#q").keyup(function() { q = this.value; clearTimeout(timer); timer = setTimeout(get_result, 1000); }); $("#reset_live_search").click(function() { $("#search_result").html(""); }); });

keyup функция осуществляем вызов функции get_result(), которая собственно и заполняет div-ник с id=»search_result» по аяксу.

mCustomScrollbar — это просто вызов стилизации (можете отключить).

Данные от /search/ajax_search.php мы получаем в формате JSON.

С JS составляющей всё понятно, теперь посмотрим, что происходит в ajax_search.php:

В данном случае поиск осуществляется методом Search Битриксового класса CSearch. В PARAM2 пишем в каком инфоблоке ищем. Результаты поиска запихиваем в массив $result. Обратите внимание, что в $res[‘ITEM_ID’] может быть как элемент, так и раздел. В зависимости от того, что нашли, в $result_item[‘BODY_FORMATED’] пихаем либо название раздела, либо кусок текста из найдённого элемента инфоблока.