本文是《WordPress 媒体文件上传开发入门》专题的第 1 篇,共 3 篇:
- WordPress 多媒体上传组件入门
- 通过 WordPress 多媒体上传组件添加和移除图片
- 通过 WordPress 多媒体上传组件保存图片
WordPress 3.5 正式版发布时,最显著的一个变化就是 WordPress 媒体上传功能。对这个变化的更切确地说应该是引入了一个新的多媒体上传组件。
毕竟,旧版本的多媒体上传组件仍然存在并且可以和当前的多媒体库一起运行,但是,它必须通过添加合适的脚本、样式以及其他依赖的功能。
软件的特性和功能总是存在被废弃的时候。在我们的案例中,WordPress的多媒体库也不例外。尽管它不再被WordPress核心使用了,但还是有很多插件和其他第三方工具仍然使用旧版本的多媒体库。
在使用多媒体库时出现了很多份旧版本的功能性代码,这个挑战使得我们很可能不再查找旧的功能例子。
因为新的多媒体库作为 WordPress 新的标准,而且没有很多关于如何使用它的可用的文档,我们将会在接下来的几篇文章中浏览这些功能并且了解新版本的多媒体库是如何架构的,我们如何在自己的工作中实现,我们如何利用已经在WordPress核心中包含的功能。
WordPress多媒体上传组件
新的WordPress多媒体上传组件比旧版本的交互界面有很多优势:
- 支持拖拽
- 更简洁的界面
- 更容易管理的画廊
- 还有更多…
有一点很重要的必须注意,虽然最新的上传组件是采用一套和之前完全不同的技术,这意味着你之前写过的实现多媒体管理的代码仍然是可运行的(直到 Thickbox 被废弃),但是它过时的外观设计将会与当前使用 WordPress 来管理多媒体的用户体验有所不同。
简单介绍Underscore和Backbone
在我们开始把这些加入到我们的代码来创建我们自己的实例前,先来理解下一个新的多媒体库的基础是很重要的。
一如之前提到的,旧版本的多媒体上传组件使用了一个叫做 Thickbox 的库来渲染我们看到的元素,但在最新的实现中,WordPress使用 Underscores(不要和 Underscore 主题混淆了),和 Backbone——这两个 JavaScript 技术一起来驱动用户界面和管理多媒体上传组件的事件。
尽管我们不准备深入了解这些库,但还是有必要去了解它们在多媒体上传组件中的作用。
首先介绍 Backbone:
Backbone.js 给 web 应用持续提供了用于绑定健值对和自定义事件的模型,丰富的集合处理函数,可申明事件处理的视图,还可以使用 RESTfull 风格的 JSON 接口连接到现有的 API 中。
还有 Underscore:
Underscore是一个JavaScript库,提供了一整函数时编程的实用功能,但是没有扩展任何内置对象。如果我面对一个空白的HTML页面,并且想要立即就变成可用的,我需要什么?你可以使用jQuery和Underscore。
很明显,你可以花更多的时间来了解上面的两个内容,但我想要提醒的是现在应该开始我们了解如何管理UI和自定义多媒体库的事件上,我们已经可以做到对下面将要介绍的代码是如何运行的有所认识了。
最后,要记住上面介绍的不是 jQuery。如果你已经使用过这些库——我们现在就是——这两个库是完全分离的。你可以——我们也打算——使用jQuery函数来添加Backbone和Underscore。
整合媒体上传组件
现在,让我们开始真正地写一些代码。
这里给出的例子可以让我们一起看一下如何把一个基本版本的多媒体库加入到一个已经存在的WordPress主题中。我们的这个例子的目的是建立一个插件;然而,我们要使用的环境包含如下:
- WordPress 3.9.2 安装版本
- Twentytwelve 主题
就是这么多了。剩下的代码会包含在我们的插件中。当然,这就提出了一个问题,我们的插件究竟是什么样的
简单来说,我们准备模仿WordPress的“特色图片”功能,我们打算介绍添加在文章的底部的“底部特色图片”,而不是(或者在文章的顶部附近)。
很显然,这个功能并不重要——重点在于实现新的多媒体库。
所有的代码都能在文章关联的GitHub库中找到,你可以像关注文章一样关注这些代码并且把代码下载下来查看。
1. 设置项目目录
在wp-content/plugins目录中,添加一个名为acme-footer-image的目录。我们会把项目的文件放到这里。到此,可以按照下面的介绍添加空文件:
README.txt
LICENSE
acme-footer-image.php
这三个文件从名字上就能理解其作用。acme-footer-image.php是我们准备定义插件头部和开始执行插件的文件。class-acme-footer-image.php这里定义了初始化我们的插件功能的类。
下一步,在插件目录中添加一个名为admin的目录,保存所有管理功能,这个目录应该包含如下内容:
admin/class-admin-footer-image.php
admin/js/admin.js
最后,在admin子目录中添加一个views目录,用来放我们的元素数据框。我们将会在文章的后面学习更多的内容。
为了确保我们能够创建组织良好的文件从而保持职责明确,我们会通过我们的好代码教程来看每个文件。到此,已经有了所有我们可以开始工作需要的东西了。
2. 设置 README
在开始写真正的代码之前,先根据默认的信息来填写README。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | === Acme Footer Image === Contributors: tommcfarlin Donate link: http://tommcfarlin.com/ Tags: featured images Requires at least: 3.9.2 Tested up to: 3.9.2 Stable tag: 0.1.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Append a featured image at the bottom of the content of a post or page. == Description == Append a featured image at the bottom of the content of a post or page. Used as a demo for a Tuts+ Code tutorial. == Installation == This section describes how to install the plugin and get it working. e.g. 1. Upload `plugin-name.php` to the `/wp-content/plugins/` directory 1. Activate the plugin through the 'Plugins' menu in WordPress 1. Place `<?php do_action('plugin_name_hook'); ?>` in your templates == Changelog == = 0.1.0 = * Initial release |
=== Acme Footer Image === Contributors: tommcfarlin Donate link: http://tommcfarlin.com/ Tags: featured images Requires at least: 3.9.2 Tested up to: 3.9.2 Stable tag: 0.1.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Append a featured image at the bottom of the content of a post or page. == Description == Append a featured image at the bottom of the content of a post or page. Used as a demo for a Tuts+ Code tutorial. == Installation == This section describes how to install the plugin and get it working. e.g. 1. Upload `plugin-name.php` to the `/wp-content/plugins/` directory 1. Activate the plugin through the 'Plugins' menu in WordPress 1. Place `<?php do_action('plugin_name_hook'); ?>` in your templates == Changelog == = 0.1.0 = * Initial release
请注意,这里也包含更新日志。
3. 设置插件类
下一步,我们需要定义核心的插件类。该类将会包含如下内容:
- 定义版本号
- 定义类中使用的别名(slug)
- 注册并引入必要的 JavaScript
- 渲染 Meta box
一般来说,我找不到使用面向对象的方式来开发插件的最好方法,因为就像你看到的,这个类里已经包含了不止一个功能。这是缺乏练习;然后,因为这里的代码很短,而且大部分代码都是在通过 JavaScript 来驱动多媒体库,这也是为不得不做的。
让我们从整体上来看一下这个类,并且我们将会仔细地看一些独立的组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | <?php /** * The dashboard-specific functionality of the plugin. * * @link http://tommcfarlin.com * @since 0.1.0 * * @package Acme_Footer_Image * @subpackage Acme_Footer_Image/admin */ /** * The dashboard-specific functionality of the plugin. * * Defines the plugin name, version, the meta box functionality * and the JavaScript for loading the Media Uploader. * * @package Acme_Footer_Image * @subpackage Acme_Footer_Image/admin * @author Tom McFarlin <tom@tommcfarlin.com> */ class Acme_Footer_Image { /** * The ID of this plugin. * * @since 0.1.0 * @access private * @var string $name The ID of this plugin. */ private $name; /** * The current version of the plugin. * * @since 0.1.0 * @access private * @var string $version The version of the plugin */ private $version; /** * Initializes the plugin by defining the properties. * * @since 0.1.0 */ public function __construct() { $this->name = 'acme-footer-image'; $this->version = '0.1.0'; } /** * Defines the hooks that will register and enqueue the JavaScriot * and the meta box that will render the option. * * @since 0.1.0 */ public function run() { add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) ); } /** * Renders the meta box on the post and pages. * * @since 0.1.0 */ public function add_meta_box() { $screens = array( 'post', 'page' ); foreach ( $screens as $screen ) { add_meta_box( $this->name, 'Footer Featured Image', array( $this, 'display_featured_footer_image' ), $screen, 'side' ); } } /** * Registers the JavaScript for handling the media uploader. * * @since 0.1.0 */ public function enqueue_scripts() { wp_enqueue_media(); wp_enqueue_script( $this->name, plugin_dir_url( __FILE__ ) . 'js/admin.js', array( 'jquery' ), $this->version, 'all' ); } /** * Renders the view that displays the contents for the meta box that for triggering * the meta box. * * @param WP_Post $post The post object * @since 0.1.0 */ public function display_featured_footer_image( $post ) { include_once( dirname( __FILE__ ) . '/views/admin.php' ); } } |
<?php /** * The dashboard-specific functionality of the plugin. * * @link http://tommcfarlin.com * @since 0.1.0 * * @package Acme_Footer_Image * @subpackage Acme_Footer_Image/admin */ /** * The dashboard-specific functionality of the plugin. * * Defines the plugin name, version, the meta box functionality * and the JavaScript for loading the Media Uploader. * * @package Acme_Footer_Image * @subpackage Acme_Footer_Image/admin * @author Tom McFarlin <tom@tommcfarlin.com> */ class Acme_Footer_Image { /** * The ID of this plugin. * * @since 0.1.0 * @access private * @var string $name The ID of this plugin. */ private $name; /** * The current version of the plugin. * * @since 0.1.0 * @access private * @var string $version The version of the plugin */ private $version; /** * Initializes the plugin by defining the properties. * * @since 0.1.0 */ public function __construct() { $this->name = 'acme-footer-image'; $this->version = '0.1.0'; } /** * Defines the hooks that will register and enqueue the JavaScriot * and the meta box that will render the option. * * @since 0.1.0 */ public function run() { add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) ); } /** * Renders the meta box on the post and pages. * * @since 0.1.0 */ public function add_meta_box() { $screens = array( 'post', 'page' ); foreach ( $screens as $screen ) { add_meta_box( $this->name, 'Footer Featured Image', array( $this, 'display_featured_footer_image' ), $screen, 'side' ); } } /** * Registers the JavaScript for handling the media uploader. * * @since 0.1.0 */ public function enqueue_scripts() { wp_enqueue_media(); wp_enqueue_script( $this->name, plugin_dir_url( __FILE__ ) . 'js/admin.js', array( 'jquery' ), $this->version, 'all' ); } /** * Renders the view that displays the contents for the meta box that for triggering * the meta box. * * @param WP_Post $post The post object * @since 0.1.0 */ public function display_featured_footer_image( $post ) { include_once( dirname( __FILE__ ) . '/views/admin.php' ); } }
大多数代码都可以根据注释看明白。如果看不懂的话,不要犹豫并且立马在下面留言。让我们一起看看下面的两段代码:
首先,是MetaBox的定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?php public function add_meta_box() { $screens = array( 'post', 'page' ); foreach ( $screens as $screen ) { add_meta_box( $this->name, 'Footer Featured Image', array( $this, 'display_featured_footer_image' ), $screen, 'side' ); } } |
<?php public function add_meta_box() { $screens = array( 'post', 'page' ); foreach ( $screens as $screen ) { add_meta_box( $this->name, 'Footer Featured Image', array( $this, 'display_featured_footer_image' ), $screen, 'side' ); } }
请注意,我们在页面(Page)和文章(post)中都支持 MetaBox。在这个函数中通过引用 display_featured_footer_image 这个回调函数来渲染 MetaBox。
1 2 3 | public function display_featured_footer_image( $post ) { include_once( dirname( __FILE__ ) . '/views/admin.php' ); } |
public function display_featured_footer_image( $post ) { include_once( dirname( __FILE__ ) . '/views/admin.php' ); }
这个文件很简单。这是一个链接,通过JavaScript根据ID来访问。
1 2 3 | <p class="hide-if-no-js"> <a title="Set Footer Image" href="javascript:;" id="set-footer-thumbnail">Set featured image</a> </p> |
<p class="hide-if-no-js"> <a title="Set Footer Image" rel="nofollow noopener noreferrer" href="javascript:;" id="set-footer-thumbnail">Set featured image</a> </p>
并且,我们引入了加载多媒体库需要的JavaScript。
1 2 3 4 5 6 7 8 9 10 11 12 13 | public function enqueue_scripts() { wp_enqueue_media(); wp_enqueue_script( $this->name, plugin_dir_url( __FILE__ ) . 'js/admin.js', array( 'jquery' ), $this->version, 'all' ); } |
public function enqueue_scripts() { wp_enqueue_media(); wp_enqueue_script( $this->name, plugin_dir_url( __FILE__ ) . 'js/admin.js', array( 'jquery' ), $this->version, 'all' ); }
注意这里,我们在引入 JavaScript 之前先调用 wp_enqueue_media。根据官方文档,这个函数:
引入了所有的脚本,样式,设置和使用多媒体 JavaScript APIs 的模板。
为了确保能够正确地加载多媒体上传组件而引入所需要的依赖是必须的。
4. JavaScript
下一步,让我们一起看一下为了确保用户在点击适当的链接后能看到多媒体库而需要写的 JavaScript。
这段代码中的注释有很多,所以应该很容易理解。如果有不理解的地方,请在文章的下面留言反馈。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | /** * Callback function for the 'click' event of the 'Set Footer Image' * anchor in its meta box. * * Displays the media uploader for selecting an image. * * @since 0.1.0 */ function renderMediaUploader() { 'use strict'; var file_frame, image_data; /** * If an instance of file_frame already exists, then we can open it * rather than creating a new instance. */ if ( undefined !== file_frame ) { file_frame.open(); return; } /** * If we're this far, then an instance does not exist, so we need to * create our own. * * Here, use the wp.media library to define the settings of the Media * Uploader. We're opting to use the 'post' frame which is a template * defined in WordPress core and are initializing the file frame * with the 'insert' state. * * We're also not allowing the user to select more than one image. */ file_frame = wp.media.frames.file_frame = wp.media({ frame: 'post', state: 'insert', multiple: false }); /** * Setup an event handler for what to do when an image has been * selected. * * Since we're using the 'view' state when initializing * the file_frame, we need to make sure that the handler is attached * to the insert event. */ file_frame.on( 'insert', function() { /** * We'll cover this in the next version. */ }); // Now display the actual file_frame file_frame.open(); } (function( $ ) { 'use strict'; $(function() { $( '#set-footer-thumbnail' ).on( 'click', function( evt ) { // Stop the anchor's default behavior evt.preventDefault(); // Display the media uploader renderMediaUploader(); }); }); })( jQuery ); |
/** * Callback function for the 'click' event of the 'Set Footer Image' * anchor in its meta box. * * Displays the media uploader for selecting an image. * * @since 0.1.0 */ function renderMediaUploader() { 'use strict'; var file_frame, image_data; /** * If an instance of file_frame already exists, then we can open it * rather than creating a new instance. */ if ( undefined !== file_frame ) { file_frame.open(); return; } /** * If we're this far, then an instance does not exist, so we need to * create our own. * * Here, use the wp.media library to define the settings of the Media * Uploader. We're opting to use the 'post' frame which is a template * defined in WordPress core and are initializing the file frame * with the 'insert' state. * * We're also not allowing the user to select more than one image. */ file_frame = wp.media.frames.file_frame = wp.media({ frame: 'post', state: 'insert', multiple: false }); /** * Setup an event handler for what to do when an image has been * selected. * * Since we're using the 'view' state when initializing * the file_frame, we need to make sure that the handler is attached * to the insert event. */ file_frame.on( 'insert', function() { /** * We'll cover this in the next version. */ }); // Now display the actual file_frame file_frame.open(); } (function( $ ) { 'use strict'; $(function() { $( '#set-footer-thumbnail' ).on( 'click', function( evt ) { // Stop the anchor's default behavior evt.preventDefault(); // Display the media uploader renderMediaUploader(); }); }); })( jQuery );
这里仅仅是显示多媒体库。在上传或者选者图片之后并没有真正地做任何事情。
5. 设置插件核心文件
最后,定义启动插件的文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?php /** * Acme Footer Image * * Append a featured image at the bottom of the content of a post or page. Used as a demo * for a Tuts+ Code tutorial. * * @package Acme_Footer_Image * @author Tom McFarlin <tom@tommcfarlin.com> * @license GPL-2.0+ * @link http://tommcfarlin.com * @copyright 2014 Tom McFarlin * * @wordpress-plugin * Plugin Name: Acme Footer Image * Plugin URI: TODO * Description: Appends a featured image at the bottom of the content of a post or page. * Version: 0.1.0 * Author: Tom McFarlin * Author URI: http://tommcfarlin.com * License: GPL-2.0+ * License URI: http://www.gnu.org/licenses/gpl-2.0.txt */ // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } /** * Includes the core plugin class for executing the plugin. */ require_once( plugin_dir_path( __FILE__ ) . 'admin/class-acme-footer-image.php' ); /** * Begins execution of the plugin. * * Since everything within the plugin is registered via hooks, * then kicking off the plugin from this point in the file does * not affect the page life cycle. * * @since 0.1.0 */ function run_acme_footer_image() { $plugin = new Acme_Footer_Image(); $plugin->run(); } run_acme_footer_image(); |
<?php /** * Acme Footer Image * * Append a featured image at the bottom of the content of a post or page. Used as a demo * for a Tuts+ Code tutorial. * * @package Acme_Footer_Image * @author Tom McFarlin <tom@tommcfarlin.com> * @license GPL-2.0+ * @link http://tommcfarlin.com * @copyright 2014 Tom McFarlin * * @wordpress-plugin * Plugin Name: Acme Footer Image * Plugin URI: TODO * Description: Appends a featured image at the bottom of the content of a post or page. * Version: 0.1.0 * Author: Tom McFarlin * Author URI: http://tommcfarlin.com * License: GPL-2.0+ * License URI: http://www.gnu.org/licenses/gpl-2.0.txt */ // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } /** * Includes the core plugin class for executing the plugin. */ require_once( plugin_dir_path( __FILE__ ) . 'admin/class-acme-footer-image.php' ); /** * Begins execution of the plugin. * * Since everything within the plugin is registered via hooks, * then kicking off the plugin from this point in the file does * not affect the page life cycle. * * @since 0.1.0 */ function run_acme_footer_image() { $plugin = new Acme_Footer_Image(); $plugin->run(); } run_acme_footer_image();
到此,所有的内容都已经是比较熟悉的了:我们需要确保有权限加载该插件,我们包含了仪表盘的依赖、创建了小工具实例。
6. 运行它
这时候,我们在看如何激活插件。在WordPress安装插件的界面上安装后,打开页面(Page)或者文章(Post)。你应该能注意到“底部的特色图片”。然后,当我们点击链接的时候,多媒体库就会出现。
如果没有出现的话,再次检查你的 JavaScript 文件是否已经被正确地加载。
这时候,你可以自由地选择并且上传图片了,尽管什么事情也没发生。在下一篇文章中,我们将会学习如何利用多媒体上传组件获取数据。
总结
在下一篇文章中,我们将会学习如何利用 JavaScript 获取数据并添加到多媒体库中。
另外,我们将会学习如何在多媒体上传组件中使用已有的模板添加扩展属性到WordPress核心中。稍后我们将会学习如何添加更多的信息。
现在,仔细研究一下本文给出的代码,试一试能不能让这些代码在你自己的项目中运行,然后把你的反馈信息留下。
最后,不要忘记你可以从文章 GitHub 库查看代码:https://github.com/tutsplus/acme-footer-image
原文出自:http://code.tutsplus.com/tutorials/getting-started-with-the-wordpress-media-uploader--cms-22011
由 surenpi.com@wordpress大学 原创翻译,未经允许,禁止转载和采用本译文。
到此这篇关于WordPress 多媒体上传组件入门就介绍到这了。若是时间允许,自己还会在哪些地方做得更好等等,只有坚持这样,你才可能有快速的进步。更多相关WordPress 多媒体上传组件入门内容请查看相关栏目,小编编辑不易,再次感谢大家的支持!