おしゃれなギャラリーが作れるCMS「Lychee」を使ってみた
みなさん、CMSってご存じですか?
Contents Management Systemの略で、htmlを直接編集することなく、ブログやホームページが作れるシステムのことです。
世界中で広く利用されている「WordPress」は、このCMSの一種です。
WordPressなら、ブログを書くときにいちいちhtmlをまるごと制作する、なんてことはないですよね?
これがCMSの特徴です。
CMSは、WordPress以外にもDrupalやConcrete5など様々な種類があります。
余談ですが、個人的にはConcrete5が使いやすくて好きだったりします。
今日は、このCMSの中から「Lychee」をご紹介します。
Lycheeとは
タイトルに合ったようにLycheeはギャラリーを作るためのものです。
ギャラリーとは、写真を一覧で表示して、画像をクリックすると拡大される、といった機能を持つものです。
スマホの中にも写真を見るためのギャラリーアプリが入っていますよね。
写真をメインで扱うようなサイトでは、なるべく使いやすく、きれいに見せたいところですよね。
そんな望みを叶えてくれるのが、Lycheeです。
WordPressにプラグインをいれてギャラリーを作ってもいいのですが、そうすると大掛かりなシステムになりますよね。
ちょっと写真が見れるサイトを作りたいんだ、なんて時には面倒だったりします。
ということで、Lycheeが活用されるのです。
Lycheeは、主にPHPとjavascriptで構成されており、写真の管理にMySQLが必要です。
WordPressがインストールできるサーバーであれば、Lycheeもインストール可能です。
インストール手順はとても簡単です。
まず、Lycheeのgithubにアクセスし、ファイルをダウンロードします。
git cloneしても構いません。
github.com
このファイルを解凍し、インストールしたいディレクトリに配置して、その場所にアクセスします。
あとは画面に従って、MySQLのユーザー名やパスワードなど必要な情報を入力し、管理者用パスワードを設定すれば完了です。
詳しい利用方法は、READMEの中に書かれています。
直感的に使い方がわかるので、迷うこともないと思います。
Lycheeの良い点・悪い点
Lycheeの良いところは、シンプルさと美しさです。
ギャラリーを作るCMSは、レイアウトが残念で全近代的なビジュアルだったりしますが、Lycheeは黒を基調としたシンプルなデザインです。
また、それでいて必要な機能はしっかり備わっています。
写真を一括でzipにしてダウンロードしたり、写真1枚1枚を全画面表示したり、名前を変更したり共有したり。
さらにはパスワードによって写真を保護する、なんてこともできます。
基本的な機能は揃っていて、便利です。
今まで3日ほど私が使ってきて困ったことがいくつかありました。
まず、パスワード保護に関するものです。
パスワードによって写真を保護している場合、フォルダ内の写真を見るたびにパスワードを求められることがあります。
写真を1枚見るごとにパスワードを求められ、非常に面倒でした。
この原因はchromeのパスワード保存機能が原因でした。
管理者用のアカウント情報をchromeに記憶させていたことで、このような面倒な現象が起こるようです。
また、写真の一括ダウンロードですが、写真の数が多くなるとうまく動かなくなりました。
原因は、zipファイルの送信にありました。
一括ダウンロードでは、毎回phpにてzipファイルの作成が行われ、そのまま送信されるのですが、これがファイルサイズを考慮しない作りとなっているようです。
サーバーのメモリ不足によって転送ができなくなるようです。
php/Module/Album.php内のgetArchive()を以下のように編集すると直りました。
<?php public function getArchive() { // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); // Illicit chars $badChars = array_merge( array_map('chr', range(0,31)), array("<", ">", ":", '"', "/", "\\", "|", "?", "*") ); // Photos query switch($this->albumIDs) { case 's': $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE public = 1', array(LYCHEE_TABLE_PHOTOS)); $zipTitle = 'Public'; break; case 'f': $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE star = 1', array(LYCHEE_TABLE_PHOTOS)); $zipTitle = 'Starred'; break; case 'r': $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) GROUP BY checksum', array(LYCHEE_TABLE_PHOTOS)); $zipTitle = 'Recent'; break; default: $photos = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE album = '?'", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); $zipTitle = 'Unsorted'; } // Get title from database when album is not a SmartAlbum if ($this->albumIDs!=0&&is_numeric($this->albumIDs)) { $query = Database::prepare(Database::get(), "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); $album = Database::execute(Database::get(), $query, __METHOD__, __LINE__); if ($album===false) return false; // Get album object $album = $album->fetch_object(); // Album not found? if ($album===null) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); return false; } // Set title $zipTitle = $album->title; } // Escape title $zipTitle = str_replace($badChars, '', $zipTitle); $filename = LYCHEE_DATA . $zipTitle . '.zip'; // Create zip $zip = new ZipArchive(); if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create ZipArchive'); return false; } // Execute query $photos = Database::execute(Database::get(), $photos, __METHOD__, __LINE__); // Check if album empty if ($photos->num_rows==0) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create ZipArchive without images'); return false; } // Parse each path $files = array(); while ($photo = $photos->fetch_object()) { // Parse url $photo->url = LYCHEE_UPLOADS_BIG . $photo->url; // Parse title $photo->title = str_replace($badChars, '', $photo->title); if (!isset($photo->title)||$photo->title==='') $photo->title = 'Untitled'; // Check if readable if (!@is_readable($photo->url)) continue; // Get extension of image $extension = getExtension($photo->url, false); // Set title for photo $zipFileName = $zipTitle . '/' . $photo->title . $extension; // Check for duplicates if (!empty($files)) { $i = 1; while (in_array($zipFileName, $files)) { // Set new title for photo $zipFileName = $zipTitle . '/' . $photo->title . '-' . $i . $extension; $i++; } } // Add to array $files[] = $zipFileName; // Add photo to zip $zip->addFile($photo->url, $zipFileName); } // Finish zip $zip->close(); // Send zip header("Content-Type: application/zip"); header("Content-Disposition: attachment; filename=\"$zipTitle.zip\""); header("Content-Length: " . filesize($filename)); //変更ここから while (ob_get_level() > 0) { ob_end_clean(); } ob_start(); $file = fopen($filename, 'rb'); if(!$file) { exit; } while(!feof($file) and (connection_status() == 0)) { echo fread($file, '1048576'); ob_flush(); } ob_flush(); ob_end_clean(); //変更ここまで // Delete zip unlink($filename); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; }
こちらの記事を参考にさせていただきました。ありがとうございます。
every-rating.com
最後に
いかがでしょうか。不具合が多々あるので、実用可能ではないかもしれませんが、おしゃれで使い勝手がいいので、一度使ってみてはいかがでしょうか。
ではまた。