ขนาดรูปภาพที่กำหนดเองแต่ละรายการในไดเรกทอรีการอัปโหลดที่กำหนดเอง


11

ฉันต้องการอัพโหลดขนาดภาพที่กำหนดเองของฉันในโฟลเดอร์ที่กำหนดเอง โฟลเดอร์ควรมีชื่อของความกว้างที่เลือก ตัวอย่างเช่น:

หากฉันเพิ่มขนาดที่กำหนดเองเหล่านี้ ...

add_image_size('custom-1', 300, 9999);
add_image_size('custom-2', 400, 9999);

มันคงจะดีนะที่อัพโหลดรูปอัพโหลดแล้ว:

http://www.my-site.com/wp-content/uploads/300/my-image.jpg
http://www.my-site.com/wp-content/uploads/400/my-image.jpg

เป็นไปได้ไหม ฉันเพิ่งพบว่าฉันสามารถเปลี่ยนโฟลเดอร์อัพโหลดทั่วโลกด้วยตัวกรองupload_dir

คำตอบ:


21

ฟิลิปป์เป็นไปได้ทุกอย่างถ้าคุณตั้งใจ คุณสามารถแก้ไขปัญหาของคุณได้โดยขยายคลาสแก้ไขรูปภาพ WordPress

หมายเหตุฉันใช้ WordPress 3.7 - ฉันยังไม่ได้ตรวจสอบรหัสด้านล่างใด ๆ ในเวอร์ชันก่อนหน้านี้และในรุ่นล่าสุด 3.8


ข้อมูลเบื้องต้นเกี่ยวกับโปรแกรมแก้ไขรูปภาพ

WordPress มีสองคลาสในตัวที่จัดการการปรับแต่งภาพ

  • WP_Image_Editor_GD( /wp-includes/class-wp-image-editor-gd.php)
  • WP_Image_Editor_Imagick( /wp-includes/class-wp-image-editor-imagick.php)

ทั้งสองคลาสขยายWP_Image_Editorเนื่องจากทั้งสองใช้เอ็นจิ้นรูปภาพ (GD และ ImageMagick ตามลำดับ) เพื่อโหลดปรับขนาดบีบอัดและบันทึกรูปภาพ

โดยค่าเริ่มต้น WordPress จะพยายามใช้เครื่องมือ ImageMagick ก่อนซึ่งต้องการส่วนขยาย PHP เนื่องจากเป็นที่ต้องการมากกว่าโปรแกรมเอ็นจิ้น GD เริ่มต้นของ PHP เซิร์ฟเวอร์ที่ใช้ร่วมกันส่วนใหญ่ไม่ได้เปิดใช้งานส่วนขยาย ImageMagick


เพิ่มโปรแกรมแก้ไขรูปภาพ

ในการตัดสินใจว่าจะใช้เอ็นจินใด WordPress จะเรียกใช้ฟังก์ชันภายใน__wp_image_editor_choose()(อยู่ใน/wp-includes/media.php) ฟังก์ชั่นนี้วนลูปผ่านเครื่องยนต์ทั้งหมดเพื่อดูว่าเอ็นจิ้นใดสามารถจัดการการร้องขอได้

ฟังก์ชั่นนี้ยังมีตัวกรองที่เรียกwp_image_editorsว่าช่วยให้คุณเพิ่มตัวแก้ไขรูปภาพเพิ่มเติมได้ดังนี้:

add_filter("wp_image_editors", "my_wp_image_editors");
function my_wp_image_editors($editors) {
    array_unshift($editors, "WP_Image_Editor_Custom");

    return $editors;
}

หมายเหตุ: เรากำลังprependingกำหนดเองระดับโปรแกรมแก้ไขภาพของเราWP_Image_Editor_Customเพื่อให้ WordPress จะตรวจสอบว่าเครื่องยนต์ของเราสามารถจัดการกับการปรับขนาดก่อนการทดสอบเครื่องมืออื่น ๆ


สร้างเครื่องมือแก้ไขรูปภาพของเรา

ตอนนี้เรากำลังจะเขียนโปรแกรมแก้ไขภาพของเราเองเพื่อให้เราสามารถตัดสินใจเกี่ยวกับชื่อไฟล์สำหรับตัวเราเอง ชื่อไฟล์ได้รับการจัดการโดยวิธีการWP_Image_Editor::generate_filename()(ทั้งสองโปรแกรมสืบทอดวิธีนี้) ดังนั้นเราควรเขียนทับมันในคลาสที่เรากำหนดเอง

เนื่องจากเราวางแผนที่จะเปลี่ยนชื่อไฟล์เท่านั้นเราควรขยายหนึ่งในเครื่องมือที่มีอยู่เพื่อที่เราจะได้ไม่ต้องคิดค้นล้อใหม่ ฉันจะขยายWP_Image_Editor_GDตัวอย่างของฉันเนื่องจากคุณอาจไม่ได้เปิดใช้งานส่วนขยาย ImageMagick รหัสสามารถใช้แทนกันได้สำหรับการตั้งค่า ImageMagick คุณสามารถเพิ่มทั้งคู่ได้หากคุณวางแผนที่จะใช้ชุดรูปแบบในการตั้งค่าที่แตกต่างกัน

// Include the existing classes first in order to extend them.
require_once ABSPATH.WPINC."/class-wp-image-editor.php";
require_once ABSPATH.WPINC."/class-wp-image-editor-gd.php";

class WP_Image_Editor_Custom extends WP_Image_Editor_GD {
    public function generate_filename($prefix = NULL, $dest_path = NULL, $extension = NULL) {
        // If empty, generate a prefix with the parent method get_suffix().
        if(!$prefix)
            $prefix = $this->get_suffix();

        // Determine extension and directory based on file path.
        $info = pathinfo($this->file);
        $dir  = $info['dirname'];
        $ext  = $info['extension'];

        // Determine image name.
        $name = wp_basename($this->file, ".$ext");

        // Allow extension to be changed via method argument.
        $new_ext = strtolower($extension ? $extension : $ext);

        // Default to $_dest_path if method argument is not set or invalid.
        if(!is_null($dest_path) && $_dest_path = realpath($dest_path))
            $dir = $_dest_path;

        // Return our new prefixed filename.
        return trailingslashit($dir)."{$prefix}/{$name}.{$new_ext}";
    }
}

รหัสข้างต้นส่วนใหญ่ถูกคัดลอกโดยตรงจากWP_Image_Editorชั้นเรียนและแสดงความคิดเห็นเพื่อความสะดวกของคุณ การเปลี่ยนแปลงที่แท้จริงเพียงอย่างเดียวคือคำต่อท้ายเป็นคำนำหน้า

อีกวิธีหนึ่งคุณสามารถโทรparent::generate_filename()และใช้mb_str_replace()เพื่อเปลี่ยนคำต่อท้ายเป็นคำนำหน้า แต่ฉันคิดว่าน่าจะผิดพลาดมากกว่า


การบันทึกเส้นทางใหม่ไปยังเมทาดาทา

หลังจากอัพโหลดimage.jpgแล้วโฟลเดอร์อัพโหลดจะมีลักษณะดังนี้:

  • 2013/12/150x150/image.jpg
  • 2013/12/300x300/image.jpg
  • 2013/12/image.jpg

จนถึงตอนนี้ดีมาก อย่างไรก็ตามเมื่อทำการเรียกฟังก์ชั่นพื้นฐานอย่างเช่นwp_get_attachment_image_src()เราจะสังเกตเห็นขนาดภาพทั้งหมดจะถูกเก็บไว้image.jpgโดยไม่มีเส้นทางไดเรกทอรีใหม่

เราสามารถแก้ไขปัญหานี้ได้โดยการบันทึกโครงสร้างโฟลเดอร์ใหม่ไปยังข้อมูลเมตาของภาพ (ที่จัดเก็บชื่อไฟล์) ข้อมูลที่ไหลผ่านตัวกรองต่างๆ ( wp_generate_attachment_metadataผู้อื่น) ก่อนที่จะถูกใส่เข้าไปในฐานข้อมูล WP_Image_Editor::multi_resize()แต่เนื่องจากเราอยู่แล้วการดำเนินการแก้ไขภาพที่กำหนดเองที่เราสามารถเดินทางกลับไปยังแหล่งข้อมูลเมตาขนาดภาพ: มันสร้างอาร์เรย์แบบนี้:

Array (
    [thumbnail] => Array (
        [file]      => image.jpg
        [width]     => 150
        [height]    => 150
        [mime-type] => image/jpeg
    )

    [medium] => Array (
        [file]      => image.jpg
        [width]     => 300
        [height]    => 300
        [mime-type] => image/jpeg
    )
)

เราจะเขียนทับmulti_resize()วิธีในชั้นเรียนที่กำหนดเองของเรา:

function multi_resize($sizes) {
    $sizes = parent::multi_resize($sizes);

    foreach($sizes as $slug => $data)
        $sizes[$slug]['file'] = $data['width']."x".$data['height']."/".$data['file'];

    return $sizes;
}

อย่างที่คุณเห็นฉันไม่ได้สนใจที่จะแทนที่รหัสใด ๆ ฉันเพิ่งเรียกเมธอด parent และปล่อยให้มันสร้างเมทาดาทา จากนั้นฉันวนลูปผ่านอาร์เรย์ผลลัพธ์และปรับfileค่าสำหรับแต่ละขนาด

ตอนนี้wp_get_attachment_image_src($att_id, array(300, 300))กลับ2013/12/300x300/image.jpgมา ไชโย!


ความคิดสุดท้าย

ฉันหวังว่านี่จะเป็นพื้นฐานที่ดีสำหรับคุณในการทำอย่างละเอียด อย่างไรก็ตามโปรดทราบว่ารูปภาพมีขนาดเล็กกว่าขนาดที่ระบุ (เช่น 280x300) ส่วนต่อท้ายที่สร้างขึ้น (คำนำหน้าในกรณีของเรา) และขนาดภาพเป็น 280x300 ไม่ใช่ 300x300 หากคุณอัปโหลดรูปภาพขนาดเล็กจำนวนมากคุณจะได้รับโฟลเดอร์ต่าง ๆ มากมาย

วิธีการแก้ปัญหาที่ดีที่จะใช้ทั้งกระสุนขนาดเป็นชื่อโฟลเดอร์ ( small, mediumฯลฯ ) หรือขยายรหัสขนาดรอบขึ้นอยู่กับขนาดของภาพที่ต้องการที่อยู่ใกล้ที่สุด

คุณสังเกตเห็นว่าคุณต้องการใช้เพียงความกว้างเป็นชื่อไดเรกทอรี ได้รับการเตือนว่า - ปลั๊กอินหรือธีมสามารถสร้างสองขนาดที่แตกต่างกันที่มีความกว้างเท่ากัน แต่มีความสูงต่างกัน

นอกจากนี้คุณสามารถลบโฟลเดอร์ปี / เดือนได้โดยปิดการใช้งาน 'จัดระเบียบการอัปโหลดของฉันเป็นโฟลเดอร์รายเดือนและรายปี' ภายใต้การตั้งค่า> สื่อหรือโดยการจัดการgenerate_filenameต่อไป

หวังว่านี่จะช่วยได้ โชคดี!


3
คำตอบคืออะไร! : D คนดี!
Philipp Kühn

1
ยินดีต้อนรับคุณ! ฉันสมมติว่าคุณมีประสบการณ์ตัวกรอง OOP และ WP อย่างน้อยสักหน่อย แต่ถ้ามีอะไรที่คุณยังไม่เข้าใจคุณสามารถถามได้ ขอบคุณสำหรับความโปรดปราน!
Robbert

2
@ Robert ตรงไปตรงมานี่มันช่างยอดเยี่ยม ฉันฉีกขาดออกไปเพราะขาดการกระทำและขอตัวกรองในระบบอัพโหลดสื่อ ดูเหมือนจะชัดเจนในการหวนกลับ แต่ก็ไม่ได้เกิดขึ้นกับฉันที่จะแทนที่โปรแกรมแก้ไขภาพทั้งหมด การทำเช่นนี้แก้ปัญหาได้มากมายในคราวเดียว
Jonathan Fingland

1
@ JonathanFingland ฮาฉันยอมรับว่าฉันต้องลงไปที่หลุมกระต่ายสำหรับอันนี้ ดีใจที่ได้รับความช่วยเหลือ!
Robbert

โน้ตเล็ก ๆ - ในความสงบสุขครั้งสุดท้ายของรหัส (ฟังก์ชั่นสาธารณะ multi_resize ($ ขนาด)) คำหลัก "สาธารณะ" ทำให้เว็บไซต์ไม่ทำงาน เพิ่งลบออกและมันก็ขึ้นอีกครั้ง 2k17 และคำตอบของคุณยังยอดเยี่ยมขอขอบคุณ !!
Paradoxetion

3

@ คำตอบของ Robbert เป็นทรัพยากรอันศักดิ์สิทธิ์ในความพยายามของฉันในการจัดเก็บขนาดอื่นที่สร้างโดย WordPress ในไดเรกทอรีที่แยกต่างหาก รหัสของฉันยังเปลี่ยนไดเรกทอรีอัปโหลดเป็น. / สื่อดังนั้นโปรดแก้ไขบรรทัดเหล่านี้หากคุณไม่ต้องการ มันไม่ใช่คำตอบที่ถูกต้องสำหรับคำถามแรกของผู้โพสต์ แต่เสนอทางเลือกในการแก้ปัญหาเดียวกัน:

if ( !is_multisite() ) {
    update_option( 'upload_path', 'media' ); //to-do: add to options page
    define( 'UPLOADS', 'media' ); //define UPLOADS dir - REQUIRED
}
//don't “Organize my uploads into month- and year-based folders”
update_option( 'uploads_use_yearmonth_folders', '0' ); // to-do: add to options page

//create a custom WP_Image_Editor that handles the naming of files
function tect_image_editors($editors) {
    array_unshift( $editors, 'WP_Image_Editor_tect' );

    return $editors;
}

add_filter( 'wp_image_editors', 'tect_image_editors' );

require_once ABSPATH . WPINC . '/class-wp-image-editor.php';
require_once ABSPATH . WPINC . '/class-wp-image-editor-gd.php';

class WP_Image_Editor_tect extends WP_Image_Editor_GD {
    public function multi_resize($sizes) {
        $sizes = parent::multi_resize($sizes);

        $media_dir = trailingslashit( ABSPATH . UPLOADS );

        foreach($sizes as $slug => $data) {
            $default_name = $sizes[ $slug ]['file'];
            $new_name = $slug . '/' . preg_replace( '#-\d+x\d+\.#', '.', $data['file'] );

            if ( !is_dir( $media_dir . $slug ) ) {
                mkdir( $media_dir . $slug );
            }
            //move the thumbnail - perhaps not the smartest way to do it...
            rename ( $media_dir . $default_name, $media_dir . $new_name );

            $sizes[$slug]['file'] = $new_name;
        }

        return $sizes;
    }
}

ทำงานได้โดยไม่มีปัญหาใด ๆ ตามการทดสอบของฉันแม้ว่าฉันจะไม่ได้ลองตรวจสอบว่ามันทำงานอย่างไรกับปลั๊กอินแกลเลอรี่ / สื่อยอดนิยม

โบนัสที่เกี่ยวข้อง: ยูทิลิตี้ดิบเพื่อลบภาพย่อที่สร้างจากเวิร์ดเพรสทั้งหมด delete_deprecated_thumbs.php


1

ฉันดูที่ส่วนของรหัส WordPress และฉันเกรงว่าฉันจะไม่มีข่าวดี

มี 2 ​​คลาส:

  • WP_Image_Editor_GD
  • WP_Image_Editor_Imagick,

ทั้งการขยายWP_Image_Editorชั้นนามธรรม

ชั้นเรียนเหล่านี้ใช้multi_resizeวิธีการซึ่งใช้ในการสร้างภาพหลายภาพจากภาพที่อัปโหลด

ข่าวร้ายจริง ๆ ก็คือไม่มีตะขอตัวกรองอยู่ในนั้นเราสามารถใช้เพื่อปรับเปลี่ยนพา ธ ปลายทางสำหรับไฟล์ที่สร้างขึ้นใหม่


นั่นเป็นความอัปยศ ฉันต้องการใช้Imager.js ที่ดีแต่นั่นอาจจะไม่ทำงานหากไม่มีสิ่งนั้น
Philipp Kühn

ดูเหมือนว่า Imager.js จะทำให้รูปภาพมองไม่เห็นบอต (Google, Facebook และอื่น ๆ ) ดังนั้นฉันจึงแนะนำให้ใช้งานมัน (เว้นแต่คุณจะเพิ่มnoscriptแท็กด้วยตนเอง)
fregante

อืมฉันไม่คิดอย่างนั้น ปกติแล้วคุณจะใช้แท็ก img กับ src ของรูปภาพ และคุณเพิ่มนอกจากนี้ข้อมูลแท็กกับไวยากรณ์ของภาพขนาดอื่น ๆ<img src="http://placehold.it/260" data-src="http://placehold.it/{width}" />: จากนั้นสคริปต์จะตรวจสอบขนาดที่ img มีและโหลดขนาดภาพที่ดีที่สุดสำหรับขนาดนั้น
Philipp Kühn

@ PhilippKühnฉันก็ผิดหวังเหมือนกัน ความคิดของคุณค่อนข้างเรียบร้อยและฉันต้องการใช้มันเพื่อจัดระเบียบไดเรกทอรีอัปโหลด (ลบรูปขนาดย่อที่ไม่ได้ใช้หลังจากการเปลี่ยนชุดรูปแบบเป็นความเจ็บปวดใน ... )
Krzysiek Dróżdż

@ KrzysiekDróżdżเฮ้ฉันคิดว่าฉันเข้าใจแล้ว ดูคำตอบของฉันด้านล่าง ด้วยวิธีนี้คุณยังสามารถจัดเรียงรูปภาพด้วยชื่อไฟล์และลบขนาดรูปภาพที่ไม่ได้ใช้ออกได้อย่างง่ายดาย
Philipp Kühn

1

ตกลงฉันคิดว่าฉันเข้าใจแล้ว! ไม่สมบูรณ์แบบ แต่ก็โอเคสำหรับสิ่งนี้ฉันต้องการมัน สำหรับฉันความกว้างของภาพเป็นสิ่งสำคัญ ความสูงนั้นไร้ประโยชน์สำหรับฉัน โดยเฉพาะอย่างยิ่งสำหรับการนำImager.jsความสูงใน URL ของภาพไปรบกวน

add_filter('image_make_intermediate_size', 'custom_rename_images');

function custom_rename_images($image) {
    // Split the $image path
    $info = pathinfo($image);
    $dir = $info['dirname'] . '/';
    $ext = '.' . $info['extension'];
    $name = wp_basename($image, '$ext');

    // New Name
    $name_prefix = substr($name, 0, strrpos($name, '-'));
    $size_extension = substr($name, strrpos($name, '-') + 1);
    $image_sizes = explode('x', $size_extension);
    $image_width = $image_sizes[0];
    $new_name = $dir . $image_width . '-' . $name_prefix . $ext;

    // Rename the intermediate size
    $did_it = rename($image, $new_name);

    // Return if successful
    if ($did_it) return $new_name;

    // Return on fail
    return $image;
}

ด้วยรหัสนี้ชื่อไฟล์จะเป็นอย่างไร:

http://www.my-site.com/wp-content/uploads/300-my-image.jpg
http://www.my-site.com/wp-content/uploads/400-my-image.jpg

มันเป็นไปไม่ได้ที่จะเพิ่มโฟลเดอร์ย่อยในชื่อไฟล์เพราะถ้าฉันเพิ่มภาพในโพสต์ / หน้าเสมอแหล่งต้นฉบับจะใช้แทน และการลบภาพเหล่านี้เมื่อลบจะไม่ทำงานเช่นกัน ฉันไม่แน่ใจว่าทำไม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.