Today our goal is to create a hierarchical structure of categories. It is important for us that it is convenient to store categories and that it is easy to display them where we need them.
Sometimes the simple seems complicated, that's why I'll lay out a few code snippets that I hope will be useful to you for implementing php categories in the form of a tree.
So, the structure should consist of the category id (id), the category name (name) and of course the parent category id (parent_id). In MySQL it looks like this:
CREATE TABLE IF NOT EXISTS `category` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `parent_id` int(11) NOT NULL, PRIMARY KEY (`id`)) ENGINE =InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ;
Minimal and understandable table structure for storing categories.
INSERT INTO `category` (`id`, `name`, `parent_id`) VALUES (1, "Phones and tablets", "0"), (2, "Cars", "0"), (3, "Samsung ", "1"), (4, "Apple", "1"), (5, "LG", "1"), (6, "Ford", "2"), (7, "Lexus", "2"), (8, "BMW", "2"), (9, " Galaxy Tab 4", "3"), (10, "Galaxy S6", "3");
Where parent_id=0, this category has no parent category.
Everything is clear and simple here. Now let's move on to listing the categories. But for the correct output of the list, we first need to get the entire list of php categories, and only then, using recursion, form our tree. The following function is to get this list:
Function get_cat() ( // query the database $sql = "SELECT * FROM category"; $result = mysql_query($sql); if(!$result) ( return NULL; ) $arr_cat = array(); if( mysql_num_rows($result) != 0) ( //For($i = 0; $i< mysql_num_rows($result);$i++) { $row = mysql_fetch_array($result,MYSQL_ASSOC); //Формируем массив, где ключами являются адишники на родительские категории if(empty($arr_cat[$row["parent_id"]])) { $arr_cat[$row["parent_id"]] = array(); } $arr_cat[$row["parent_id"]] = $row; } //возвращаем массив return $arr_cat; } }
//get the catalog array $result = get_cat();
Now we need a function with recursion
Function view_cat($arr,$parent_id = 0) ( //Recursion exit conditions if(empty($arr[$parent_id])) ( return; ) echo "
- "; // loop through the array and display for($i = 0; $i< count($arr[$parent_id]);$i++) {
echo "
- " .$arr[$parent_id][$i]["name"].""; //recursion - check if there are any child categories view_cat($arr,$arr[$parent_id][$i]["id"] ); echo " "; ) echo "
Now it remains only to display the directory on the screen using the recursive function
View_cat($result);
And in general, that's all. This way we can get a complete tree of categories with infinite subcategories.
) I showed you an example of using regular expressions to find certain pieces source code pages. Now we will learn how to write them yourself. This skill will help you write, clear text from unnecessary fragments, search for the right parts in large volumes of text, and so on.
Publication date: 20.10.2013
We continue to write a liveinternet visitor statistics parser. If someone has just joined us, then I advise you to start with, where we connected to the service without authorization. There we learned how to get content from open pages that are not password protected. But, in fact, access to most sites is closed, so there is very little use for a script that does not know how to log in, as you understand. But don't worry, we'll fix it now.
Publication date: 08.10.2013
Good afternoon, readers! It's time to get some practice. You already have enough knowledge to start writing useful scripts that will make your work easier. One of these can be a parser. What it is, I described in detail in my own, so if you don’t know, I advise you to read it. Briefly, the essence of the parser is to search and isolate necessary information from a large piece of text. In the case of the Internet, this is most often pulling out the required data from the pages of sites. In our case, this will be Liveinternet. So let's go!
Publication date: 03/10/2013
This article will focus on such a powerful tool as cURL, as well as a php library that provides access to this tool - libcurl. What is all this for? To communicate with the server via data transfer protocols, such as http or ftp. The rest of the protocols are not of particular interest to us, if someone wants to delve into this topic, then they will have to dig English-language resources, and this article will contain the basics and examples of use.
Publication date: 24.11.2012
Publication date: 05.11.2012
And now there will be a rather large, but not complicated lesson about working with files in php. First of all, what are the files for? After all, you can store everything in the database MySQL data or PostgreSQL or whatever. But sometimes there are such tasks when using the database, with all the processing and concern for the security of the connection, is not advisable. For example, you need to make a regular counter, and before that, we did not use a database in our project. So why should we, for the sake of one tiny counter, start a database and store only a couple of lines in it? it's much easier to use files. In addition, sometimes hosting does not support databases at all, then files generally remain the only way out.
Publication date: 04.11.2012
Whenever you allow your users to submit text to your site (name, or any other information), you must be careful. You need to be sure that you do not have security holes in the site that attackers can use to hack. If you still need to receive data from the user, be sure to use the htmlentities function to prevent running HTML code or scripts that can be harmful and dangerous!
Publication date: 04.11.2012
In this lesson, we will look at techniques for passing data between forms and pages. These methods are POST and GET. We will talk about each separately and in more detail. Generally speaking, it is necessary for communication between forms. For example, we fill in some fields on the page and we need to transfer them to another page for processing.
Publication date: 03.11.2012
In fact, as you might have guessed by now, the do while loop is a slightly modified version of the while loop we saw in previous tutorials. If you remember how the regular while works, then it will be easier for you to understand the new loop. Let's repeat: the body of the while loop is executed if the condition is true and not executed if it is not true, but it may not be executed even once if the condition is false from the very beginning. How does do while work?
Publication date: 03.11.2012
Imagine that you have an associative array that you want to iterate over. PHP provides an easy way to use each element of an array in turn using the Foreach construct.
Returns an array of objects containing category information.
The parameters passed to this function are very similar to the parameters passed to the wp_list_categories() function and can be passed either as an array or as a query string: type=post&order=DESC .
✈ 1 time = 0.005625s = So slow| 50000 times = 11.98s = slowly| PHP 7.1.11, WP 4.9.5
Usage
$categories = get_categories($args);Usage Pattern
$categories = get_categories(array("taxonomy" => "category", "type" => "post", "child_of" => 0, "parent" => "", "orderby" => "name", " order" => "ASC", "hide_empty" => 1, "hierarchical" => 1, "exclude" => "", "include" => "", "number" => 0, "pad_counts" => false, // full list parameters, see the description of the function http://wp-kama.ru/function/get_terms)); if($categories)( foreach($categories as $cat)( // Data in the $cat object // $cat->term_id // $cat->name (Category 1) // $cat->slug (rubrika- 1) // $cat->term_group (0) // $cat->term_taxonomy_id (4) // $cat->taxonomy (category) // $cat->description (Description text) // $cat->parent (0) // $cat->count (14) // $cat->object_id (2743) // $cat->cat_ID (4) // $cat->category_count (14) // $cat->category_description (Description text) // $cat->cat_name (Category 1) // $cat->category_nicename (rubrika-1) // $cat->category_parent (0) ) ) taxonomy (line) The name of the taxonomy to process. Added since version 3.0.Default: "category" type (line)
- post - post categories (default);
- link - sections of links.
Default: "post"
Default: "" order by (line)
Sorting the received data according to certain criteria. For example, by the number of posts in each category or by category name. The following criteria are available:
- ID - sorting by ID;
- name - sort by name (default);
- slug - sorting by alt. name (slug);
- count - by the number of entries in the category;
- term_group - by group.
Default: "name"
Order (line)
The sorting direction specified in the "orderby" parameter:
- ASC - in order, from smallest to largest (1, 2, 3; a, b, c);
- DESC - in reverse order, from largest to smallest (3, 2, 1; c, b, a).
Default: "ASC"
Hide_empty (logical)
Whether or not to get empty categories (having no entries):
- 1 (true) - do not receive empty,
- 0 (false) - get empty.
Default: true
Hierarchical (logical) If the parameter is set to true, the result will include empty child categories whose child categories have entries (non-empty).
Default: true exclude (string/array) Exclude any categories from the list. You must specify category IDs separated by commas or in an array. If this parameter is specified, the child_of parameter will be overridden.
Default: "" include (string/array) List only the specified categories. You need to specify category IDs separated by commas or in an array.
Default: "" number (number) Limit. The number of categories to be retrieved. By default, no restrictions - all categories will be retrieved. pad_counts (logical) If true, then the number that shows the number of entries in the parent categories will be the sum of its own entries and entries from child categories.
Default: false
Examples
#1 Dropdown list
In order to create a dropdown list of categories, we can use another special function wp_dropdown_categories() :
wp_dropdown_categories(array("hide_empty" => 0, "name" => "category_parent", "orderby" => "name", "selected" => $category->parent, "hierarchical" => true, "show_option_none" => __("None")));
however, with this approach, we will lose some flexibility in setting up the list, since we will end up with a fully formed list.
Therefore, in some cases it will be more logical to create a drop-down list using the function get_categories(). Here's an example (assuming we want to display the subcategories (children) of category 10):
#2 List of categories and their description
This example will show us how to list links to categories, where immediately after each link there will be a description of the category (specified when creating / editing a category):
"name", "order" => "ASC")); foreach($categories as $category)( echo "
Category: term_id) . ""title="" . sprintf(__("View all posts in %s"), $category->name) . "" " . ">" . $category->name."
"; echo "Description:". $category->description . "
"; echo "Post Count: ". $category->count . "
"; } ?>Notes
- See: get_terms() Type of arguments that can be changed.
List of changes
Since version 2.1.0 | Introduced. |
The code getcategories : wp-includes/category.php WP 5.3.2
"category"); $args = wp_parse_args($args, $defaults); /** * Filters the taxonomy used to retrieve terms when calling get_categories(). * * @since 2.7.0 * * @param string $taxonomy Taxonomy to retrieve terms from. * @param array $args An array of arguments. See get_terms(). */ $args["taxonomy"] = apply_filters("get_categories_taxonomy", $args["taxonomy"], $args); // Back compat if (isset($args["type"]) && "link" == $args["type"]) ( _deprecated_argument(__FUNCTION__, "3.0.0", sprintf(/* translators: 1: " type => link", 2: "taxonomy => link_category" */ __("%1$s is deprecated. Use %2$s instead."), "type => link
",
"taxonomy => link_category
")); $args["taxonomy"] = "link_category"; ) $categories = get_terms($args); if (is_wp_error($categories)) ( $categories = array(); ) else ( $categories = (array ) $categories; foreach (array_keys($categories) as $k) ( _make_cat_compat($categories[ $k ]); ) ) return $categories; ) In this article (webmaster level - advanced), we will talk about, intersecting in different ways, the so-called. faceted navigation. To simplify the assimilation of the material, I recommend going over the Wikipedia article "Facet classification" and publications in English (but with pictures!) "Design better faceted navigation for your websites".
Faceted navigation filtered by color or price range can be useful for your visitors, but often detrimental to search by creating multiple address combinations with duplicate content. Due to duplicates, search engines will not be able to quickly crawl the site for content updates, which accordingly affects indexing. To minimize this problem and help webmasters make faceted navigation search-friendly, we'd like to:
Ideal for users and Google search
Clear path to products/article pages:
Representing the URL for the category page:
http://www.example.com/category.php?category=gummy-candies
Representing a URL for a specific product:
http://www.example.com/product.php?item=swedish-fish
Unwanted duplicates caused by faceted navigation
The same page is accessible from different web addresses:
Canonical page
URL: example.com/product.php? item=swedish-fish
Duplicate page
URL:example.com/product.php? item=swedish-fish&category=gummy-candies&price=5-10
category=gummy-candies&taste=sour&price=5-10
Errors:
- Doesn't make sense to Google, as users rarely search for [$9:55 marmalade].
- Doesn't make sense for crawlers to find the same item ("fruit salad") from parent category pages (either "Gummi" or "Sour Gummy").
- A negative point for the site owner, because indexing requests are diluted with multiple versions of the same category.
- A negative point for the site owner, because it is a useless and unnecessary load on the site's bandwidth
URL: example.com/category.php? category=gummy-candies&taste=sour&price=over-10
Errors:
- Incorrectly given code for search engines (in this case, the page should give the code 404)
- Blank page for users
Worst (unsearch friendly) solutions to faceted navigation
Example #1: Non-standard parameters are used in the URL: commas and brackets, instead of key=value&:
- example.com/category? [ category:gummy-candy ][ sort:price-low-to-high ][ sid:789 ]
- example.com/category?category , gummy-candy , sort , lowtohigh , sid , 789
example.com/category? category=gummy-candy&sort=low-to-high&sid=789
Example #2: Using directories or file paths rather than options in lists of values that don't change the content of the page:
example.com/c123/s789/product?swedish-fish
(where /c123/ is the category, /s789/ is the session ID, which does not change the content of the page)
Good decision:
- example.com /gummy-candy/ product?item=swedish-fish&sid=789(the directory, /gummy-candy/, changes the contents of the page in a meaningful way)
- example.com/product?item=swedish-fish& category=gummy-candy&sid=789 (URL parameters give more flexibility for search engines to determine how to crawl efficiently)
Common values that do not change the content of the page and should be listed as URL parameters include:
- Session ID
- ID Tracking
- Referrer identifiers
- Timestamps
Using minor data generated by site users (such as longitude/latitude or "days ago") in crawled and indexed URLs:
- example.com/find-a-doctor? radius=15&latitude=40.7565068&longitude=-73.9668408
- example.com/article?category=health& days-ago=7
- example.com/find-a-doctor? city=san-francisco&neighborhood=soma
- example.com/articles?category=health& date=january-10-2014
- example.com /filtering/ find-a-doctor?radius=15&latitude=40.7565068&longitude=-73.9668408
- example.com /filtering/ articles?category=health&days-ago=7
User-agent: *
Disallow: /filtering/
Example #4. Adding URL parameters without logic.
- example.com /gummy-candy/lollipops/gummy-candy/ gummy-candy/product?swedish-fish
- example.com/product? cat=gummy-candy&cat=lollipops&cat=gummy-candy&cat=gummy-candy&item=swedish-fish
- example.com /gummy-candy/ product?item=swedish-fish
- example.com/product? item=swedish-fish&category=gummy-candy
Example #5: Suggest further refinements (filtering) when there are null results.
Badly:
Allow users to select filters when there are null items to refine.
Refinement to a page with zero results (for example, price=over-10), which frustrates users and causes unnecessary queries for search engines.
How to:
Create links only when there are elements for the user to select. If the result is zero, mark the link as "grey" (i.e. unclickable). To further improve usability, consider including an item count indicator next to each filter.
Displaying a page with zero results (for example, price=over-10) is not allowed, plus it is forbidden for users to make unnecessary clicks, and for search engines to crawl this not useful page.
It is necessary to prevent unnecessary URLs and minimize visitor space by generating URLs only when products are available. This will help keep users engaged on your site (fewer back button clicks when no product is found), reduce the number of possible URLs known to search engines. Also, if the page is not just "temporarily out of stock" but is unlikely to ever contain relevant information, consider giving it a 404 response code. On the 404 page, you can design a useful message for users with more navigation options or a search box so that users can find related products.
For new sites whose webmasters are considering implementing faceted navigation, there are several options to optimize crawling (the collection of addresses on your site known to Googlebot) of unique content pages and reduce search engine indexing of duplicate pages (consolidation of indexing signals).
Determine what URL parameters are required for search engines to crawl each individual page of content (ie, determine what parameters are required to create at least one click path to each item). Required parameters can include item-id , category-id , page etc.
Determine which parameters will be useful to visitors with their queries, and which are more likely to cause duplication in crawling and indexing. In the confectionery (marmalade) example, the "taste" URL parameter could be valuable to users with the queries in the example taste=sour . However, it is logical to consider the "price" parameter as causing unnecessary duplication category=gummy-candies&taste=sour& price=over-10 . Other common examples:
- Valuable parameters for search engines: item-id , category-id , name , brand ...
- Unnecessary parameters: session-id , price-range ...
Option 1: and internal links
Mark all unnecessary URLs with the . This will reduce the labor costs of the search robot and prevent a decrease in the frequency of scanning. You need to globally manage crawling through robots.txt (Translator's note: see article "").
Use the rel="canonical" attribute to separate pages for the search index from pages not needed there (for example, on the page price=5-10
you can write the rel="canonical" attribute, indicating the category of all sour marmalade example.com/category.php?category=gummy-candies&taste=sour& page=all
).
Option 2: Robots.txt and Disallow
URLs with unnecessary parameters are included in the /filtering/ directory, which will be closed in robots.txt (prohibit disallow). This will allow all search engines to crawl only the "correct" intralink (content) of the site, but will block crawling unwanted URLs at once. For example ( example.com/category.php?category=gummy-candies), if the valuable parameters were item, category, and taste, and the session id and price were redundant, then the URL for taste would be:
example.com/category.php?category=gummy-candies& taste=sour,
but all unnecessary parameters, such as price, the URL will include in a predefined directory - /filtering/:
example.com /filtering/ category.php?category=gummy-candies&price=5-10,
which will then be banned via robots.txt:
User-agent: *
Disallow: /filtering/
Option 3: Separate hosts
Make sure the best solutions listed above (for junk addresses, for example) still apply. Otherwise, search engines have already formed a large link mass in the index. Thus, your work will be aimed at reducing the further growth of unnecessary pages viewed by Googlebot and consolidating indexing signals.
Use parameters with standard encoding and key=value format.
Make sure that values that do not change the content of the page, such as session IDs, are implemented as key=value, not directories.
Don't allow clicks and don't generate URLs when there are no elements to filter.
Add logic to URL parameter mapping: remove unnecessary parameters rather than adding values all the time (e.g. avoid generating a link like this: example.com/product?cat=gummy-candy&cat=lollipops &cat=gummy-candy&item=swedish-fish).
Store valuable parameters in the URL by listing them first (because URLs are visible in search results) and less relevant parameters last (such as the session ID).
Avoid this link structure: example.com/category.php? session-id=123&tracking-id=456&category=gummy-candies&taste=sour
Adjust the URL settings in Webmaster Tools if you have a clear understanding of how links on your site work.
Ensure that when using JavaScript to dynamically manage content (sort/filter/hide) without updating the URL, there are real web addresses on your site that have search value, such as main categories and product pages, that are crawlable and indexable . Try not to use only the home page (i.e. one URL) for your entire site, but dynamically change the content of the navigation through JavaScript - this, unfortunately, will give users only one URL in the search. Also, make sure that performance does not negatively impact dynamic filtering, as it will prevent the user from working with the site.
Improve the indexing of different pages of the same content by specifying the rel="canonical" attribute on the privileged version of the page. The rel="canonical" attribute can be used within one or more domains.
Optimize the indexing of "paginated" content (e.g. page=1 and page=2 from the "gummy candies" category) by (either):
- Add a rel="canonical" attribute to a series of pages specifying the canonical category with the "view-all" parameter (e.g. page=1, page=2, and page=3 from the "gummy candies" category with rel=”canonical” on category=gummy-candies&page=all), making sure the page is relevant to users and loads quickly.
- Use pagination markup rel="next" and rel="prev" to indicate the relationship between individual pages (see "Paginaton with rel="next" and rel="prev" ") .
And so, to begin with, I will describe what we will work with and what we will need.
System: PHP 5 and above, mySQL 4 and above
Helper classes: dbsql.class.php (database class)
Nested category class: classTreeCategory.php (directly the main class, its listing and explanations are given below.
Create a table in the database with the following structure:
Viewing MySQL Code
This table contains a field ID- serial number of the category, podcat- has a value of zero for categories of the first order or the ID of the parent category, name- name of category.
An example of the class, displaying categories as a list with subcategories:
View PHP code
include("dbsql.class.php") ; include("classTreeCategory.php" ) ; $DB = new DB_Engine("mysql" , $settings [ "dbHost" ] , $settings [ "dbUser" ] , $settings [ "dbPass" ] , $settings [ "dbName" ] ) ; // connect to the database, specifying access data$category = new TreeCategory ($DB ) ; // pass to the category class, the object of work with the database$category -> table = "category" ; // table name in the database with categories$array = $category -> getCategory() ; // get all categories from the database in the form of a multi-level array, sorted and nested already in the order we need$category -> outCategory ($array , "option" ) ; // preparing the output of categories (forming HTML), passing an array with categories echo $category -> html ; // output categories as HTML |
As you can see from the example above, everything is extremely simple, we create a new $category object, set which database table we work with: 'category', then we get from the table a list of all categories already formatted as an array and decomposed in a hierarchical order, taking into account all subcategories. then we pass the array to the outCategory() method, which generates a ready-made HTML code for us, which remains only to be displayed in the browser.
The outCategory() method, as we can see, takes two parameters @array and @string in the first parameter an array with all categories, and in the second a string containing a value option or table, this value specifies what type of HTML code to generate.
Meaning option
View HTML Code
To insert the given HTML code into the select field of any form.
Meaning table- generates the following HTML code:
View HTML Code
This HTML code is handy for pasting into a table that displays all of our categories subcategories.
The class also has the following methods:
deleteItem($id);- removes one category, despite the nested ones
delCategory($array, $id);- deletes a category with all nested subcategories, $array - an array with all categories prepared by the $category->getCategory() method, $id - number of the category to be deleted
addItem();- this method should be called if you want to add a category, while this method reads the values from the data transmitted by the POST method, i.e. from the $_POST array.
$name=$this->PHP_slashes(strip_tags($_POST['name'])); // category name
$podcat=intval($_POST['podcat']); // ID of the parent category, if 0 is specified, the category will be at the root.
updateItem(); - similar to the previous method, except that this method updates the category, its name and nesting level.
The whole class was written within an hour and, of course, has flaws, but all this is fixable. Its use is advisable for educational purposes, although by the way, having finished it a little, you can embed it into any system and enjoy its work)).
I would be grateful if in the comments you offer your own options for solving this problem - organizing categories of an infinite nesting level.