• Hjalle

    (@hjalleballe)


    Hi!

    I am wondering how I can customize the search query so that I can look up pages where a certain image exists by FILE NAME. I know that all media uploads are stored in the wp_posts table. If i search by the row ID the corresponding page shows up in the result, but I want to be able to search by file name instead; This is because I want to be able to tell customers to search for 123 and if 123 exists in a media file name, then it should show up in the search results.

    EXAMPLE:
    Lets say I name images files like this: 593_some_product.jpg
    Then I want to be able to search for 593 and have the page show up where this image exists or is used.

    END OF EXAMPLE

    I am quite new to wordpress and so this is quite hard for me to understand how can do this.
    Much appreciated if anyone could help me out on this one.

    Thanks
    // Hjalmar

    • This topic was modified 8 years, 3 months ago by Hjalle.
Viewing 6 replies - 1 through 6 (of 6 total)
  • Moderator bcworkz

    (@bcworkz)

    You will want to use the WP_Query class to find attachment post types where a custom meta field with the key “_wp_attached_file” is LIKE the search term. Don’t be tempted to search the guid field in the posts table for media filenames. While this field invariably has what you’re looking for, the reason this field exists means a valid ID could be entered here which is not the filename.

    If the attachment post returned by the query has a parent ID value that’s not zero, that will be the ID of the regular post where the media file was inserted.

    Thread Starter Hjalle

    (@hjalleballe)

    Thanks a lot bcworkz for the quick reply.

    I solved the problem by doing the following:

    function add_attachements_to_search( $where ) {
        global $pagenow, $wpdb;
       
        if ( is_search() ) {
            $where = preg_replace( 
                "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
                "(".$wpdb->posts.".post_title LIKE $1 ) OR (".$wpdb->posts.".ID = (SELECT post_parent FROM ".$wpdb->posts." WHERE  ".$wpdb->posts.".post_title LIKE $1))" , $where );
        } 
    
        return $where;
    }
    add_filter( 'posts_where', 'add_attachements_to_search' );
    • This reply was modified 8 years, 3 months ago by Hjalle.
    Moderator bcworkz

    (@bcworkz)

    No, my sense is you understood perfectly. If there were any misunderstanding it’d be on me.

    You could use posts_where filter, but it’s not optimal for our needs. This filter is best when altering a query in a way that cannot be addressed by normal WP_Query arguments. Like if you did need to search in the guid field. I remind you to not actually do this, there’s a reason WP_Query does not cover this field ??

    Generally speaking, the best hook to alter queries that use WP_Query methods is the “pre_get_posts” action. The default search query goes through this action, so there’s no need to alter your search form if it’s using the default search action. Something like example.com/index.php?s=search terms . Or any other method that uses WP_Query.

    The first things your pre_get_posts callback should do is confirm the passed query is the main query and that it’s a search query. If so, set the “meta_query” query var as required to include the attached file field as part of the search query.

    There is one rather serious problem in the resulting query I think. When you add a meta_query argument it is added to the other constraints with a logical AND. I’m fairly sure you want a logical OR for this. Do verify this is the case. You can use that posts_where filter to do this. If so, you’ll also need to use the posts_where filter to change that critical AND to an OR.

    Part of the problem with using posts_where is it’s difficult for your callback to know when to apply a change and when not to. Because we already worked this out in pre_get_posts, we can add the posts_where filter from within the pre_get_posts callback so we’re sure it’ll only be applied to our search queries.

    The other reason posts_where would not work on it’s own is the postmeta table needs to be joined in, which is outside the scope of posts_where. There is a “posts_request” filter where your callback is passed the entire SQL query, but code that alters a query string is inherently fragile when compared to setting query args in pre_get_posts. We should try to keep fragile code to a minimum even if it means using two hooks instead of one.

    If there’s any chance for misunderstanding, this will be it. If anything here is not clear, don’t hesitate to ask for clarification.

    Moderator bcworkz

    (@bcworkz)

    In case it’s not clear, we cross posted. I was replying to your original post. I’m leaving it up for reference by others. As long as your solution works for you then that’s fine.

    Thread Starter Hjalle

    (@hjalleballe)

    Thanks again,

    Yeah, I realized that my first reply was unnecessary since I managed to solve the problem so I edited the reply.

    I also read this article: https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/
    where I learnt how to left join the wp_postmeta table. The code I posted above is a modification of the second paragraph in the article where I added the things you said ??

    Thanks a lot for your help bcworkz.

    • This reply was modified 8 years, 3 months ago by Hjalle.
    Moderator bcworkz

    (@bcworkz)

    You’re welcome. You pretty much worked this out on your own. My only contribution was where to search ??

Viewing 6 replies - 1 through 6 (of 6 total)
  • The topic ‘Custom query: how to search by media file name???’ is closed to new replies.