70 Craft cms利用插件进行数据导出 - xiaoxin01/Blog GitHub Wiki
Craft CMS默认没有提供数据导出功能,既有的一些数据导出插件多多少少都有一些缺陷,本文介绍如何使用插件及sql语句来导出需要的资料
安装支持使用sql query来导出资料的插件,地址在这里:
https://sprout.barrelstrengthdesign.com/craft-plugins/reports
将下载好的内容复制到Craft cms的plugins/sproutreports下,然后在admin管理界面的plugin中安装插件,即可看到Sprout Reports菜单。
点击“Sprout Report”进入Report页面,新建“Custom Query”,然后输入测试内容:
select * from craft_content limit 10;
完成之后点击Report列表页面刚刚创建的Query,即可显示出Query对应的资料。
一般情况下,导出资料的情形分为如下两种:
- 导出某个section的所有资料
- 导出某个entity type的所有资料
相关的数据库表如下:
- craft_sections: 记录所有的section
- craft_entrytypes: 记录所有entry type,其中sectionid栏位为craft_sections的外键
- craft_entries: 记录所有的entry,其中typeid栏位为craft_entrytypes的外键
- craft_content: 记录所有entry栏位的值,其中elementId为craft_entries的外键
- craft_elements_i18n: 记录entry的slug和uri等信息,其中elementId为craft_entries的外键
基于如上的分析,如果想要获取某个entity type的资料,query语句如下:
select
c.locale,
c.title,
c.field_body
from
craft_entrytypes et,
craft_entries e,
craft_content c
where
et.name='entitytype_name'
and e.typeId = et.id
and e.id = c.elementId
想要获取某个section的资料,query语句如下:
select
c.locale,
c.title,
c.field_body
from
craft_sections s,
craft_entrytypes et,
craft_entries e,
craft_content c
where
s.name='section_name'
and e.typeId = et.id
and e.id = c.elementId
and s.id = et.sectionid
上面的query方式,需要根据不同的entity type来列出不同的column来获取资料,这样对于column不同的entity type,都需要手动列举column来导出资料,不是很方便。
- craft_entrytypes的fieldLayoutId栏位记录了其包含的field布局
- craft_fieldlayoutfields的layoutId栏位对应到craft_entrytypes的fieldLayoutId,fieldId为craft_fields的外键
- craft_fields记录了所有栏位信息
获取某个entity type包含的所有栏位的query语句如下:
select et.name, f.name, f.handle from
craft_entrytypes et,
craft_fieldlayoutfields flf,
craft_fields f
where et.name='entitytype_name'
and et.fieldLayoutId = flf.layoutId
and flf.fieldId = f.id
DROP TABLE IF EXISTS execute_report;
SET @fields = (select GROUP_CONCAT(CONCAT('c.field_', t1.handle) SEPARATOR ',')
FROM (select f.handle from
craft_entrytypes et,
craft_fieldlayoutfields flf,
craft_fields f
where et.name='entitytype_name'
and et.fieldLayoutId = flf.layoutId
and flf.fieldId = f.id
and f.`type` not in ('Matrix', 'Assets', 'Entries')) t1);
SET @query_string = CONCAT('Create TEMPORARY table execute_report ', '(select ', @fields,' from
craft_sections s,
craft_entrytypes et,
craft_entries e,
craft_content c
where et.name="entitytype_name"
and e.typeId = et.id
and e.id = c.elementId
and s.id = et.sectionid);');
PREPARE query FROM @query_string;
EXECUTE query;
select * from execute_report;
查看插件获取数据的源码,内容如下:
sproutreports\integrations\sproutreports\datasources\SproutReportsQueryDataSource.php
public function getResults(SproutReports_ReportModel &$report)
{
$query = $report->getOption('query');
try
{
return craft()->db->createCommand($query)->queryAll();
}
catch (\Exception $e)
{
$report->setResultsError($e->getMessage());
}
}
修改为:
public function getResults(SproutReports_ReportModel &$report)
{
$query = $report->getOption('query');
try
{
//return craft()->db->createCommand($query)->queryAll();
if(stristr($query, '#execute#'))
{
$query = str_ireplace('#execute#', '', $query);
craft()->db->createCommand($query)->execute();
return craft()->db->createCommand('select * from execute_report;')->queryAll();
}
else
{
return craft()->db->createCommand($query)->queryAll();
}
}
catch (\Exception $e)
{
$report->setResultsError($e->getMessage());
}
}
如果query语句包含#execute#,则以execute方式执行,否则按默认方式执行。
#execute#
DROP TABLE IF EXISTS execute_report;
SET @fields = (select GROUP_CONCAT(CONCAT('c.field_', t1.handle) SEPARATOR ',')
FROM (select f.handle from
craft_entrytypes et,
craft_fieldlayoutfields flf,
craft_fields f
where et.name='entitytype_name'
and et.fieldLayoutId = flf.layoutId
and flf.fieldId = f.id
and f.`type` not in ('Matrix', 'Assets', 'Entries')) t1);
SET @fields = CONCAT('c.locale, c.title, ', @fields);
SET @query_string = CONCAT('Create TEMPORARY table execute_report ', '(select ', @fields,' from
craft_sections s,
craft_entrytypes et,
craft_entries e,
craft_content c
where et.name="entitytype_name"
and e.typeId = et.id
and e.id = c.elementId
and s.id = et.sectionid);');
PREPARE query FROM @query_string;
EXECUTE query;