問題描述
我一直試圖讓這個工作達一年多,並嘗試了許多方法,並沒有得到它的工作。如果有人可以幫助我,我真的很感激。這是我要做的事情
我需要為我的自定義帖子型別為幻燈片 (lom_slideshow) 建立 15 個自定義 metaboxes 用於寫入螢幕。除了滑塊的數量 (例如幻燈片 1,幻燈片 2 …),每個 metabox 將是相同的。我想讓 metaboxes 將每個欄位儲存到單獨的自定義欄位中。
以下是每個 metabox 中需要的欄位:
-
數字/文字欄位
-
標題:幻燈片編號
-
自定義欄位鍵:slide1-number
-
-
核取方塊
-
標題:隱藏此幻燈片
-
自定義欄位鍵:slide1-hide
-
-
無線電切換
-
標題:幻燈片型別
-
自定義欄位鍵:slide1-slidesetype
-
值:影像幻燈片或影片幻燈片
-
-
文字域
-
標題:幻燈片標題
-
自定義欄位鍵:slide1-title
-
-
影像 (這個可以工作幾種方式,我不太在乎它如何工作,只要它)
-
標題:幻燈片圖片
-
自定義欄位鍵:slide1-image
-
它將如何運作:只要它做以下一件事我會很開心…
-
A) 與該帖子相關聯的所有影像附件的下拉式清單。
-
B) 與該帖子相關聯的所有附加影像的縮圖列表。
-
C) 影像上傳欄位上傳影像並將其附加到帖子。
-
-
所見即所得
-
標題:幻燈片說明
-
自定義欄位鍵:slide1-desc
-
型別:wysiwyg
-
-
多行文字
-
標題:影片嵌入程式碼
-
自定義欄位鍵:slide1-embed
-
幻燈片 2 將是一樣的,但所有的自定義欄位值將附加”slide2-“ 而不是”slide1-“
唯一的其他考慮是,我希望他們在主要內容列,只有在我的幻燈片自定義帖子型別 (lom_slideshow) 上可見。
就像我說的,我已經嘗試了這麼多時間,從來沒有這樣做。我過去已經很近了,並且已經得到了整個事情的工作,除非我看不到所見即所得的多個例項顯示在頁面上。我不再有程式碼,因為我從那以後改變了很多次。我最終決定使用更多欄位外掛來做這個而不是我自己的程式碼,並用 5 個元框進行開發測試,但是當我嘗試使用 15 個框來實現它時,我需要外掛在我的資料庫表上造成嚴重破壞。我真的不想要另外一個外掛。
我實際上正在尋找一個人來告訴我如何編寫程式碼。我不需要連結到教程,因為我有信心我已經嘗試了所有,除非在最後一個小時左右釋出。
對於這裡的一些背景,我原本想做的是:Help Creating a Slideshow Custom Post Type with Custom Meta Boxes?
EAMann 為我提供了一個非常全面的答案,但這是我的技能之外,我無法實現。我已經簡化了我在這個問題上的請求,希望能夠最終完成這個。
最佳解決方案
解決一個複雜的問題 (理性地)
為瞭解決複雜的問題,有一種標準化/眾所周知的方法:將你的複雜問題分解成一套較小的問題。較小的問題更容易解決。如果您已經解決了每個較小的問題,那麼您最經常已經解決了您的複雜問題。
找到並分割成零件
到目前為止的理論。我們來檢查你的需要。我用自己的話說 line-up 你上面描述的內容:
-
在多個例項 (Slide-1 到 slide-N) 中處理一組選項。
-
在後期元值中儲存值。
-
多個例項中的 Metabox(Slide-1 至 slide-N) 。
-
Metabox 內的幻燈片編輯器 (Form)(再次是多個例項)
-
編輯資料的基本格式 (例如使用簡單的 HTML 表單元素)
-
要解決的技術問題,有多個 WYSIWYG 編輯。
-
您更復雜的影像輸入。
那麼怎麼編碼呢?我認為最重要的部分是,在開始實際編碼之前,你會想起你真正想要實現的內容,以及如何將問題分成較小的部分。上面的列表可能不完整,這只是我從你的問題中可以看到的。而格式是非常特別的。它或多或少是從你寫的重複,但有點訂單到單點。
所以檢查這些是否是您的需求,並將該列表擴充套件到您認為合適的所有內容。
完成後,下一步是看看這些需要的東西可以用簡單的單詞和外掛的功能列表來表達
-
一個外掛:SlideshowPlugin 。
-
幻燈片由幻燈片組成。
-
編輯幻燈片的編輯器。
-
儲存和檢索幻燈片資料的地方。
看起來很簡單,對吧?我可能會錯過這裡的東西,所以在繼續之前先仔細檢查一下。正如寫的,開始編寫之前,只需用簡單的措辭和術語來彌補你的想法。甚至不要考慮哪些部分是有問題的,哪些部分不是或如何編寫一些細節,如 HTML Input 元素的命名。我知道如果你已經嘗試了很長時間,從頭開始重新啟動,這是很難的,因為你腦海裡有許多想法再次出現。
拿鉛筆和一些紙。這通常有助於彌補某人的心靈。
你可以看到我沒有在這裡指定 Metabox 或 Custom Post Type 的需要。首先了解您的問題的部分太具體了。 Metabox 或 Custom Post Type 非常具體,可能是如何編寫外掛的。所以我暫時停下來,試圖縮短但正確地描述需求。 Metabox 或類似的東西可能在設計中發揮作用。讓我們來看看。
設計你的外掛
在你知道你需要/想要實現的之後,你可以想出如何設計這個外掛。這可以透過繪製一點圖片來完成。只需從功能列表中識別零件,並將它們相互關聯。你可以看到,實際上不需要做美術;):
不好意思,我希望這可以讀。無論如何,您可以建立自己的影像,這只是一個例子。設計可以有所不同,所以如果你不會以同樣的方式繪製,那就是正常的。
我喜歡在紙上開始設計步驟,因為它有助於從上面更好地瞭解問題,並且在電腦上的紙張上快得多。
因此,現在您可以將您的列表與您的設計進行比較,並檢查列表中的所有功能是否涵蓋在設計中的部件。看起來好像我的清單和我的形象,所以我繼續,但不要跳過這一步。否則你不知道你是否錯過了一些東西。隨著你開始編寫程式碼,改變一些已經被編碼的東西比影像或列表要困難得多。
分離設計中的問題
現在這個外掛變得更具體了。經過一些小的設計,可能是開始編碼的正確時機。由於我們有上面的列表,我可以透過設計瞭解每一個點,並且設計 cross-check,以便我知道這些零件是如何相互關聯的。
因為如果每一個部分都完成,那麼外掛就可以準備就緒,不需要立即就整個事情進行整理,這是原來的問題。
我現在做的編碼有點評論風格和一些示例程式碼。這是第一個實現方案,程式碼未經測試。這只是為了讓我的手變髒,為了你可能有一個例子,可以寫下如何 – 但不是必須的 – 。有時候,我往往太具體了,請記住我。當我編寫程式碼時,re-write 在建立時很常見,但是在建立示例程式碼時我無法使其顯示。所以記住這一點。如果您看到要做的更簡單,請選擇您的路線。您需要稍後更改和擴充套件程式碼,所以這只是一些示例程式碼。
Plugin
只需一個類來處理基本操作,例如註冊鉤子,併為幻燈片提供幻燈片和編輯器的 Metaboxes 。這是一切開始的地方。外掛以單個程式碼開始。我稱之為 bootstrap:
<?php
/** Plugin Headers ... */
return SlideshowPlugin::bootstrap();
class SlideshowPlugin {
/** @var Slideshow */
private $slideshow;
/** @var SlideshowMetaboxes */
private $metaboxes;
/** @var SlideshowPlugin */
static $instance;
static public function bootstrap() {
$pluginNeeded = (is_admin() && /* more checks based your needs */ );
if (!$pluginNeeded)
return;
}
if (NULL === self::$instance) {
// only load the plugin code while it's really needed:
require_once('library/Slideshow.php');
require_once('library/SlideshowSlide.php');
require_once('library/Store.php');
require_once('library/Metaboxes.php');
require_once('library/Metabox.php');
require_once('library/Form.php');
// ...
self::$instance = new SlideshowPlugin();
}
return self::$instance;
}
private function addAction($action, $parameters = 0, $priority = 10) {
$callback = array($this, $action);
if (!is_callable($callback)) {
throw new InvalidArgumentExeception(sprintf('Plugin %s does not supports the %s action.', __CLASS__, $action));
}
add_action($action, $callback, $parameters, $priority);
}
public function __construct() {
$this->addAction('admin_init');
}
/**
* @return bool
*/
private function isEditorRequest() {
// return if or not the request is the editor page
}
/**
* @-wp-hook
*/
public function admin_init() {
// register anything based on custom post type and location in the admin.
// I don't care about the details with CPT right now.
// It's just that editorAction is called when we're on the slideshow
// editor page:
if ($this->isEditorRequest()) {
$this->editorAction();
}
}
private function getPostID() {
// ... code goes here to get post id for request
return $postID;
}
private function getSlideshow() {
is_null($this->slideshow)
&& ($postID = $this->getPostID())
&& $slideshow = new Slideshow($postID)
;
return $slideshow;
}
private function getMetaboxes() {
is_null($this->metaboxes)
&& ($slideshow = $this->getSlideshow())
&& $this->metaboxes = new SlideshowMetaboxes($slideshow)
;
return $this->metaboxes;
}
private function editorAction() {
$metaboxes = $this->getMetaboxes();
}
}
所以這個外掛類已經很完整了。我沒有指定如何檢索 postID,但它已經被封裝在它自己的函式中。旁邊,我沒有程式碼來檢查這是否是顯示編輯器的正確頁面,但是已經有一些存根程式碼。
最後,如果請求是在實際的自定義帖子型別編輯器頁面上,則會呼叫 editorAction(),在那裡,Metaboxes 已經被收錄。而已。外掛現在應該很完整。它有幻燈片和照顧 Metaboxes 。與設計相比,這些是與外掛相關的部分。與影像比較:
-
決定是否顯示編輯器。
-
外掛和幻燈片之間的連線。該外掛已經有幻燈片放映。
-
連線到 Metaboxes 。該外掛已經有了 Metaboxes 。
看起來完整在這方面做的工作。
幻燈片和幻燈片
幻燈片對映為 1:1 對映到一個帖子。所以它需要有郵政編號。幻燈片可以儲存資料,所以它基本上是一個資料型別。它儲存您需要的所有值。它是一個複合資料型別,它包含 0 到 N 個幻燈片。另一個幻燈片是另一個資料型別,其中包含每個幻燈片的資訊。
幻燈片然後由 metabox 使用,可能是一種形式。
我還選擇實現幻燈片資料的儲存和檢索以及這些資料型別 (設計中標記為 「儲存」) 的框。這是混亂的資料型別和實際的物件。
但是當商店連線到幻燈片和幻燈片只在設計我連線他們彼此。對於未來可能太近了,但是為了首次實施設計,我認為這是一個有效的方法。由於這是第一種方法,因此即使有一些問題,我也相信這個方向是正確的:
class SlideshowSlide {
private $slideshow;
private $index;
public $number, $hide, $type, $title, $image, $wysiwyg, $embed
public function __construct($slideshow, $index) {
$this->slideshow = $slideshow;
$this->index = $index;
}
public function getSlideshow() { return $this->slideshow; }
public function getIndex() { return $this->index; }
}
class Slideshow implements Countable, OuterIterator {
private $postID;
private $slides = array();
private function loadSlidesCount() {
$postID = $this->postID;
// implement the loading of the count of slides here
}
private function loadSlide($index) {
$postID = $this->postID;
// implement the loading of slide data here
$data = ... ;
$slide = new SlideshowSlide($this, $index);
$slide->setData($data); // however this is done.
return $slide;
}
private function loadSlides() {
$count = $this->loadSlidesCount();
$slides = array();
$index = 0;
while(($index < $count) && ($slide = $this->loadSlide($index++)))
FALSE === $slide || $slides[] = $slide
;
$this->slides = $slides;
}
public function __construct($postID) {
$this->postID = $postID;
$this->loadSlides();
}
public function count() {
return count($this->slides);
}
public function getInnerIterator() {
return new ArrayIterator($this->slides);
}
private function touchIndex($index) {
$index = (int) $index;
if ($index < 0 || $index >= count($this->slides) {
throw new InvalidArgumentExpression(sprintf('Invalid index %d.', $index));
}
return $index;
}
public function getSlide($index) {
$index = $this->touchIndex($index);
return $this->slides[$index];
}
}
幻燈片和幻燈片課程也相當完整,但也缺少實際的程式碼。這只是為了展示我的想法,即擁有屬性/方法和一些處理內容以及如何實現資料檢索。
Metabox
Metabox 需要知道它代表哪個幻燈片。所以它需要知道幻燈片和具體幻燈片。幻燈片可以由外掛提供,幻燈片可以由索引 (例如 0 … N 表示,其中 N 是幻燈片中的幻燈片數量-1) 。
class Metabox {
public function __construct(SlideshowSlide $slide) {
}
}
Metabox 類實際上是擴充套件外掛類。它也可以透過外掛類完成一些工作,但是當我想要在外掛的上下文中可以顯示幻燈片的同時可以有多個例項時,我選擇了這種方式。
Metabox 現在需要處理請求邏輯:它代表一個實際上以某種方式輸出的 Metabox,但是它也是輸入,因為它需要處理表單輸入。
好的是,它實際上並沒有處理細節,因為表單輸出和輸入都是由表單物件完成的。
所以可能如果我將這個類編碼到最後,我會完全刪除它。我現在不知道目前,它代表了 Metabox 在編輯器頁面上的一個特定幻燈片。
Metaboxes
class Metaboxes
private $slideshow;
private $boxes;
public function __construct(Slideshow $slideshow) {
$this->slideshow = $slideshow;
$this->editorAction();
}
private function createMetaboxes() {
$slides = $this->slideshow;
$boxes = array();
foreach($slides as $slide) {
$boxes[] = new Metabox($slide);
}
$this->boxes = $boxes;
}
private function editorAction() {
$this->createMetaboxes();
}
到目前為止,我只寫了一些小程式碼。 Metaboxes 課堂是所有 metaboxes 的經理。幻燈片的代表 Metabox 代表幻燈片。
該存根程式碼並不多,但例項化一個 Metabox 每個幻燈片。它可以而且必須做更多的到最後。
您可能想在這裡使用 Composite Pattern,因此對 Metaboxes 物件執行操作將對每個 Metabox 執行相同的操作。與例項化相比,它建立了新的 Metaboxes 。所以你以後不需要處理個別的 Metaboxes,只需要與 Metaboxes 物件。只是一個想法
Form
該表格可能是您處理程式碼和程式碼行最複雜的事情。它需要抽象您的資料以透過瀏覽器進行處理。所以它必須能夠處理多個例項。您可以透過使用 genreal 字首 (例如”slide”) 將表單元素名稱 (如需要唯一) 字首,然後是識別符號 (幻燈片索引,我將此索引命名為您想要更改數字,例如具有排序鍵),然後是實際值識別符號 (例如”number” 或”hide”) 。
我們來看看:一個表單知道它的字首,幻燈片的數字和它包含的所有欄位。這幾乎對映到上面介紹的幻燈片和幻燈片資料型別。有些小 stub-code:
/**
* SlideForm
*
* Draw a Form based on Slide Data and a Form definition. Process it's Input.
*/
class SlideForm {
/** @var Slide */
private $slide;
private $prefix = 'slide';
public function __construct(Slide $slide) {
$this->slide = $slide;
}
private function inputNamePrefix() {
$index = $this->slide->getIndex();
$prefix = $this->prefix;
return sprintf('%s-%d-', $prefix, $index);
}
private function inputName($name) {
return $this->inputNamePrefix().$name;
}
private function printInput(array $element) {
list($type, $parameters) = $element;
$function = 'printInput'.$type;
$callback = array($this, $function)
call_user_func_array($callback, $parameters);
}
private function printInputText($value, $name, $label, $size = 4) {
$inputName = $this->inputName($name);
?>
<label for="<?php echo $inputName ; ?>">
<?php echo htmlspecialchars($label); ?>:
</label>
<input type="text"
name="<?php echo $inputName; ?>"
size="<?php echo $size; ?>"
value="<?php echo htmlspecialchars($value); ?>">
<?php
}
private function printInputCheckbox($value, $name, $label, ... ) { ... }
private function printInputRadio($value, $name, $label, ... ) { ... }
private function printInputImage($value, $name, $label, ... ) { ... }
private function printInputWysiwyg($value, $name, $label, ... ) { ... }
private function printInputTextarea($value, $name, $label, ... ) { ... }
// ...
private function mapSlideValueTo(array $element) {
$slide = $this->slide;
list($type, $parameters) = $element;
list($name) = $parameters;
$value = $slide->$name;
array_unshift($parameters, $value);
$element[1] = $parameters;
return $element;
}
/**
* @return array form definition
*/
private function getForm() {
// Form Definition
$form = array(
array(
'Text',
array(
'number', 'Number'
),
array(
'Checkbox',
array(
'hide', 'Display', 'Hide This Slide'
),
),
array(
'Radio',
array(
'type', 'Type', array('Image', 'Video')
),
),
array(
'Text',
array(
'title', 'Title', 16
),
),
// ...
);
return $form;
}
public function printFormHtml() {
$form = $this->getForm();
foreach($form as $element) {
$element = $this->mapSlideValueTo($element);
$this->printInput($element);
}
}
public function processFormElement($element) {
list($type, $parameters) = $element;
list($name) = $parameters;
$inputName = $this->inputName($name);
$map = array(
'Text' => 'String',
'Checkbox' => 'Checkbox',
'Radio' => 'Radio',
);
// I would need to continue to code there.
throw new Exception('Continue to code: Process Form Input based on Form Definition');
}
public function processForm() {
$form = $this->getForm();
foreach($form as $element) {
$this->processFormElement($element); // <- this function needs to be coded
}
}
// ...
}
這個課程現在很大,因為它一次處理三件事情:
-
表格定義
-
表單輸出渲染
-
表單輸入處理
將它分解成它代表的三個部分是更明智的。我離開了你。它已經顯示瞭如何將表單功能封裝到較小的任務中,以便更容易地滿足您的需求。例如。如果 Image Input 元素輸出需要調整,則可以輕鬆地進行擴充套件/拋光。所見即所得您可以稍後更改實現,因為它不會影響您的幻燈片和幻燈片資料型別。
這個背後的原則也被稱為分離問題,那就是我如何開始我的答案:將問題分解成更小的問題。這些分離的問題更容易解決。
我希望這個時刻有所幫助。最後我甚至沒有回到自定義帖子型別。我知道他們必須進入外掛,但使用新的設計,很容易找到寫入程式碼的地方。
還剩下什麼?
-
將程式碼分割成多個檔案。每個檔案一個類。您可以輕鬆地將它們合併在一起,但是為了開發,將東西分開,以便您自己解決較小的問題/部分。
-
測試:您需要自行測試零件的功能。幻燈片是否應該做什麼?很高興你可以使用 Unittests,如果你寫的類,對於 PHP 有 PHPUnit 。這有助於您開發程式碼,同時知道它完全正確。這有助於解決每個人的單位中的簡單問題,您可以稍後更容易地更改程式碼,因為您可以一直執行測試。
-
測試#2:當然你需要測試你的外掛作為一個整體,所以你知道它正在做你正在尋找的。你能想像如何自動完成這些工作,所以您可以一直以相同的質量重複測試。
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。
