Frankelin Li's Technical Blog

website·Indexed 30 days ago

https://frankelinli.github.io

A collection of technical tutorials and code snippets focusing on WordPress customization, Python automation, Git workflows, and frontend development components using Docusaurus and CSS.

Tokens
79.2K
Snippets
322
Records
385
Agent score
71%

What's inside Frankelin Li Blog

  1. Evaluate Docusaurus for your project requirements

    Docusaurus is a static site generator specifically optimized for technical documentation and developer blogs. It may not be suitable for projects requiring:

    • Complex interactive features (e.g., e-commerce, social networks).
    • Non-documentation site types (e.g., comprehensive corporate portals).
    • Rapid expansion of complex functionality without custom coding.
  2. Understand the Visual API concept for visual automation

    The Visual API is proposed as a new standard for developing state-based, testable visual automation. It aims to solve the common problems of high complexity and the inability to test codebases in large-scale visual automation applications. An open-source framework is available to streamline the process of building a Visual API.
  3. Use subdirectories to create SEO-friendly URL hierarchies

    Using subdirectories in a URL structure helps establish a clear content hierarchy and provides users and search engines with additional context about the page's purpose. A flat URL (e.g., domain.com/airpods.html) is ambiguous, whereas a hierarchical URL (e.g., domain.com/store/earbuds/apple/airpods.html) explicitly indicates that the page is a specific product within a store's earbuds category under the Apple brand.
    # Ambiguous URL
    domain.com/airpods.html
    
    # Hierarchical, SEO-friendly URL
    domain.com/store/earbuds/apple/airpods.html
  4. Understand WP_User object properties in WordPress

    In WordPress, the WP_User object contains fixed properties that map directly to the fields in the wp_users database table. These properties provide core information about a user account.
  5. Generate dynamic site URLs in WordPress using get_site_url()

    To ensure that assets like images automatically adapt to the current environment (e.g., switching between local development and production), use the built-in WordPress function get_site_url(). This avoids the need to manually update hardcoded URLs when migrating a website.
    <img src="<?php echo get_site_url(); ?>/wp-content/uploads/2024/12/mpwechat.jpg" alt="微信公众号二维码">
  6. Create a standalone PHP page that loads the WordPress environment

    To use WordPress functions (like get_option, get_users, or wp_get_current_user) in a standalone PHP file outside of the standard theme template hierarchy, you must load the WordPress environment by requiring the wp-load.php file. This allows the script to access the WordPress database, API, and global variables.
    <?php
    // Load WordPress environment
    require( dirname(__FILE__) . '/wp-load.php' );
    
    // Now you can use WordPress functions
    $site_title = get_option('blogname');
    echo "Site Title: $site_title";
    ?>
  7. Implement a collapsible post list in a WordPress category sidebar

    To create a sidebar that lists posts from the current category with a 'Show More' toggle, you need to modify the sidebar template to limit visible posts, add CSS for styling, and use jQuery for the toggle interaction. This approach avoids the need for sub-categories by using a simple counter to hide posts beyond a specific threshold (e.g., 5 posts).
    <?php
    // In docsidebar.php
    $categories = get_the_category();
    if (!empty($categories)) {
        foreach ($categories as $category) {
            echo '<div class="category-sidebar">';
            echo '<h3>' . esc_html($category->name) . '</h3>';
    
            $args = array(
                'category__in' => array($category->term_id),
                'post__not_in' => array(get_the_ID()),
                'posts_per_page' => -1,
            );
            $query = new WP_Query($args);
    
            if ($query->have_posts()) {
                echo '<ul class="category-post-list">';
                $count = 0;
                while ($query->have_posts()) {
                    $query->the_post();
                    if ($count < 5) {
                        echo '<li><a href="' . get_the_permalink() . '">' . get_the_title() . '</a></li>';
                    } else {
                        echo '<li class="hidden-post" style="display: none;"><a href="' . get_the_permalink() . '">' . get_the_title() . '</a></li>';
                    }
                    $count++;
                }
                echo '</ul>';
                if ($count > 5) {
                    echo '<button class="toggle-more-posts">展开更多</button>';
                }
            } else {
                echo '<p>暂无文章。</p>';
            }
            wp_reset_postdata();
            echo '</div>';
        }
    }
    ?>
  8. Integrate React into WordPress using a custom page template

    To use React within a WordPress page, create a custom PHP page template in your theme directory (e.g., customlist.php). This approach allows you to fetch WordPress data using PHP and pass it directly to a React application as a JSON object, avoiding the need for separate API calls for initial data loading. The template must include the Template Name header to be selectable in the WordPress page editor.
    <?php
    /*
    Template Name: React Categories List
    */
    
    get_header();
    
    // Fetch categories and their associated posts
    $categories = get_categories(array('hide_empty' => false));
    $categories_with_posts = array();
    foreach ($categories as $category) {
        $posts = get_posts(array(
            'category' => $category->term_id,
            'numberposts' => -1,
        ));
        $categories_with_posts[] = array(
            'category' => $category,
            'posts' => $posts,
        );
    }
    
    // Convert data to JSON for JavaScript use
    $categories_with_posts_json = json_encode($categories_with_posts);
    ?>
    
    <div id="app"></div>
    
    <?php get_footer(); ?>
    
    <!-- Load React, ReactDOM, and Babel -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
    
    <script type="text/javascript">
      // Pass PHP data to JS global variable
      const categoriesWithPosts = <?php echo $categories_with_posts_json; ?>;
    </script>
    
    <script type="text/babel">
      // React component logic goes here
      const App = () => {
        return <div>Data from WordPress: {JSON.stringify(categoriesWithPosts)}</div>;
      };
      ReactDOM.render(<App />, document.getElementById('app'));
    </script>
  9. Create a React-powered Categories List page template in WordPress

    To create a dynamic, searchable list of categories and posts using React within WordPress, create a custom page template file (e.g., custom-page.php) in your child theme directory (e.g., astra-child).

    This approach uses PHP to fetch all categories and their associated posts from the WordPress database, encodes that data into JSON, and passes it to a React frontend for rendering. Once the file is created, you can assign this template to any page by selecting 'React Categories List' from the Template dropdown in the WordPress page editor sidebar.

    <?php
    /*
    Template Name: React Categories List
    */
    
    get_header();
    
    // Fetch all categories
    $categories = get_categories(array(
        'hide_empty' => false,
    ));
    
    // Fetch posts for each category
    $categories_with_posts = array();
    foreach ($categories as $category) {
        $posts = get_posts(array(
            'category' => $category->term_id,
            'numberposts' => -1,
        ));
        $categories_with_posts[] = array(
            'category' => $category,
            'posts' => $posts,
        );
    }
    
    // Convert data to JSON for JavaScript use
    $categories_with_posts_json = json_encode($categories_with_posts);
    ?>
    
    <div id="app"></div>
    
    <?php
    get_footer();
    ?>
    
    <!-- Load React, ReactDOM, and Babel -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
    
    <script type="text/javascript">
      const categoriesWithPosts = <?php echo $categories_with_posts_json; ?>;
    </script>
    
    <script type="text/babel">
      const { useState, useEffect } = React;
    
      const CategoryList = ({ categories }) => {
        const [searchTerm, setSearchTerm] = useState('');
        const filteredCategories = categories.filter(categoryData => 
          categoryData.category.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
          categoryData.posts.some(post => post.post_title.toLowerCase().includes(searchTerm.toLowerCase()))
        );
    
        return (
          <div className="categories">
            <input 
              type="text"
              placeholder="Search categories or posts..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="search-input"
            />
            {filteredCategories.map((categoryData, index) => (
              <Category key={index} categoryData={categoryData} />
            ))}
            {filteredCategories.length === 0 && <p>No categories or posts found.</p>}
          </div>
        );
      };
    
      const Category = ({ categoryData }) => {
        const { category, posts } = categoryData;
        const [isExpanded, setIsExpanded] = useState(true);
    
        return (
          <div className="category">
            <h2 onClick={() => setIsExpanded(!isExpanded)}>{category.name}</h2>
            {isExpanded && (
              posts.length > 0 ? (
                <ul>
                  {posts.map(post => (
                    <li key={post.ID}>
                      <a href={post.guid} dangerouslySetInnerHTML={{ __html: post.post_title }}></a>
                    </li>
                  ))}
                </ul>
              ) : (
                <p>No posts available</p>
              )
            )}
          </div>
        );
      };
    
      const App = () => {
        const [categories, setCategories] = useState([]);
        const [loading, setLoading] = useState(true);
    
        useEffect(() => {
          setCategories(categoriesWithPosts);
          setLoading(false);
        }, []);
    
        if (loading) return <p>Loading...</p>;
    
        return (
          <div>
            <h1>All Categories and Posts</h1>
            <CategoryList categories={categories} />
          </div>
        );
      };
    
      ReactDOM.render(<App />, document.getElementById('app'));
    </script>