I've started with a bunch of functions, made the code work, then I spent a day rewriting it in an OO way, as much as I can.
I've tried to group up the task into objects, letting the relative data go to the relative function. But it still doesn't sound like OO, just several groups of functions.
There is an 'upload attachment form' in my CMS, which can be used for uploading attachments for [Category, Page, Content]. The form includes a file input (multiple) and some data for "where the attachment belongs to".
The code will be used at the handing page where the form POST to.
It should be able to:
- Do the error checking, return error message if occur
- Load some dynamic setting from database
- Save the file into specific directory
- Rename the file into random string
- Create a thumb image
- Store file data into the database, including some linking table
- Handle both normal and ajax request, and return the correct feedback For the thumb image, it should only do whenever if the file is a image, but I didn't do it yet.
Please help me and let me know how to get it done in a nice OO way.
You can also see my code at codeviewer.
UploadHandeler
Class UploadHandeler{
private $helper;
private $files;
private $dataModel;
function __construct(){
$this->helper = new UHelper;
$this->dataModel = new DataModel;
$this->files = new FilesControl;
}
public function init(){
$this->helper->checkInput();
$this->dataModel->setField();
$this->dataModel->setObj();
$this->files->setBaseDir('test_upload/');
$this->files->setSetting($this->dataModel->fieldId);
$this->files->checkDir();
$this->files->loadfiles();
}
public function saveFiles(){
$this->files->renameFiles();
$this->files->saveFiles();
$this->files->makeThumbImage(150,255);
}
public function insertDB(){
$this->dataModel->loadData($this->files->files);
$this->dataModel->insertDB();
echo'<br>-----end-------<br>';
}
}
FilesController
Class FilesControl{
public $baseDir;
public $files;
public $filename_arr = array();
public $setting = array();
function __construct(){
$this->files = UHelper::getfileArray();
}
public function setBaseDir($dir){
if(!file_exists($dir)){
return UHelper::exitError('Base-directory is not exists.');
}
$this->baseDir = $dir;
return true;
}
function setSetting($fieldId){
$result = Query::get_Setting($fieldId);
if(!$result){
return UHelper::exitError('AttachmentFeild not found.');
}
$this->setting['allowed_ext'] = explode(',' ,$result[0]['allowed_ext']);
$this->setting['maxFileSize'] = $result[0]['maxFileSize'];
$this->setting['maxFileNum'] = $result[0]['maxFileNum'];
$this->setting['path'] = $this->baseDir.'/'.$result[0]['folder'].'/';
return;
}
function checkDir(){
$dir = $this->setting['path'];
//create directory if not exists
if(!file_exists($dir)){
if(!mkdir($dir, 0777)){
UHelper::exitError('Fail when create directory.');
}
}
return true;
}
function loadFiles(){
$new_obj_arr = array();
foreach ($this->files as $itemData) {
$this->checkFile($itemData);
$file = new File;
$file->loadFile($itemData);
array_push($new_obj_arr, $file);
}
$this->files = $new_obj_arr;
return true;
}
function checkFile($file){
$allowed_ext = $this->setting['allowed_ext'];
$exd = UHelper::get_extension($file['name']);
if( $file['error'] !== 0){
return UHelper::exitError('Something went wrong with your upload.');
}
if(!in_array($exd, $allowed_ext)){
return UHelper::exitError('File format "'.$exd.'" is not allowed.');
}
return true;
}
/*-----------------------------------------------*/
function renameFiles(){
foreach ($this->files as $key => $file) {
$exd = $file->fileType;
do{
$fileName = UHelper::randomString().'.'.$exd;
}while( $this->fileNameIsRepeat($fileName) );
$this->files[$key]->fileName= $fileName;
array_push($this->filename_arr, $fileName);
}
return true;
}
function fileNameIsRepeat($fileName){
if( file_exists($this->setting['path'].$fileName) ||
in_array($fileName, $this->filename_arr)){
return true;
}else{
return false;
}
}
function saveFiles(){
$dir = $this->setting['path'];
foreach ($this->files as $file) {
$tmp_name = $file->tmp_name;
$path = $dir.$file->fileName;
if(!move_uploaded_file($tmp_name, $path)){
Helper::exitError('Fail when saving file!');
}
}
return true;
}
function makeThumbImage($max_w, $max_h){
$dir = $this->setting['path'];
foreach ($this->files as $file) {
$fileName = $file->fileName;
$path = $dir.$fileName;
$exd = $file->fileType;
$image = $this->imageResize($path, $exd, $max_w, $max_h);
$this->saveImage($image, $fileName, $exd);
}
return true;
}
/*-----------------------------------------------*/
function imageResize($path, $exd, $max_w, $max_h){
//load image as resource
$src_image= $this->loadImage($path, $exd);
//Get the image size
$src_w=ImageSX($src_image);
$src_h=ImageSY($src_image);
$s = UHelper::getNewSize($src_w, $src_h, $max_w, $max_h);
$dst_w=$s['w'];
$dst_h=$s['h'];
//do the resize
$dst_image=ImageCreateTrueColor($dst_w,$dst_h);
imagecopyresampled($dst_image,$src_image,0,0,0,0,$dst_w,$dst_h,$src_w,$src_h);
imagedestroy($src_image);
return $dst_image;
}
function loadImage($path, $exd){
switch ($exd) {
case 'jpg':
case 'jpeg':
$image=imagecreatefromjpeg($path);
break;
case 'png':
$image=imagecreatefrompng($path);
break;
case 'gif':
$image=imagecreatefromgif($path);
break;
default:
UHelper::exitError('Image type not support.');
break;
}
return $image;
}
function saveImage($image, $fileName, $exd){
$folder = $this->setting['path'];
$dst_path = UHelper::makeNewPath($folder, $fileName);
switch ($exd) {
case 'jpg':
case 'jpeg':
ImageJpeg($image,$dst_path,95);
break;
case 'png':
Imagepng($image,$dst_path,0);
break;
case 'gif':
Imagegif($image,$dst_path);
break;
default:
UHelper::exitError('Image type not support.');
break;
}
imagedestroy($image);
return true;
}
}
File
Class File{
public $tmp_name;
public $org_name;
public $fileName;
public $fileType;
public $size;
function loadFile($row){
$this->tmp_name = $row['tmp_name'];
$this->org_name = $row['name'];
$this->size = $row['size'];
$this->fileType = UHelper::get_extension($row['name']);
}
}
UHelper
Class UHelper{
public function exitError($errorMsg){
exit($errorMsg);
return false;
}
public function checkInput(){
if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
UHelper::exitError('Wrong HTTP method.');
}
if(!array_key_exists('Upload',$_FILES)){
UHelper::exitError('Something went wrong with your upload.');
}
return true;
}
public function getfileArray(){
$new_arr = array();
$files = $_FILES["Upload"];
$num = count($files["name"]);
for ($i=0; $i<$num ; $i++){
$new_arr[$i] = array();
}
foreach ($files as $key => $row) {
for ($i=0; $i<$num ; $i++){
$new_arr[$i][$key] = $files[$key][$i];
}
}
return $new_arr;
}
public function get_extension($file_name){
$ext = explode('.', $file_name);
$ext = array_pop($ext);
return strtolower($ext);
}
public function randomString() {
$length = 5;
$characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWZYZ";
$charactersNum = strlen($characters) ;
$string='';
for ($p = 0; $p < $length; $p++){
$string .= $characters[mt_rand(0, $charactersNum-1)];
}
return dechex(time()).strtolower($string);
}
public function getNewSize($w, $h, $max_w, $max_h){
if($w <= $max_w && $h <= $max_h){
$new_w = $w;
$new_h = $h;
}
if($w > $max_w || $h > $max_h){
$new_w = $max_w;
$w_radio = $w / $new_w;
$new_h = $h/$w_radio;
}
if($new_h > $max_h){
$new_h = $max_h;
$h_radio = $h / $new_h;
$new_w = $w/$h_radio;
}
return array("w"=> $new_w, "h"=> $new_h);
}
public function makeNewPath($folder, $fileName){
$pop = explode('.', $fileName);
$fileName = $pop[0];
$exd = $pop[1];
$newPath = $folder.$fileName.'_s'.'.'.$exd;
return $newPath;
}
}
DataModel
Class DataModel{
public $baseDir;
public $objName;
public $objId ;
public $fieldId;
public $files;
public $objType_arr = array(
'1'=>'categoryItem',
'2'=>'page',
'3'=>'content'
);
public function setField(){
if(!isset($_POST['attachmentField_id'])){
return UHelper::exitError('Parameter missing.');
}
$this->fieldId = $_POST['attachmentField_id'];
return true;
}
public function setObj(){
$objType=$_POST['objType'];
if(!isset($this->objType_arr[$objType])){
return UHelper::exitError('Object type incorrect.');
}
$name = $this->objType_arr[$objType];
$idName = $name.'_id';
if(!isset($_POST[$idName])){
return UHelper::exitError('Parameter missing.');
}
$this->objName = $name;
$this->objId = $_POST[$idName];
return true;
}
/*-----------------------------*/
public function loadData($fileData){
$this->files = $fileData;
return true;
}
public function insertDB(){
$files = $this->files;
$fieldId = $this->fieldId;
$objId = $this->objId;
$user = User::getCurrentUser();
$datetime = date("Y-m-d H:i:s");
$tableName = ucfirst($this->objName).'AttachmentFeild_Value';
$fieldName = $this->objName.'_id';
/** Get $attachment_id if already have record **/
$attachment_id = Query::get_AttachmentId($tableName, $fieldName, $objId, $fieldId);
if(!$attachment_id){
$folder = $this->setting['dir'];
Query::insert_Attachment($folder);
$attachment_id = Yii::app()->db->getLastInsertID();
Query::insert_Obj_to_Field($tableName, $objId, $fieldId, $attachment_id);
}
foreach ($files as $file) {
$filename = $file->fileName;
$org_name = $file->org_name;
$exd = $file->exd;
// insert into AttachmentItem
Query::insert_AttachmentItem($attachment_id, $filename, $org_name, $exd);
}
}
}
Query
Class Query{
public function get_Setting($fieldId){
$sql =
"SELECT *
FROM {{AttachmentFeild}}
WHERE id = :fieldId
AND status = '6'";
$command = Yii::app()->db->createCommand($sql);
$command->bindParam(":fieldId", $fieldId, PDO::PARAM_STR);
$result = $command->queryAll();
return $result;
}
public function get_AttachmentId($tableName, $fieldName, $objId, $fieldId){
$sql =
"SELECT *
FROM {$tableName}
WHERE $fieldName = :objId
AND attachmentFeild_id =:fieldId";
$command = Yii::app()->db->createCommand($sql);
$command->bindParam(":objId", $objId, PDO::PARAM_STR);
$command->bindParam(":fieldId", $fieldId, PDO::PARAM_STR);
$result = $command->queryAll();
if(!$result){
return false;
}
$attachment_id = $result[0]['attachment_id'];
return $attachment_id;
}
public function insert_Attachment($folder){
$user = User::getCurrentUser();
$datetime = date("Y-m-d H:i:s");
$sql =
"INSERT INTO {{Attachment}}
VALUES(null, 1, null, null, :folder ,null, 6, :user, :user, :datetime, :datetime, null)";
$command = Yii::app()->db->createCommand($sql);
$command->bindParam(":folder", $folder, PDO::PARAM_STR);
$command->bindParam(":user", $user, PDO::PARAM_STR);
$command->bindParam(":datetime", $datetime, PDO::PARAM_STR);
$command->execute();
return true;
}
public function insert_Obj_to_Field($tableName, $objId, $fieldId, $attachment_id){
$user = User::getCurrentUser();
$datetime = date("Y-m-d H:i:s");
$sql =
"INSERT INTO {$tableName}
VALUES(null, :objId, :fieldId, :attm_id, :user, :user, :datetime, :datetime, null)";
$command = Yii::app()->db->createCommand($sql);
$command->bindParam(":objId", $objId, PDO::PARAM_STR);
$command->bindParam(":fieldId", $fieldId, PDO::PARAM_STR);
$command->bindParam(":attm_id", $attachment_id, PDO::PARAM_STR);
$command->bindParam(":user", $user, PDO::PARAM_STR);
$command->bindParam(":datetime", $datetime, PDO::PARAM_STR);
$command->execute();
return true;
}
public function insert_AttachmentItem($attachment_id, $filename, $org_name, $exd){
$user = User::getCurrentUser();
$datetime = date("Y-m-d H:i:s");
$sql =
"INSERT INTO AttachmentItem
VALUES (null, :attchId, null, null, 1, :filename, :org_name, :exd, '6', 1000, :user, :user, :datetime, :datetime, null)";
$command = Yii::app()->db->createCommand($sql);
$command->bindParam(":attchId", $attachment_id, PDO::PARAM_STR);
$command->bindParam(":filename", $filename, PDO::PARAM_STR);
$command->bindParam(":org_name", $org_name, PDO::PARAM_STR);
$command->bindParam(":exd", $exd, PDO::PARAM_STR);
$command->bindParam(":user", $user, PDO::PARAM_STR);
$command->bindParam(":datetime", $datetime, PDO::PARAM_STR);
$result = $command->execute();
return true;
}
}