数据导出:定制数据库表

WBOY
发布: 2023-09-02 18:02:01
原创
802 人浏览过
<p><img src="https://img.php.cn/upload/article/000/887/227/169364887365792.jpg" alt="数据导出:定制数据库表"></p> <p>正如本系列的第一篇文章中提到的,自定义数据库表的主要问题之一是它们不由现有的导入和导出处理程序处理。本文旨在解决这个问题,但应该指出的是,目前还没有完全令人满意的解决方案。</p> <p>让我们考虑两种情况:</p> <ol> <li>自定义表格引用本机 WordPress 表格</li> <li>自定义表格完全独立于原生表格</li> </ol> <p>“最坏情况”是第一种情况。以保存用户活动日志的自定义表为例。它引用用户 ID、对象 ID 和对象类型 - 所有这些都引用存储在本机 WordPress 表中的数据。现在想象一下,有人想要将其 WordPress 网站中的所有数据导入到第二个网站中。例如,完全有可能在导入帖子时,WordPress 必须为其分配一个新的 ID,因为第二个站点中可能已经存在具有该 ID 的帖子。</p> <p>在这种情况下,有必要跟踪此类更改并更新表中引用的 ID。这本身并不那么困难。 <em>不幸的是</em>,用于处理从其他 WordPress 站点导入数据的 WordPress Importer 插件缺乏必要的挂钩来实现这一点。正如此评论中所建议的,一种潜在的解决方法是将数据也存储在后元中。不幸的是,这会导致重复数据,并且违背数据库规范化——通常不是一个好主意。最后,它仅在少数用例中真正可行。</p> <p>第二种情况避免了这种复杂性,但仍然需要自定义导入和导出处理程序。我们将在接下来的两篇文章中演示这种情况。但是,为了与本系列的其余部分保持一致,我们将坚持使用活动日志表,即使它是情况 (1) 的示例。</p> <hr> <h2>决定格式</h2> <p>首先我们需要决定导出文件采用的格式。最佳格式取决于数据的性质(或“结构”)及其使用方式。在我看来,XML 通常更好,因为它可以处理一对多关系。然而,有时如果数据是表格形式,那么 CSV 可能更可取,特别是因为它易于与电子表格应用程序集成。在此示例中,我们将使用 XML。</p> <hr> <h2>加价</h2> <p>下一步是创建一个管理页面,以允许用户导出日志表中的数据。我们将创建一个类,该类将在“工具”菜单项下方添加一个页面。该页面仅包含一个按钮,提示用户下载导出文件。该类还将添加一个处理程序来侦听表单提交并触发文件下载。</p> <p>首先让我们看一下类的结构,然后再填写其方法的详细信息。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbal:false;">class WPTuts_Log_Export_Admin_Page{ /** * The page hook suffix */ static $hook_suffix=''; static function load(){ add_action('admin_menu', array(__CLASS__,'add_submenu')); add_action('admin_init', array(__CLASS__,'maybe_download')); } static function add_submenu(){} static function maybe_download(){} static function display(){} } WPTuts_Log_Export_Admin_Page::load(); </pre><div class="contentsignin">登录后复制</div></div> <p><code>WPTuts_Log_Export_Admin_Page::load()</code> 初始化类并将回调挂钩到适当的操作:</p> <ul> <li> <code>add_submenu</code> – 负责在“工具”菜单下添加页面的方法。</li> <li> <code>maybe_download</code> – 此方法将监听检查是否已提交下载请求。这还将检查权限和随机数。 </li> </ul> <p>需要在发送任何标头之前尽早调用导出侦听器,因为我们将自己设置这些标头。我们可以将其挂接到 <code>init</code> 上,但由于我们只允许在管理中下载导出文件,因此 <code>admin_init</code> 在这里更合适。</p> <p>向菜单添加页面非常简单。要在“工具”下添加页面,我们只需调用 <code>add_management_page()</code>。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbal:false;">static function add_submenu(){ self::$hook_suffix = add_management_page( __('Export Logs','wptuts-log'), __('Export Logs','wptuts-log'), 'manage_options', 'wptuts-export', array(__CLASS__,'display') ); } </pre><div class="contentsignin">登录后复制</div></div> <p>这里的 <code>$hook_suffix</code> 是用于各种屏幕特定钩子的后缀,这里讨论。我们在这里不使用它 - 但如果您使用它,最好将其值存储在变量中,而不是对其进行硬编码。</p> <p>在上面我们将方法 <code>display()</code> 设置为我们页面的回调,接下来我们定义它:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbal:false;">static function display(){ echo '&lt;div class=&quot;wrap&quot;&gt;'; screen_icon(); echo '&lt;h2&gt;' . __( 'Export Activity Logs', 'wptuts-log' ) . '&lt;/h2&gt;'; ?&gt; &lt;form id=&quot;wptuts-export-log-form&quot; method=&quot;post&quot; action=&quot;&quot;&gt; &lt;p&gt; &lt;label&gt;&lt;?php _e( 'Click to export the activity logs','wptuts-log' ); ?&gt;&lt;/label&gt; &lt;input type=&quot;hidden&quot; name=&quot;action&quot; value=&quot;export-logs&quot; /&gt; &lt;/p&gt; &lt;?php wp_nonce_field('wptuts-export-logs','_wplnonce') ;?&gt; &lt;?php submit_button( __('Download Activity Logs','wptuts-log'), 'button' ); ?&gt; &lt;/form&gt; &lt;?php } </pre><div class="contentsignin">登录后复制</div></div> <p>最后,我们希望监听上述表单何时提交并触发导出文件下载。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbal:false;">static function maybe_download(){ /* Listen for form submission */ if( empty($_POST['action']) || 'export-logs' !== $_POST['action'] ) return; /* Check permissions and nonces */ if( !current_user_can('manage_options') ) wp_die(''); check_admin_referer( 'wptuts-export-logs','_wplnonce'); /* Trigger download */ wptuts_export_logs(); } </pre><div class="contentsignin">登录后复制</div></div> <p>剩下的就是创建函数 <code>wptuts_export_logs()</code> 来创建并返回我们的 .xml 文件。</p> <hr> <h2>创建导出文件</h2> <p>我们希望函数做的第一件事是检索日志。如果有的话,我们需要设置适当的标头并以 XML 格式打印它们。由于我们希望用户下载 XML 文件,因此我们将 Content-Type 设置为 <code>text/xml</code>,将 Content-Description 设置为 <code>File Transfer</code>。我们还将为下载文件生成合适的名称。最后,我们将添加一些注释 - 这些完全是可选的,但有助于指导用户如何处理下载的文件。</p> <p>由于在本系列的前一部分中,我们为表创建了 API,因此我们的导出处理程序不需要直接接触数据库 - 也不需要清理 <code>$args</code> 数组,因为这是由 <code> 处理的wptuts_get_logs()</code>。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbal:false;">function wptuts_export_logs( $args = array() ) { /* Query logs */ $logs = wptuts_get_logs($args); /* If there are no logs - abort */ if( !$logs ) return false; /* Create a file name */ $sitename = sanitize_key( get_bloginfo( 'name' ) ); if ( ! empty($sitename) ) $sitename .= '.'; $filename = $sitename . 'wptuts-logs.' . date( 'Y-m-d' ) . '.xml'; /* Print header */ header( 'Content-Description: File Transfer' ); header( 'Content-Disposition: attachment; filename=' . $filename ); header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true ); /* Print comments */ echo &quot;&lt;!-- This is a export of the wptuts log table --&gt;\n&quot;; echo &quot;&lt;!-- (Demonstration purposes only) --&gt;\n&quot;; echo &quot;&lt;!-- (Optional) Included import steps here... --&gt;\n&quot;; /* Print the logs */ } </pre><div class="contentsignin">登录后复制</div></div> <p>您会注意到,我们已将实际查询数组作为参数传递给 <code>wptuts_export_logs()</code> 函数。我们可以对此进行硬编码,但不这样做也是有道理的。虽然这里的目的只是导出表中的<em>所有内容</em>,但将查询作为参数传递允许我们稍后添加在特定时间范围内或针对特定用户导出日志的选项。</ p> <p>创建 XML 文件时,我们需要确保标签之间打印的值不包含字符 <code>&</code>、<code><</code> 或 <code>></code>。为了确保这一点,对于 ID,我们使用 <code>absint</code> 清理数据,并使用 <code>sanitize_key</code> 清理对象类型和活动(因为我们希望这些仅包含小写字母数字、下划线和连字符)。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbal:false;">/* Print logs to file */ echo '&lt;logs&gt;'; foreach ( $logs as $log ) { ?&gt; &lt;item&gt; &lt;log_id&gt;&lt;?php echo absint($log-&gt;log_id); ?&gt;&lt;/log_id&gt; &lt;activity_date&gt;&lt;?php echo mysql2date( 'Y-m-d H:i:s', $log-&gt;activity_date, false ); ?&gt;&lt;/activity_date&gt; &lt;user_id&gt;&lt;?php echo absint($log-&gt;user_id); ?&gt;&lt;/user_id&gt; &lt;object_id&gt;&lt;?php echo absint($log-&gt;object_id); ?&gt;&lt;/object_id&gt; &lt;object_type&gt;&lt;?php echo sanitize_key($log-&gt;object_type); ?&gt;&lt;/object_type&gt; &lt;activity&gt;&lt;?php echo sanitize_key($log-&gt;activity); ?&gt;&lt;/activity&gt; &lt;/item&gt; &lt;?php } echo '&lt;/logs&gt;'; </pre><div class="contentsignin">登录后复制</div></div> <p>更一般地,您可以使用以下函数将要打印的值包装在 <code>CDATA</code> 标记内来清理它们:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbal:false;">/** * Wraps the passed string in a XML CDATA tag. * * @param string $string String to wrap in a XML CDATA tag. * @return string */ function wptuts_wrap_cdata( $string ) { if ( seems_utf8( $string ) == false ) $string = utf8_encode( $string ); return '&lt;![CDATA[' . str_replace( ']]&gt;', ']]]]&gt;&lt;![CDATA[&gt;', $string ) . ']]&gt;'; } </pre><div class="contentsignin">登录后复制</div></div> <p>最后我们 <code>exit()</code> 以防止任何进一步的处理:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbal:false;"> /* Finished - now exit */ exit(); </pre><div class="contentsignin">登录后复制</div></div> <p>导航到我们的导出页面,单击“下载活动日志”应提示下载 XML 文件。</p> <hr> <h2>摘要</h2> <p>在本教程中,我们研究了从自定义表中导出数据。不幸的是,当数据引用本机 WordPress 表时,这充其量是有问题的。上述方法仅适用于数据无法做到这一点的情况。使用的示例(我们的活动日志)显然不属于此类,只是为了与本系列的其余部分保持一致而使用。</p> <p>当数据<em>确实</em>引用本机表时,显然有必要将其与本机表一起导入,并在此过程中跟踪导入期间发生的 ID 任何更改。目前,现有的导入和导出处理程序无法实现这一点,因此唯一可行的选择是创建自己的处理程序。在自定义数据仅引用单个帖子类型的简单情况下,可以设计导入和导出处理程序来处理该帖子类型以及自定义数据,并通知用户不要使用该帖子类型的本机导出器。 </p> <p>在本系列的下一部分中,我们将为导出的 .xml 文件创建一个简单的导入处理程序。</p>

以上是数据导出:定制数据库表的详细内容。更多信息请关注PHP中文网其他相关文章!

相关标签:
来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板