Frontend. 15+ hooks for functions.php
Another collection of popular, useful, and interesting hooks for the frontend of the site. Here I have tried to collect, test, and improve some interesting and necessary hacks that I managed to find on the web. There were small and large errors almost everywhere.
More collections of hooks:
Changing the image on the login page - wp-login.php
This code changes the wp-login.php login page. Here you can replace the logo and link from the main image that leads to the wordpress.org site.
## Changes the logo, its link, and the title attribute on the login page if(1){ // Change the image (logo) // specify the correct image link. add_action( 'login_head', 'wp_login_logo_img_url' ); function wp_login_logo_img_url() { echo ' <style> .login h1 a{ background-image: url( '. get_template_directory_uri() .'/images/logo.png ) !important; } </style>'; } // Change the link from the logo add_filter( 'login_headerurl', 'wp_login_logo_link_url' ); function wp_login_logo_link_url( $url ){ return home_url(); } // Change the title attribute of the logo link add_filter( 'login_headertitle', 'wp_login_logo_title_attr' ); function wp_login_logo_title_attr( $title ) { $title = get_bloginfo( 'name' ); return $title; } }
The first hook can be replaced with this one. Then the logo image on the login page will be taken from the header image setting.
## Takes the image for the logo on the login page from the one set in the settings add_action( 'login_head', 'wp_login_logo_img_url' ); function wp_login_logo_img_url() { if( function_exists('get_custom_header') ){ $width = get_custom_header()->width; $height = get_custom_header()->height; } else { $width = HEADER_IMAGE_WIDTH; $height = HEADER_IMAGE_HEIGHT; } echo ' <style> .login h1 a { background-image: url('. get_header_image() .') !important; background-size: '. $width .'px '. $height .'px !important; width: '. $width .'px !important; height: '. $height .'px !important; } </style>'; }
Redirect to a post when searching
When searching on the site, it sometimes happens that only one post is found. In some cases, it is convenient to immediately redirect to this post, so that the user does not have to click to go to the only post.
// Redirect to a post from the search page if only one post is found add_action('template_redirect', 'single_result'); function single_result(){ if( ! is_search() ) return; global $wp_query; if( $wp_query->post_count == 1 ){ wp_redirect( get_permalink( reset($wp_query->posts)->ID ) ); die; } }
Google Analytics and Yandex Metrica (installation)
The code for the metric or analytics can be added directly to the header.php template file. But it is better to do this through a hook so that this code can be programmatically disabled later:
add_action( 'wp_head', 'add_googleanalytics', 99 ); // or, if you need to display it in the footer //add_action( 'wp_footer', 'add_googleanalytics', 99 ); function add_googleanalytics(){ ?> // Analytics code // Metrica code <?php }
Increase image sharpness (thumbnails) (only for jpg)
The thumbnails of uploaded images usually lack sharpness. Sometimes they look normal, but only sometimes... Well, and sharpness never hurt the thumbnails
The code below will work for all created intermediate sizes. The code is designed only for the GD library. If you have Imagick on your server, the code will not do anything with the thumbnails...
## Increase sharpness for created thumbnails (only jpg). Only for the GD library... add_filter('image_make_intermediate_size', 'sharpen_resized_image_files', 900 ); function sharpen_resized_image_files( $resized_file ){ if( ! function_exists('imagecreatefromstring') ) return $resized_file; // The GD image library is not installed. // load the image. equivalent to the old wp_load_image() function if(1){ // Increase memory size to the maximum. if( function_exists('wp_raise_memory_limit') ) wp_raise_memory_limit( 'image' ); $image = imagecreatefromstring( file_get_contents($resized_file) ); } if( ! is_resource($image) ) return $resized_file; // error_loading_image if( ! $size = @ getimagesize($resized_file) ) return $resized_file; // invalid_image - Could not read image size list( $orig_w, $orig_h, $orig_type ) = $size; switch( $orig_type ){ case IMAGETYPE_JPEG: $matrix = array( array(-1, -1, -1), array(-1, 16, -1), array(-1, -1, -1), ); $divisor = array_sum(array_map('array_sum', $matrix)); $offset = 0; imageconvolution( $image, $matrix, $divisor, $offset ); imagejpeg( $image, $resized_file, apply_filters( 'jpeg_quality', 90, 'edit_image' ) ); break; case IMAGETYPE_PNG: return $resized_file; case IMAGETYPE_GIF: return $resized_file; } return $resized_file; }
What will be the result:
gzip compression
How does it work and what's the catch? The browser requests a page from the server. The server creates the HTML code of the requested page, compresses it, and gives it to the browser. The browser receives it in compressed form, decompresses it, and shows it to us. As a result of compression, the size of the HTML code when loaded by the browser from the server is reduced, for example, from 500 to 250 KB.
Compression can be enabled in different ways: in the server settings, through the .htaccess file, or in PHP. Below is shown only one way - enabling it through one of the PHP modules - this is just one of about 6 ways.
Compression may already be enabled:
- automatically on the server
- in page caching plugins such as WP Total Cache, WP Super Cache.
Therefore, before using the code, make sure that compression is not yet enabled. To do this, look at the HTTP response headers, it is visible there:
- open the developer panel in the Google Chrome browser (ctrl+shift+i)
- go to the "Network" tab
- reload the page in the browser and click on the first line (this is the request for the HTML code of the page)
- look at the headers.
If compression is not yet enabled, then insert the code below into the theme's functions.php and check if it has been enabled. Since this code only works when the zlib PHP library is enabled (it is usually available on the server).
if( extension_loaded('zlib') && ini_get('output_handler') != 'ob_gzhandler' ){ add_action('wp', function(){ @ ob_end_clean(); @ ini_set('zlib.output_compression', 'on'); } ); }
If compression has not been enabled, look for another way to enable it on the web.
Add post types to search results
Whether to include a post type in the search or not is set when registering the post type, in the exclude_from_search parameter in register_post_type().
If the post type is not yet included in the search, an alternative way to include it there is the code below. Here, the post type movie is added to the search results, so now when searching, WP will also search for the specified query in the movie post type.
## Add post types to search results add_action('pre_get_posts', 'get_posts_search_filter'); function get_posts_search_filter( $query ){ if ( ! is_admin() && $query->is_main_query() && $query->is_search ) { $query->set('post_type', array('post', 'movie') ); } }
Page generation time
Let's display data on how many database queries were made to generate the page, at what speed the page was generated, and how much memory was required for this.
Since WP 5.9, the function timer_float() has appeared, it is better to use it:
/** * Displays data on the number of database queries, * script execution time, and the amount of memory used. */ add_filter( 'admin_footer_text', 'wp_usage' ); function wp_usage(){ echo sprintf( 'SQL: %d in %.3F sec. %s MB', get_num_queries(), timer_float(), round( memory_get_peak_usage()/1024/1024, 2 ) ); }
For WP 5.8 and below:
/** * Displays data on the number of database queries, * script execution time, and the amount of memory used. */ add_filter( 'admin_footer_text', 'wp_usage' ); // in the admin footer add_filter( 'wp_footer', 'wp_usage' ); // in the site footer function wp_usage(){ echo sprintf( 'SQL: %d in %s sec. %s MB', get_num_queries(), timer_stop( 0, 3 ), round( memory_get_peak_usage()/1024/1024, 2 ) ); }
Link to the first image in the content
Option 1:
The code below will automatically "extract" the first image from the current post and return the ready <img> code of the image wrapped in a link to the current post.
In the $num parameter, you can specify the number of the image in the post to be retrieved. For example, if you specify 2, the code will retrieve the second image instead of the first.
/** * Retrieves the first or specified image from the content of the current post in the loop * and returns it in the form of an `<a><img>` construction (image = anchor link to the current post). * Convenient to use as a post thumbnail... * * @param integer [$num = 1] The number of the image in the text to be retrieved. * @return string HTML */ function get_post_content_image( $num = 1 ){ global $more; $more = 1; $content = get_the_content(); $count = substr_count( $content, '<img'); $start = 0; for( $i=1; $i<=$count && $i<=$num; $i++ ){ $imgBeg = strpos( $content, '<img', $start ); $post = substr( $content, $imgBeg ); $imgEnd = strpos( $post, '>'); $postOutput = substr( $post, 0, $imgEnd+1 ); $postOutput = preg_replace('~(?:width|height)="[0-9]*"~', '', $postOutput ); $image[$i] = $postOutput; $start = $imgEnd + 1; } // if the image exists, output it if( isset($image[$num]) && stristr($image[$num], '<img') ) return '<a href="'. get_permalink() .'">'. $image[$num] ."</a>"; $more = 0; }
Usage example:
echo get_post_content_image(); // <a href="http://example.com/zapis/"><img class="alignnone size-medium wp-image-126" src="http://example.com/wp-content/uploads/2016/05/asd.jpg" alt=""></a>
Option 2:
See the answer to the question: How to get the URL of the first image from the post content?
Which template file is used?
To find out which theme file is used to generate the current page, simply look into the global variable $template.
This code outputs the path to the file used as the template for the current viewed page before the header or in the footer.
add_action('wp_head', 'show_template'); // before the header // add_action('wp_footer', 'show_template'); // in the footer function show_template(){ global $template; echo $template; }
Adding post type to the output on the archive page of the tag
Suppose, when registering the post type, we specified the taxonomy of tags (post_tag) for it, and now the new post type also has tags. Now we need the standard tag page to display posts from our new post type as well.
add_filter('request', 'any_ptype_on_cat'); function any_ptype_on_cat( $request ){ // for tags if( isset($request['tag']) ) $request['post_type'] = array('post','custom_post_type'); // for categories if( isset($request['category_name']) ) $request['post_type'] = array('post','custom_post_type'); return $request; }
Remove the "Read More" jump
If the post content contains the <!--more--> tag, then in the post loop, the "Read More" link will lead to the post page and then redirect the user to the text that comes after this tag. To remove this "jump," use the following code:
add_filter('the_content_more_link', 'remove_more_jump_link'); function remove_more_jump_link( $link ){ return preg_replace('~#more-[0-9]+~', '', $link ); }
The code will work only if the excerpt is displayed through get_the_content() or the_content()
Embeds (oEmbed) in text (in the "Text" widget)
Embedding objects in the "Text" widget. What does this mean? Let's consider an example. Suppose we need the links from a special whitelist to be processed in the text widget, just like in a post. For example, we specify a link to a YouTube video on a separate line, and when viewed, it turns into a YouTube player - the link changes to HTML code on the fly.
The hack below allows you to enable such a "feature" for the text widget. Insert the code into the theme's functions.php file.
After inserting the code, you can use shortcodes and special links. All of this will be processed.
global $wp_embed; add_filter( 'widget_text', [ $wp_embed, 'run_shortcode' ], 8 ); add_filter( 'widget_text', [ $wp_embed, 'autoembed' ], 8 );
Read also: oEmbed in WordPress.
Loading scripts/styles if a shortcode is present in the content
Build In PostConnection and Verification on All Pages
This code shows how to connect a script or style file conditionally - if a specified shortcode is present in the displayed content.
// Connect the script if the specified shortcode is present on the page. // Use a filter as an event. add_filter( 'the_posts', 'has_my_shortcode' ); function has_my_shortcode( $posts ){ if( is_admin() || empty( $posts ) || ! is_main_query() ){ return $posts; } $shortcode_name = 'my_shortcode'; foreach( $posts as $post ){ if( has_shortcode( $post->post_content, $shortcode_name ) ){ add_action( 'wp_enqueue_scripts', 'add_my_scripts' ); break; } } return $posts; } // Enqueue scripts if shortcode is present function add_my_scripts() { $theme_url = get_stylesheet_directory_uri(); wp_enqueue_script( 'my_script', "{$theme_url}/my_script.js" ); }
Connection and Verification for Individual Pages - is_singular()
// Connecting scripts/styles if shortcode is present in the content add_action( 'wp_head', 'my_shortcode_styles' ); function my_shortcode_styles() { global $post; $shortcode_name = 'my_shortcode_name'; if( ! ( $post && is_singular() && has_shortcode( $post->post_content, $shortcode_name ) ) ){ return; } ?> <style> .foo{ color: red; } </style> <?php }
Loading scripts/styles if a widget is active
This example shows how to load a JS file if the "Calendar" widget is activated. Similarly, you can load scripts for any active widget.
## Loading a script if there is an active widget## ID of the basic WP widgets can be found in the description at /function/the_widget add_action('wp_enqueue_scripts', 'add_calendar_widget_scripts'); function add_my_widget_scripts(){ if( ! is_active_widget( false, false, 'calendar' ) ) return; // exit if the widget is not active $theme_url = get_stylesheet_directory_uri(); wp_enqueue_script('my_widget_script', $theme_url .'/calendar_widget_script.js' ); }
For details, read the description of the function is_active_widget().
For each WordPress widget, see the description of the function the_widget()
Loading a script when the widget's own code is active
This code is useful for developers who create widgets. If a widget has its own separate script or styles, it is more reasonable to load them only when the widget is activated.
// Widget class class My_Widget extends WP_Widget { function __construct() { // Initialize the parent class parent::__construct( 'widget_id', // Widget ID, if not specified (leave ''), the ID will be equal to the class name in lowercase: my_widget 'Widget Title', array('description' => 'Widget Description'), ); // widget scripts/styles, only if it is active if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) { add_action('wp_enqueue_scripts', array( $this, 'add_my_widget_scripts' )); add_action('wp_head', array( $this, 'add_my_widget_style' ) ); } } // Widget output function widget( $args, $instance ){ $title = apply_filters( 'widget_title', $instance['title'] ); echo $args['before_widget']; if( $title ) echo $args['before_title'] . $title . $args['after_title']; echo 'Hello!'; echo $args['after_widget']; } // Save widget settings (cleaning) function update( $new_instance, $old_instance ) { } // HTML form for widget settings in the Admin Panel function form( $instance ) { } // Widget script function add_my_widget_scripts() { // filter to be able to disable scripts if( ! apply_filters( 'show_my_widget_script', true, $this->id_base ) ) return; $theme_url = get_stylesheet_directory_uri(); wp_enqueue_script('my_widget_script', $theme_url .'/my_widget_script.js' ); } // Widget styles function add_my_widget_style() { // filter to be able to disable styles if( ! apply_filters( 'show_my_widget_style', true, $this->id_base ) ) return; ?> <style type="text/css"> .my_widget a{ display:inline; } </style> <?php } }
Removing the script/style version from the URL
When registering a script, a version is specified for it. /wp-includes/css/dashicons.min.css?ver=4.9. You can remove such a version from the script or style link:
Removing all versions from all scripts:
// Remove script versions add_filter( 'script_loader_src', '_remove_script_version' ); // Remove style versions add_filter( 'style_loader_src', '_remove_script_version' ); function _remove_script_version( $src ){ $parts = explode( '?', $src ); return $parts[0]; }
Removing only WordPress versions:
## removes the WP version from the given URL for scripts and styles add_filter( 'script_loader_src', 'hb_remove_wp_version_from_src' ); add_filter( 'style_loader_src', 'hb_remove_wp_version_from_src' ); function hb_remove_wp_version_from_src( $src ) { global $wp_version; parse_str( parse_url( $src, PHP_URL_QUERY ), $query ); if ( ! empty($query['ver']) && $query['ver'] === $wp_version ) { $src = remove_query_arg('ver', $src); } return $src; }
Removing auto-links in comments
In comments, text in the form of a link: http://example.com/foo is automatically turned into a link. To remove this conversion, insert the following hack into the theme's functions.php file:
remove_filter('comment_text', 'make_clickable', 9);