将 CodeIgniter 多文件 DropZone 上传器代码划分到 MVC 中?
Dividing Up CodeIgniter Multi-File DropZone Uploader Code into MVC?
我是 CodeIgniter 的新手,我正在尝试将工作的 DropZone 多文件上传器转换为 MVC CodeIgniter 格式。我在这里看到了一些其他示例,但需要获得针对我的特定代码的建议。
我知道如何将 upload/form 页面放置在视图中并通过控制器加载。但是,表单处理程序代码是我需要帮助的地方。
Upload/Form 页数:
<head>
<script type="text/javascript" src="js/jquery-2.1.1.js"></script>
<!-- Add Dropzone -->
<link rel="stylesheet" type="text/css" href="css/dropzone.css" />
<script type="text/javascript" src="js/dropzone.js"></script>
</head>
<body>
<div class="image_upload_div">
<form action="upload_thumbnails.php" class="dropzone">
</form>
</div>
<script type="text/javascript">
//Disabling autoDiscover
Dropzone.autoDiscover = false;
$(function() {
//Dropzone class
var myDropzone = new Dropzone(".dropzone");
myDropzone.on("queuecomplete", function() {
//Redirect URL
//window.location.href = 'http://php.net';
});
});
</script>
</body>
表单处理程序代码的哪些部分应该放在模型和控制器中?这是我正在努力的部分。
表单处理程序代码:
if(!empty($_FILES)){
function createThumbnail($filename) {
$final_width_of_image = 200;
$path_to_image_directory = 'uploads/';
$path_to_thumbs_directory = 'uploads/thumbs/';
if(preg_match('/[.](jpg)$/', $filename)) {
$im = imagecreatefromjpeg($path_to_image_directory . $filename);
} else if (preg_match('/[.](gif)$/', $filename)) {
$im = imagecreatefromgif($path_to_image_directory . $filename);
} else if (preg_match('/[.](png)$/', $filename)) {
$im = imagecreatefrompng($path_to_image_directory . $filename);
}
$ox = imagesx($im);
$oy = imagesy($im);
$nx = $final_width_of_image;
$ny = floor($oy * ($final_width_of_image / $ox));
$nm = imagecreatetruecolor($nx, $ny);
if(!imagecopyresized($nm, $im, 0,0,0,0,$nx,$ny,$ox,$oy)){
header("HTTP/1.0 500 Internal Server Error");
echo 'Thumbnail Not created';
exit();
}
if(!file_exists($path_to_thumbs_directory)) {
if(!mkdir($path_to_thumbs_directory)) {
header("HTTP/1.0 500 Internal Server Error");
echo 'Thumbnail Not Created';
exit();
}
}
// Save new thumbnail image
imagejpeg($nm, $path_to_thumbs_directory . $filename);
}
//database configuration
$dbHost = 'localhost';
$dbUsername = 'insertnamehere';
$dbPassword = 'insertpwhere';
$dbName = 'ci_local';
//connect with the database
$conn = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName);
if($mysqli->connect_errno){
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$targetDir = "uploads/";
$fileName = $_FILES['file']['name'];
$targetFile = $targetDir.$fileName;
if(move_uploaded_file($_FILES['file']['tmp_name'],$targetFile)){
// NEW
//createThumbnail($file['file']['name']);
createThumbnail($fileName);
// NEW
//insert file information into db table
$conn->query("INSERT INTO files (file_name, uploaded) VALUES('".$fileName."','".date("Y-m-d H:i:s")."')");
} else {
echo "Ooops";
}
}
如有任何建议,我们将不胜感激。
您的 createThumbnail
函数是一个很好的例子,它应该放在模型、库或助手中。助手只包含函数,而库或模型是基于 class 的,因此可以访问 class 属性并具有构造函数。我倾向于将它变成一个库或一个助手,因为它没有耦合(因此可重用)到任何特定的或其他功能。
通常您只想 return 或在不在控制器中的任何函数中抛出异常。
- 这允许您在一个文件中设置输出,而不必
搜索您的模型、库等。如果你想改变
你的输出在路上(例如,如果你计划使用 AJAX)。
- 还允许非紧密耦合的代码库
轻松移植到可能不同的其他安装。
- 有利于可读性。
型号
任何与数据库相关的东西都应该放在模型中,因为模型代表应用程序中的数据逻辑或实际使用的数据。您应该真正使用 Codeigniter 的内置数据库功能,而不是自己初始化数据库和 运行 查询。您的插入或更新语句应移动到与控制器相关的模型中。
控制器
您的控制器仅用于加载模型,以及视图可能需要的任何变量。它还应该用于设置响应,无论是 flash 消息还是 json 编码。在许多示例中,它还用于 form_validation
或在执行相关模型中存在的 CRUD 操作之前的数据检查。
tl;dr 任何与数据库相关的东西都放在模型中,任何可重用且不紧密耦合的东西都放在库中,或者如果它与 oop 没有特定关系则放在助手中(比如数组排序)算法),任何 form/input/view/response 相关的东西都在控制器中。
大致上你可以做这样的事情(代码可能无法开箱即用;我使用我自己的实现,它不同于默认的 dz 行为,因为我也使用 jquerys sortable ...我也不确定错误处理,因为我使用另一种技术来处理):
// byte_helper.php
/**
* Gets max upload size from post_max_size and upload_max_filesize
* Returns whichever is smaller
*
* @return int
*/
function file_upload_max_size() {
$max_size = convert_to_bytes(ini_get('post_max_size'));
$upload_max = convert_to_bytes(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = $upload_max;
}
return $max_size;
}
/**
* Converts KB (K) through GB (G) to bytes
*
* @param string $from
* @return int bytes
*/
function convert_to_bytes($from) {
$number = filter_var($from, FILTER_SANITIZE_NUMBER_INT);
$type = strtoupper(str_replace($number, '', $from));
switch ($type) {
case "KB":
case "K":
$number = $number * 1024;
break;
case "MB":
case "M":
$number = $number * pow(1024, 2);
break;
case "GB":
case "G":
$number = $number * pow(1024, 3);
break;
}
return fix_integer_overflow($number);
}
/**
* Fixes integer overflow
*
* @param int $size
* @return int
*/
function fix_integer_overflow($size) {
if ($size < 0) {
$size += 2.0 * (PHP_INT_MAX + 1);
}
return $size;
}
class Dropzone_controller extends CI_Controller {
public function upload() {
if (!$this->input->is_ajax_request()) {
exit('No direct script access allowed');
}
$this->load->helper('byte');
$config['upload_path'] = ''; // upload directory realpath
$config['file_name'] = md5(time()); // I like to set my own filename
$config['overwrite'] = true;
$config['allowed_types'] = 'jpg|jpeg|png|gif';
$config['max_size'] = file_upload_max_size();
$config['file_ext_tolower'] = true;
$this->load->library('upload', $config);
if (!$this->upload->do_upload('file')) {
$this->dz_error($this->upload->display_errors('', '<br>'));
}
$data = $this->upload->data();
$full_path = realpath($data['full_path']); // CI uses weird slashes
// here you can use imagelib to resize if you want, I personally
// like to use verot's class upload for that
$this->load->model('dropzone_model');
if (!$this->dropzone_model->add_image($full_path)) {
@unlink($full_path); // remove orphaned image
$this->dz_error('Failed to add image to the database!');
}
$this->dz_success();
}
//
private function dz_error($error) {
$this->output
->set_header("HTTP/1.0 400 Bad Request")
->set_output($error)
->_display();
exit;
}
private function dz_success() {
// don't really need to do anything here?
}
}
class Dropzone_model extends CI_Model {
public function add_image($full_path) {
return $this->db->insert('sometable', array('image' => $full_path));
}
}
我是 CodeIgniter 的新手,我正在尝试将工作的 DropZone 多文件上传器转换为 MVC CodeIgniter 格式。我在这里看到了一些其他示例,但需要获得针对我的特定代码的建议。
我知道如何将 upload/form 页面放置在视图中并通过控制器加载。但是,表单处理程序代码是我需要帮助的地方。
Upload/Form 页数:
<head>
<script type="text/javascript" src="js/jquery-2.1.1.js"></script>
<!-- Add Dropzone -->
<link rel="stylesheet" type="text/css" href="css/dropzone.css" />
<script type="text/javascript" src="js/dropzone.js"></script>
</head>
<body>
<div class="image_upload_div">
<form action="upload_thumbnails.php" class="dropzone">
</form>
</div>
<script type="text/javascript">
//Disabling autoDiscover
Dropzone.autoDiscover = false;
$(function() {
//Dropzone class
var myDropzone = new Dropzone(".dropzone");
myDropzone.on("queuecomplete", function() {
//Redirect URL
//window.location.href = 'http://php.net';
});
});
</script>
</body>
表单处理程序代码的哪些部分应该放在模型和控制器中?这是我正在努力的部分。
表单处理程序代码:
if(!empty($_FILES)){
function createThumbnail($filename) {
$final_width_of_image = 200;
$path_to_image_directory = 'uploads/';
$path_to_thumbs_directory = 'uploads/thumbs/';
if(preg_match('/[.](jpg)$/', $filename)) {
$im = imagecreatefromjpeg($path_to_image_directory . $filename);
} else if (preg_match('/[.](gif)$/', $filename)) {
$im = imagecreatefromgif($path_to_image_directory . $filename);
} else if (preg_match('/[.](png)$/', $filename)) {
$im = imagecreatefrompng($path_to_image_directory . $filename);
}
$ox = imagesx($im);
$oy = imagesy($im);
$nx = $final_width_of_image;
$ny = floor($oy * ($final_width_of_image / $ox));
$nm = imagecreatetruecolor($nx, $ny);
if(!imagecopyresized($nm, $im, 0,0,0,0,$nx,$ny,$ox,$oy)){
header("HTTP/1.0 500 Internal Server Error");
echo 'Thumbnail Not created';
exit();
}
if(!file_exists($path_to_thumbs_directory)) {
if(!mkdir($path_to_thumbs_directory)) {
header("HTTP/1.0 500 Internal Server Error");
echo 'Thumbnail Not Created';
exit();
}
}
// Save new thumbnail image
imagejpeg($nm, $path_to_thumbs_directory . $filename);
}
//database configuration
$dbHost = 'localhost';
$dbUsername = 'insertnamehere';
$dbPassword = 'insertpwhere';
$dbName = 'ci_local';
//connect with the database
$conn = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName);
if($mysqli->connect_errno){
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$targetDir = "uploads/";
$fileName = $_FILES['file']['name'];
$targetFile = $targetDir.$fileName;
if(move_uploaded_file($_FILES['file']['tmp_name'],$targetFile)){
// NEW
//createThumbnail($file['file']['name']);
createThumbnail($fileName);
// NEW
//insert file information into db table
$conn->query("INSERT INTO files (file_name, uploaded) VALUES('".$fileName."','".date("Y-m-d H:i:s")."')");
} else {
echo "Ooops";
}
}
如有任何建议,我们将不胜感激。
您的 createThumbnail
函数是一个很好的例子,它应该放在模型、库或助手中。助手只包含函数,而库或模型是基于 class 的,因此可以访问 class 属性并具有构造函数。我倾向于将它变成一个库或一个助手,因为它没有耦合(因此可重用)到任何特定的或其他功能。
通常您只想 return 或在不在控制器中的任何函数中抛出异常。
- 这允许您在一个文件中设置输出,而不必 搜索您的模型、库等。如果你想改变 你的输出在路上(例如,如果你计划使用 AJAX)。
- 还允许非紧密耦合的代码库 轻松移植到可能不同的其他安装。
- 有利于可读性。
型号
任何与数据库相关的东西都应该放在模型中,因为模型代表应用程序中的数据逻辑或实际使用的数据。您应该真正使用 Codeigniter 的内置数据库功能,而不是自己初始化数据库和 运行 查询。您的插入或更新语句应移动到与控制器相关的模型中。
控制器
您的控制器仅用于加载模型,以及视图可能需要的任何变量。它还应该用于设置响应,无论是 flash 消息还是 json 编码。在许多示例中,它还用于 form_validation
或在执行相关模型中存在的 CRUD 操作之前的数据检查。
tl;dr 任何与数据库相关的东西都放在模型中,任何可重用且不紧密耦合的东西都放在库中,或者如果它与 oop 没有特定关系则放在助手中(比如数组排序)算法),任何 form/input/view/response 相关的东西都在控制器中。
大致上你可以做这样的事情(代码可能无法开箱即用;我使用我自己的实现,它不同于默认的 dz 行为,因为我也使用 jquerys sortable ...我也不确定错误处理,因为我使用另一种技术来处理):
// byte_helper.php
/**
* Gets max upload size from post_max_size and upload_max_filesize
* Returns whichever is smaller
*
* @return int
*/
function file_upload_max_size() {
$max_size = convert_to_bytes(ini_get('post_max_size'));
$upload_max = convert_to_bytes(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = $upload_max;
}
return $max_size;
}
/**
* Converts KB (K) through GB (G) to bytes
*
* @param string $from
* @return int bytes
*/
function convert_to_bytes($from) {
$number = filter_var($from, FILTER_SANITIZE_NUMBER_INT);
$type = strtoupper(str_replace($number, '', $from));
switch ($type) {
case "KB":
case "K":
$number = $number * 1024;
break;
case "MB":
case "M":
$number = $number * pow(1024, 2);
break;
case "GB":
case "G":
$number = $number * pow(1024, 3);
break;
}
return fix_integer_overflow($number);
}
/**
* Fixes integer overflow
*
* @param int $size
* @return int
*/
function fix_integer_overflow($size) {
if ($size < 0) {
$size += 2.0 * (PHP_INT_MAX + 1);
}
return $size;
}
class Dropzone_controller extends CI_Controller {
public function upload() {
if (!$this->input->is_ajax_request()) {
exit('No direct script access allowed');
}
$this->load->helper('byte');
$config['upload_path'] = ''; // upload directory realpath
$config['file_name'] = md5(time()); // I like to set my own filename
$config['overwrite'] = true;
$config['allowed_types'] = 'jpg|jpeg|png|gif';
$config['max_size'] = file_upload_max_size();
$config['file_ext_tolower'] = true;
$this->load->library('upload', $config);
if (!$this->upload->do_upload('file')) {
$this->dz_error($this->upload->display_errors('', '<br>'));
}
$data = $this->upload->data();
$full_path = realpath($data['full_path']); // CI uses weird slashes
// here you can use imagelib to resize if you want, I personally
// like to use verot's class upload for that
$this->load->model('dropzone_model');
if (!$this->dropzone_model->add_image($full_path)) {
@unlink($full_path); // remove orphaned image
$this->dz_error('Failed to add image to the database!');
}
$this->dz_success();
}
//
private function dz_error($error) {
$this->output
->set_header("HTTP/1.0 400 Bad Request")
->set_output($error)
->_display();
exit;
}
private function dz_success() {
// don't really need to do anything here?
}
}
class Dropzone_model extends CI_Model {
public function add_image($full_path) {
return $this->db->insert('sometable', array('image' => $full_path));
}
}