Mỗi kích thước hình ảnh tùy chỉnh trong thư mục tải lên tùy chỉnh?


11

Tôi muốn tải lên kích thước hình ảnh tùy chỉnh của mình trong các thư mục tùy chỉnh. Thư mục nên có tên của chiều rộng đã chọn. Ví dụ:

Nếu tôi thêm các kích cỡ tùy chỉnh này ...

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

Sẽ thật tuyệt khi những hình ảnh được tải lên được tải lên như thế này:

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

Điều này có thể không? Tôi chỉ thấy rằng tôi có thể thay đổi thư mục tải lên toàn cầu bằng bộ lọc upload_dir .

Câu trả lời:


21

Philipp, bất cứ điều gì là có thể nếu bạn đặt tâm trí của bạn với nó. Bạn có thể giải quyết vấn đề của mình bằng cách mở rộng lớp trình chỉnh sửa hình ảnh WordPress.

Lưu ý Tôi đang sử dụng WordPress 3.7 - Tôi chưa kiểm tra bất kỳ mã nào dưới đây trong các phiên bản trước và trong phiên bản 3.8 mới nhất.


Khái niệm cơ bản về chỉnh sửa ảnh

WordPress có hai lớp được xây dựng để xử lý thao tác hình ảnh:

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

Hai lớp này mở rộng WP_Image_Editorvì cả hai đều sử dụng một công cụ hình ảnh khác nhau (tương ứng GD và ImageMagick) để tải, thay đổi kích thước, nén và lưu hình ảnh.

Theo mặc định, WordPress sẽ cố gắng sử dụng công cụ ImageMagick trước tiên, nó cần một phần mở rộng PHP, bởi vì nó thường được ưa thích hơn công cụ GD mặc định của PHP. Hầu hết các máy chủ được chia sẻ không bật tiện ích mở rộng ImageMagick.


Thêm trình chỉnh sửa hình ảnh

Để quyết định sử dụng công cụ nào, WordPress gọi một chức năng nội bộ __wp_image_editor_choose()(nằm trong/wp-includes/media.php ). Hàm này lặp qua tất cả các động cơ để xem động cơ nào có thể xử lý yêu cầu.

Hàm này cũng có một bộ lọc được gọi là wp_image_editorscho phép bạn thêm nhiều trình chỉnh sửa hình ảnh như vậy:

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

    return $editors;
}

Lưu ý chúng ta thêm vào trước lớp biên tập hình ảnh tùy chỉnh của chúng tôi WP_Image_Editor_Customđể WordPress sẽ kiểm tra xem động cơ của chúng tôi có thể xử lý thay đổi kích thước trước khi thử nghiệm động cơ khác.


Tạo Trình chỉnh sửa hình ảnh của chúng tôi

Bây giờ chúng tôi sẽ viết trình chỉnh sửa hình ảnh của riêng mình để chúng tôi có thể quyết định tên tệp cho chính mình. Filenaming được xử lý bằng phương thức WP_Image_Editor::generate_filename()(cả hai công cụ đều kế thừa phương thức này), vì vậy chúng ta nên ghi đè lên nó trong lớp tùy chỉnh của chúng ta.

Vì chúng tôi chỉ có kế hoạch thay đổi tên tệp, chúng tôi nên mở rộng một trong các công cụ hiện có để chúng tôi không phải phát minh lại bánh xe. Tôi sẽ mở rộng WP_Image_Editor_GDtrong ví dụ của mình, vì có lẽ bạn không bật tiện ích mở rộng ImageMagick. Mã có thể hoán đổi cho một thiết lập ImageMagick. Bạn có thể thêm cả hai nếu bạn dự định sử dụng chủ đề trên các thiết lập khác nhau.

// 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}";
    }
}

Hầu hết các mã ở trên được sao chép trực tiếp từ WP_Image_Editorlớp và nhận xét để thuận tiện cho bạn. Thay đổi thực tế duy nhất là hậu tố bây giờ là tiền tố.

Ngoài ra, bạn chỉ có thể gọi parent::generate_filename()và sử dụng một mb_str_replace()để thay đổi hậu tố thành tiền tố, nhưng tôi đoán rằng sẽ có xu hướng sai hơn.


Lưu đường dẫn mới vào siêu dữ liệu

Sau khi tải lên image.jpg, thư mục tải lên trông như thế này:

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

Càng xa càng tốt. Tuy nhiên, khi gọi các chức năng cơ bản như wp_get_attachment_image_src(), chúng tôi sẽ nhận thấy tất cả các kích thước hình ảnh được lưu trữ image.jpgmà không có đường dẫn thư mục mới.

Chúng ta có thể giải quyết vấn đề này bằng cách lưu cấu trúc thư mục mới vào siêu dữ liệu hình ảnh (nơi tên tệp được lưu trữ). Dữ liệu chạy qua các bộ lọc khác nhau ( wp_generate_attachment_metadatatrong số các bộ lọc khác) trước khi được chèn vào cơ sở dữ liệu, nhưng vì chúng tôi đã triển khai trình chỉnh sửa hình ảnh tùy chỉnh, chúng tôi có thể quay lại nguồn siêu dữ liệu kích thước hình ảnh : WP_Image_Editor::multi_resize(). Nó tạo ra các mảng như thế này:

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
    )
)

Chúng tôi sẽ ghi đè multi_resize()phương thức trong lớp tùy chỉnh của chúng tôi:

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;
}

Như bạn có thể thấy, tôi không buồn thay thế bất kỳ mã nào. Tôi chỉ gọi phương thức cha và để nó tạo siêu dữ liệu. Sau đó, tôi lặp qua mảng kết quả và điều chỉnh filegiá trị cho từng kích thước.

Bây giờ wp_get_attachment_image_src($att_id, array(300, 300))trở lại 2013/12/300x300/image.jpg. Hoan hô!


Suy nghĩ cuối cùng

Tôi hy vọng điều này cung cấp một cơ sở tốt để bạn giải thích. Tuy nhiên, xin lưu ý nếu một hình ảnh nhỏ hơn kích thước được chỉ định (ví dụ 280x300), hậu tố được tạo (tiền tố trong trường hợp của chúng tôi) và kích thước hình ảnh là 280x300, không phải 300x300. Nếu bạn tải lên nhiều hình ảnh nhỏ hơn, bạn sẽ nhận được rất nhiều thư mục khác nhau.

Một giải pháp tốt là sử dụng sên kích thước làm tên thư mục ( small,medium , vân vân) hoặc mở rộng mã để kích thước vòng lên đến kích thước hình ảnh ưa thích gần nhất.

Bạn lưu ý rằng bạn chỉ muốn sử dụng chiều rộng làm tên thư mục. Mặc dù được cảnh báo - các plugin hoặc chủ đề có thể tạo ra hai kích thước khác nhau với cùng chiều rộng nhưng chiều cao khác nhau.

Ngoài ra, bạn có thể xóa các thư mục năm / tháng bằng cách vô hiệu hóa 'Sắp xếp tải lên của tôi vào các thư mục dựa trên tháng và năm' trong Cài đặt> Phương tiện hoặc bằng cách thao tác generate_filename hơn nữa.

Hi vọng điêu nay co ich. Chúc may mắn!


3
Thật là một câu trả lời! : D Người đàn ông tốt bụng!
Philipp Kühn

1
Không có gì! Tôi đã giả sử rằng bạn có ít nhất một chút kinh nghiệm về bộ lọc OOP và WP, nhưng nếu có bất cứ điều gì bạn chưa hiểu, hãy hỏi. Cảm ơn bạn cho tiền thưởng!
Robbert

2
@Robbert Thành thật mà nói, điều này thật tuyệt vời. Tôi đã xé tóc vì thiếu hành động và bộ lọc móc trong hệ thống tải lên phương tiện truyền thông. Nó có vẻ rõ ràng khi nhìn lại, nhưng nó đơn giản đã không xảy ra với tôi để ghi đè hoàn toàn các trình chỉnh sửa hình ảnh. Làm như vậy giải quyết rất nhiều vấn đề trong một cú trượt ngã.
Jonathan Fingerland

1
@JonathanFingland Ha, tôi thừa nhận tôi đã phải đi sâu xuống hố thỏ cho cái này. Vinh dự khi được giup bạn!
Robbert

Lưu ý nhỏ - trong mã cuối cùng (mã công khai multi_resize ($ size)) từ khóa "công khai" làm cho trang web không hoạt động. Chỉ cần loại bỏ nó và nó lên một lần nữa. 2k17 và câu trả lời của bạn vẫn rất tuyệt vời, cảm ơn bạn !!
Nghịch lý

3

Câu trả lời của @ Robbert là một nguồn tài nguyên thiêng liêng trong nỗ lực của tôi để lưu trữ các kích thước thay thế được tạo bởi WordPress trong các thư mục riêng biệt. Mã của tôi cũng thay đổi thư mục tải lên thành ./media, vì vậy hãy đảm bảo chỉnh sửa các dòng này nếu bạn không muốn điều đó. Đây không phải là một câu trả lời chính xác cho câu hỏi đầu tiên của người đăng, nhưng đưa ra một giải pháp thay thế cho cùng một vấn đề:

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;
    }
}

Hoạt động mà không có bất kỳ vấn đề nào theo các thử nghiệm của tôi, mặc dù tôi đã không thử kiểm tra xem giá vé như thế nào với các plugin bộ sưu tập / phương tiện phổ biến.

phần thưởng liên quan: một tiện ích thô để xóa tất cả các hình thu nhỏ được tạo bởi WordPress remove_deprecated_thumbs.php


1

Tôi đã xem các phần này của mã WordPress và tôi sợ rằng tôi không có tin tốt nào.

Có 2 lớp:

  • WP_Image_Editor_GD
  • WP_Image_Editor_Imagick,

cả mở rộng WP_Image_Editorlớp trừu tượng .

Các lớp này đang thực hiện multi_resizephương thức, được sử dụng để tạo nhiều ảnh từ một tệp đã tải lên.

Tin xấu thực sự là không có móc lọc trong đó, chúng ta có thể sử dụng để sửa đổi đường dẫn đích cho các tệp mới được tạo.


Thật là xấu hổ. Tôi muốn triển khai Imager.js đẹp nhưng điều đó có thể sẽ không hoạt động nếu không có điều đó.
Philipp Kühn

Có vẻ như Imager.js làm cho hình ảnh trở nên vô hình đối với bot (Google, Facebook, v.v.), do đó tôi khuyên bạn không nên sử dụng nó (trừ khi bạn cũng tự thêm noscriptthẻ)
fregante

Hmm không tôi không nghĩ vậy. Bạn thường sử dụng thẻ img với src hình ảnh. Và bạn thêm một thẻ dữ liệu với cú pháp của các kích cỡ hình ảnh khác : <img src="http://placehold.it/260" data-src="http://placehold.it/{width}" />. Và sau đó tập lệnh kiểm tra kích thước của img và tải kích thước hình ảnh tốt nhất cho điều đó.
Philipp Kühn

@ PhilippKühn Tôi cũng thất vọng. Ý tưởng của bạn khá gọn gàng và tôi muốn sử dụng nó để dọn dẹp thư mục tải lên (xóa các hình thu nhỏ không sử dụng sau khi thay đổi chủ đề là nỗi đau trong ...)
Krzysiek Dróżdż

@ KrzysiekDróżdż Này, tôi nghĩ rằng tôi đã nhận được nó. Nhìn vào câu trả lời của tôi dưới đây. Với giải pháp này, bạn cũng có thể sắp xếp qua ftp hình ảnh theo tên tệp và dễ dàng loại bỏ các kích thước hình ảnh không sử dụng.
Philipp Kühn

1

Ok, tôi nghĩ rằng tôi đã nhận nó! Không hoàn hảo nhưng không sao cho điều này tôi muốn nó cho. Đối với tôi chỉ có chiều rộng của một hình ảnh là quan trọng. Chiều cao là vô dụng đối với tôi. Đặc biệt là để triển khai Imager.js , chiều cao trong url hình ảnh là đáng lo ngại.

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;
}

Với mã này, tên tệp giống như:

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

Đó là không thể thêm một thư mục con với tên tập tin, vì nếu tôi thêm hình ảnh trong một bài / trang lúc nào cũng là nguồn gốc sẽ sử dụng để thay thế. Và xóa những hình ảnh này khi xóa cũng sẽ không hoạt động. Tôi cung không chăc tại sao.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.