カスタムアップロードディレクトリの各カスタム画像サイズ?


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には、画像操作を処理する2つの組み込みクラスがあります。

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

これらの2つのクラスは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;
}

WordPressが他のエンジンをテストする前にエンジンがサイズ変更を処理できるかどうかを確認するために、カスタム画像エディタークラスを先頭に追加していることに注意してくださいWP_Image_Editor_Custom


画像エディターを作成する

次に、独自の画像エディターを作成して、自分でファイル名を決定できるようにします。ファイル名はメソッドによって処理されるためWP_Image_Editor::generate_filename()(両方のエンジンがこのメソッドを継承します)、カスタムクラスでそれを上書きする必要があります。

ファイル名の変更のみを計画しているので、既存のエンジンの1つを拡張して、ホイールを作り直す必要がないようにする必要があります。WP_Image_Editor_GDImageMagick拡張機能を有効にしていない可能性があるため、この例では拡張します。ただし、コードは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と、uploadsフォルダーは次のようになります。

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

ご覧のとおり、私はコードを置き換える必要はありませんでした。親メソッドを呼び出して、メタデータを生成させるだけです。次に、結果の配列をループして、file各サイズの値を調整します。

wp_get_attachment_image_src($att_id, array(300, 300))返します2013/12/300x300/image.jpg。やったー!


最終的な考え

これがあなたが詳しく説明するための良い基礎になったと思います。ただし、画像が指定したサイズ(例:280x300)より小さい場合、生成されるサフィックス(この場合は接頭辞)と画像サイズは300x300ではなく280x300であることに注意してください。小さな画像をたくさんアップロードすると、多くの異なるフォルダが作成されます。

良い解決策は、フォルダ名(ASサイズスラグを使用するかになりsmallmedium、エトセトラ)または最寄りの好適な画像サイズに切り上げサイズにコードを展開します。

幅だけをディレクトリ名として使用したいとおっしゃっていました。ただし、プラグインやテーマは、同じ幅で高さの異なる2つの異なるサイズを生成する可能性があります。

また、[設定]> [メディア]で[アップロードを月ベースおよび年ベースのフォルダーに整理する]を無効にするか、generate_filenameさらに操作して、年/月フォルダーを削除できます。

お役に立てれば。幸運を!


3
なんて答えだ!:Dいい男!
フィリップ・クーン

1
どういたしまして!私はあなたが少なくともOOPとWPフィルターの経験があると想定していましたが、まだ理解していないことがあれば、遠慮なく尋ねてください。賞金をありがとう!
Robbert

2
@ロバート率直に言って、これは素晴らしい。メディアアップロードシステムのアクションフックとフィルターフックの欠如で髪を引きちぎっていました。振り返ってみると明らかなようですが、イメージエディターを完全にオーバーライドすることはできませんでした。そうすることで、一気に多くの問題を解決できます。
Jonathan Fingland 2014

1
@JonathanFinglandハ、私はこれのためにウサギの穴をはるかに下がらなければならなかったことを認めます。お役に立てて嬉しいです!
ロバート14

小さなメモ-コードの最後の平和(public function multi_resize($ sizes))キーワード "public"はウェブサイトをダウンさせます。それを削除するだけで、再び稼働します。2k17そしてあなたの答えはまだ素晴らしいです、ありがとう!!
Paradoxetion 2017年

3

@Robbertの答えは、WordPressによって生成された代替サイズを別のディレクトリに格納するための私の取り組みの神聖なリソースでした。また、私のコードではアップロードディレクトリを./mediaに変更しているので、必要がない場合は必ずこれらの行を編集してください。これは最初の投稿者の質問に対する正確な回答ではありませんが、同じ問題の代替ソリューションを提供します。

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

私のテストによれば、問題なく動作しますが、人気のあるギャラリー/メディアプラグインでどのように動作するかを確認したことはありません。

関連ボーナス:WordPressで生成されたすべてのサムネイルを削除する生のユーティリティ delete_deprecated_thumbs.php


1

WordPressのコードのこれらの部分を見てきましたが、良いニュースはありません。

2つのクラスがあります。

  • WP_Image_Editor_GD
  • WP_Image_Editor_Imagick

どちらも抽象WP_Image_Editorクラスを拡張しています。

これらのクラスはmulti_resizeメソッドを実装しており、アップロードされた画像から複数の画像を生成するために使用されます。

本当に悪いニュースは、そこにフィルターフックがなく、新しく作成されたファイルの宛先パスを変更するために使用できることです。


残念です。素敵なImager.jsを実装したかったのですが、それがないとおそらく機能しません。
PhilippKühn13年

Imager.jsは画像をボット(Google、Facebookなど)から見えなくするようです。そのため、(noscriptタグを手動で追加しない限り)使用しないことをお勧めします
fregante

うーん、そうは思いません。通常、画像のsrcでimg-tagsを使用します。さらに、他の画像サイズの構文を使用してデータタグを追加します<img src="http://placehold.it/260" data-src="http://placehold.it/{width}" />。次に、スクリプトはimgのサイズをチェックし、それに最適な画像サイズをロードします。
PhilippKühn13年

@PhilippKühn私もがっかりです。あなたのアイデアはかなりきちんとしていて、アップロードディレクトリを整理するためにそれを使いたかったです(テーマの変更後に未使用のサムネイルを削除するのは
面倒

@KrzysiekDróżdżねえ、わかったよ 以下の私の答えを見てください。このソリューションを使用すると、FTPを介して画像をファイル名でソートし、未使用の画像サイズを簡単に削除することもできます。
PhilippKü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.