php后台商品添加,需要两个表单,一个用于提交上传图片,一个用于提交商品数据到数据库。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php后台商品添加,需要两个表单,一个用于提交上传图片,一个用于提交商品数据到数据库。相关的知识,希望对你有一定的参考价值。

如图,需要用到两个提交按钮,但表单不能嵌套,该怎么办啊?,上传倒是不用立刻提交,可以和其他数据一起提交,但是我要检验上传的图片是否成功,如果图片上传失败,其他数据也提交不了,那不浪费时间吗?

看你图片上的表单设计,你都有“上传”按钮了,这就是等于已经把图片上传上去了(而此时表单的其他数据还没有提交)

一般来说,php做商品添加,表单的其他数据和图片的上传都是一起来提交的,而如果你要检查图片是否上传成功来决定是否提交其他表单数据的话,可以这样设计:
一、你现在的这个表单不用改,只需要在最下面的那个“确定”按钮上加个JS判断,判断一下上面的图片是否上传成功(如果图片上传这里成功上传了图片,你返回一个图片的保存路径及图片名称到一个隐藏的文本框里面,然后在“确定”按钮的JS代码里去取这个隐藏的文本框的值,如果有值就可以判定这个图片是上传成功的了,否则失败则整个表单的数据都不能提交)

二、图片上传框这里,确实因为表单不能嵌套,所以这个位置你就要采用一个iframe来加载另一个上传图片的页面(这个上传图片的页面代码很简单,就是那个图片上传框(当然你得加一些权限判断不然就会是一个上传漏洞了),然后写相应的上传代码把图片上传上去最后返回上传后的图片路径及文件名等信息,使用
parent.表单名.隐藏文本框名.value='xxxx.jpg'
这个JS语句来实现把你上传的图片信息保存到你的隐藏文本框里。
上面这句parent...语句的详解如下:
a.由于你的图片上传页面是放在iframe里的,因此你要把iframe里的页面的内容保存到上一层页面(即你这个添加商品的页面,也就是这个加了iframe代码的页面)
举例个吧:
你添加商品的页面文件名是a.php,在a.php的表单里你加了一个<iframe src="b.php"></iframe>
这里面的b.php就是你的上传图片的页面(在b.php中就是你正常的上传图片的表单),另外你接收上传及处理上传的程序都是在这个iframe里面完成的。。

这样应该明白了吧。既然你的上传后的返回值是在iframe里的页面中的,那要想把它保存到a.php这个页面的一个隐藏文本框里,就要使用parent了。。。
所以上面那个js语句是:parent.表单名....

b.这个js语句parent.表单名.隐藏文本框名.value='xxx'中的“表单名”、“隐藏文本框名”,是指的a.php这个页面的表单名哦。
比如你a.php的表单是<form name="addpro_form" method="post">,那么这个JS语句中的表单名也就是addpro_form。隐藏文本框同理。

这样,你明白了吧?

我写个简单的实例你看看:
a.php的代码:
<form name="addpro_form" method="post" action="a.php?act=save">
商品名称:<input type="text" name="pro_name" /><br />
商品价格:<input type="text" name="pro_price" /><br />
商品图片:<input type="hidden" name="pro_img" />
<iframe width="500" height="50" src="b.php"></iframe><br />
商品说明:<textarea name="pro_intro"></textarea><br />
<input type="submit" value="确定" />
</form>

以上是a.php的代表,也就是整个表单,其中表单名是addpro_form,隐藏文本框名是pro_img。

接着写b.php的:
<form name="upfile_form" method="post" action="upload.php" enctype="multipart/form-data">
<input type="file" name="upimages"><input type="submit" value="上传">
</form>
b.php的页面很简单就是一个上传表单而已

然后upload.php是用来接收上传的图片并返回值的:
<?php
//以下是PHP上传图片的代码(我就不写了)
......
//假设上传后得到图片名称
$imgname="111.jpg";
?>
<script type="text/javascript">
window.onload=parent.addpro_form.pro_img.value='<?php echo $imgname; ?>';
</script>

好了,upload.php的代码也写完了,上面一段php代码是上传图片最后得到上传后的图片名称,接着用一段js代码把图片名称返回到上一页去。
参考技术A 上传成功后,你会返回一个路径到这个页面.这个页面应该有一个隐藏的表单.
然后你点提交的时候,判断这个隐藏的表单内容是否为空.如果为空就提示他还没上传图片.
你整个的提交.必须是图片上传完毕之后才可以.
参考技术B 虽然表单不能嵌套提交,但是你可以用隐藏的表单域来实现啊,具体你查下就知道了,很简单的

PHP.25-TP框架商城应用实例-后台1-添加商品功能钩子函数在线编辑器过滤XSS上传图片并生成缩略图

添加商品功能

  1、创建商品控制器【C】  /www.test.com/shop/Admin/Controller/GoodsController.class.php

<?php
namespace Admin\\Controller;
use Think\\Controller;

//后台添加商品功能控制器
class GoodsController extends Controller 
{   
    //显示和处理表单
    public function add()
    {
        //判断用户是否提交了表单(如果提交了,就在if中处理表单,否则显示表单)
        if(IS_POST){    //IS_POST:TP自带常量:当前是否POST请求
            $model = D(\'goods\');    //D()实例化/Model/中模型goods
            //2.CREATE方法:a.接收数据并保存到模型中  b.根据模型中定义的规则验证表单
            /**
            *第一个参数:要接收的数据默认是$_POST
            *第二个参数:表单的类型。当前是添加还是修改的表单,1:添加    2:修改
            *$_POST:表单中原始的数据,I(\'post.\'):过滤后的$_POST的数据,过滤XSS攻击
            **/
            if($model->create(I(\'post\'), 1))
            {
                //插入数据库中
                if($model->add())
                {
                    //显示成功信息并等待1秒之后跳转
                    $this->success(\'操作成功!\', U(\'lst\'));
                    exit;
                }
            }
            //如果上面失败了在这里处理失败的请求
            //从模型中取出失败的原因
            $error = $model->getError();
            //由控制器显示错误信息,并在3秒跳回上一个页面[error()默认3秒]
            $this->error($error);
        }
        //显示表单
        $this->display();
    }
    
    //商品列表页
    public function lst()
    {
        echo "列表页";
    }
}
GoodsController.class.php

注意:控制器中的代码都很少,具体的业务代码都写到模型中,所有的控制器其他curd的代码基本相同,区别就是生成不同的模型

  2、创建商品模型【M】  /www.test.com/shop/Admin/Model/GoodsModel.class.php

<?php
    namespace Admin\\Model;
    use Think\\Model;
    
    class GoodsModel extends Model
    {    
        //添加调用create方法允许接收的字段
        protected $insertFields = \'goods_name,market_price,shop_price,is_on_sale,goods_desc\';
        //定义验证规则    validate:TP模型层提供的一种数据验证方法 
            //a.静态方式:在模型类里面通过$_validate属性定义验证规则。b.动态方式:使用模型类的validate方法动态创建自动验证规则 
            //定义好验证规则后,就可以在使用create方法创建数据对象的时候自动调用
        protected $_validate = array(
            array(\'goods_name\', \'require\', \'商品名称不能为空!\', \'1\'),
            array(\'market_price\', \'currency\', \'市场价格必须是货币!\', \'1\'),
            array(\'shop_price\', \'currency\', \'本店价格必须是货币类型!\', \'1\'),
        );
        
        //钩子方法_before_insert:添加前插入,在添加前会自动调用
        //第一个参数:表单中即将要被插入数据库中的数据=>数组
        //&按引用传递:函数外部的变量的值要在函数内部修改的话,必须按引用传递,除非传递的为对象,因为对象默认按引用传递
        protected function _before_insert(&$data, $option)
        {
            /**************处理LOGO******************/
            //判断有没有选择图片
            if($_FILES[\'logo\'][\'error\'] == 0){
                $upload = new \\Think\\Upload();    //实例化上传类
                $upload->maxSize = 1024*1024;    //1M
                $upload->exts = array(\'jpg\', \'gif\', \'png\', \'jpeg\');    //设置附件上传类型
                $upload->rootPath = \'./Public/Uploads/\';        //设置附件上传根目录
                $upload->savePath = \'Goods/\';        //设置附件上传子目录
                //上传文件
                $info =  $upload->upload();
                if(!$info){
                    //获取失败原因把错误信息保存到模型的error属性中,然后在控制器里调用$model—>getError()获取错误信息并由控制器打印
                    $this->error = $upload->getError();
                    return FALSE;
                }else{
                    //上传成功,并生成缩略图
                    //先拼成原图上的路径
                    $logo = $info[\'logo\'][\'savepath\'] . $info[\'logo\'][\'savename\'];
                    //拼出缩略图的路径和名称
                    $mbiglogo = $info[\'logo\'][\'savepath\'] .\'mbig_\'. $info[\'logo\'][\'savename\'];
                    $biglogo = $info[\'logo\'][\'savepath\'] .\'big_\'. $info[\'logo\'][\'savename\'];
                    $midlogo = $info[\'logo\'][\'savepath\'] .\'mid_\'. $info[\'logo\'][\'savename\'];
                    $smlogo = $info[\'logo\'][\'savepath\'] .\'sm_\'. $info[\'logo\'][\'savename\'];
                    $image = new \\Think\\Image();
                    //打开要生成缩略图的图片
                    $image->open(\'./Public/Uploads/\'.$logo);
                    //生成缩略图
                    $image->thumb(700, 700)->save(\'./Public/Uploads/\'.$mbiglogo);
                    $image->thumb(350, 350)->save(\'./Public/Uploads/\'.$biglogo);
                    $image->thumb(130, 130)->save(\'./Public/Uploads/\'.$midlogo);
                    $image->thumb(50, 50)->save(\'./Public/Uploads/\'.$smlogo);
                    /**************把路径放到表单中*****************/
                    $data[\'logo\'] = $logo;
                    $data[\'mbig_logo\'] = $mbiglogo;
                    $data[\'big_logo\'] = $biglogo;
                    $data[\'mid_logo\'] = $midlogo;
                    $data[\'sm_logo\'] = $smlogo;
                }
            }
            //获取当前时间并添加到表单中,这样就会插入数据库中
            $data[\'addtime\'] = date(\'Y-m-d H:i:s\', time());
            //过滤这个字段
            $data[\'goods_desc\'] = removeXSS($_POST[\'goods_desc\']);
        }
    }
?>
GoodsModel.class.php

  3、创建一个添加商品的表单【V】  /www.test.com/shop/Admin/View/Goods/add.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ECSHOP 管理中心 - 添加新商品 </title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />
<link href="__PUB__/Admin/Styles/general.css" rel="stylesheet" type="text/css" />
<link href="__PUB__/Admin/Styles/main.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>
    <span class="action-span"><a href="__GROUP__/Goods/goodsList">商品列表</a>
    </span>
    <span class="action-span1"><a href="__GROUP__">ECSHOP 管理中心</a></span>
    <span id="search_id" class="action-span1"> - 添加新商品 </span>
    <div style="clear:both"></div>
</h1>

<div class="tab-div">
    <div id="tabbar-div">
        <p>
            <span class="tab-front" id="general-tab">通用信息</span>
        </p>
    </div>
    <div id="tabbody-div">
        <form enctype="multipart/form-data" action="__SELF__" method="post" >
            <table width="90%" id="general-table" align="center">
                <tr>
                    <td class="label">商品名称:</td>
                    <td><input type="text" name="goods_name" value=""size="30" />
                    <span class="require-field">*</span></td>
                </tr>
                <tr>
                    <td class="label">市场售价:</td>
                    <td>
                        <input type="text" name="market_price" value="0" size="20" />
                         <span class="require-field">*</span>
                    </td>
                </tr>
                <tr>
                    <td class="label">本店售价:</td>
                    <td>
                        <input type="text" name="shop_price" value="0" size="20"/>
                        <span class="require-field">*</span>
                    </td>
                </tr> 
                <tr>
                    <td class="label">是否上架:</td>
                    <td>
                        <input type="radio" name="is_on_sale" value="1" checked="checked" /><input type="radio" name="is_on_sale" value="0" /></td>
                </tr>
                <tr>
                    <td class="label">商品描述:</td>
                    <td>
                        <textarea id="goods_desc" name="goods_desc"></textarea>
                    </td>
                </tr>
            </table>
            <div class="button-div">
                <input type="submit" value=" 确定 " class="button"/>
                <input type="reset" value=" 重置 " class="button" />
            </div>
        </form>
    </div>
</div>

<div id="footer">
共执行 9 个查询,用时 0.025161 秒,Gzip 已禁用,内存占用 3.258 MB<br />
版权所有 &copy; 2005-2012 上海商派网络科技有限公司,并保留所有权利。</div>
</body>
</html>

<!--导入在线编辑器-->
   <link href="__PUB__/umeditor1.2.3-utf8-php/themes/default/css/umeditor.css" type="text/css" rel="stylesheet">
    <script type="text/javascript" src="__PUB__/umeditor1.2.3-utf8-php/third-party/jquery.min.js"></script>
    <script type="text/javascript" src="__PUB__/umeditor1.2.3-utf8-php/third-party/template.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="__PUB__/umeditor1.2.3-utf8-php/umeditor.config.js"></script>
    <script type="text/javascript" charset="utf-8" src="__PUB__/umeditor1.2.3-utf8-php/umeditor.min.js"></script>
    <script type="text/javascript" src="__PUB__/umeditor1.2.3-utf8-php/lang/zh-cn/zh-cn.js"></script>
    <script>
        UM.getEditor(\'goods_desc\', {
            initialFrameWidth: "100%",
            initialFrameHeight: 150
        });
    </script>
add.html

   注意:修改Js、Images、Styles等路径。提交到当前方法add,一般为action=__SELF__;商品名称等提交数据名要与数据库中的表字段名相同可通过配置文件修改,以防止数据库表字段名被人窥探。

  4、修改配置文件添加DB配置,连接数据库  /www.test.com/shop/Common/Conf/conf.php

Conf.php

  注意问题:

1.模型GoodsModel.class.php中表单规则的第四个参数1:代表必须验证,不写会默认为0【存在字段就验证】,防止用户伪造不合法表单

2.在GoodsModel.class.php中,防止表单出现非法字段,以免数据库被插入非法字段数据【例如:传入超额id(自增),导致后继数据无法插入】

 3.在TP中接收用户的数据必须使用I函数接收:

用法:

      $_GET[‘name’]  -->   I(‘get.name’);

      $_POST[‘name’]   -->  I(‘post.name’);

      $_POST        -->   I(‘post.’);

 在conf.php配置文件中重新定义过滤函数

4.钩子函数:tp提供的可在数据添加、修改、删除之前或者之后要执行某些动作代码,在模型类中使用,类似自定义函数

  如:数据在添加到数据之前先获取当前系统时间添加到表单中

    基本上所有的代码都写在模型中,还有其他的钩子方法:

      _before_insert(&$data, $option)  _after_insert($data, $option)

      _before_update(&$data, $option)  _after_update($data, $option)

      _before_delete($option)      _after_delete($option)

      比如上传图片的代码等等。

5.在线编辑器--UM

 下载,解压到Public

 在需要放编辑器的页面底部(可以是其他地方,js代码一般放底部),首先要先给需要编辑器的地方加个id,如:<textarea id="goods_desc">

    :记得修改路径

6.文本域过滤XSS

下载HtmlPrifier,解压,将library取到根目录改名为HtmlPrifier,在/www.39.com/Common/Common/functions.php指定函数调用HtmlPrifier

 <?php
    //有选择性的过滤XSS --》说明:性能非常低-》尽量少用
    function removeXSS($data)
    {
        require_once \'./HtmlPurifier.auto.php\';
        
        $_clean_xss_config = HTMLPurifier_Config::createDefault();
        $_clean_xss_config->set(\'Core.Encoding\', \'UTF-8\');
        //设置保留的标签
        $_clean_xss_config->set(\'HTML.Allowed\',\'div,b,strong,i,em,a[href|title],ul,ol,li,p[style],br,span[style],img[width|height|alt|src]\');
        $_clean_xss_config->set(\'CSS.AllowedProperties\', \'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align\');
        $_clean_xss_config->set(\'HTML.TargetBlank\', TRUE);
        $_clean_xss_obj = new HTMLPurifier($_clean_xss_config);
        //执行过滤
        return $_clean_xss_obj->purify($data);
    }
 ?>
removeXSS

 

  

  添加商品时为商品上传图片并生成缩略图

作用:1. 节省带宽;2. 浏览加载快,提高用户体验

根据前台页面图片尺寸需要,决定生成几张缩略图以及其尺寸。如:列表页:130*130;商品详情页:350*350;商品详情页小图:50*50;放大镜:700*700

1、先在数据库中添加好相应的字段[ALTER TABLE]

ALTER TABLE p39_goods ADD logo varchar(150) not null default \'\' comment \'原图\';
ALTER TABLE p39_goods ADD sm_logo varchar(150) not null default \'\' comment \'小图\';
ALTER TABLE p39_goods ADD mid_logo varchar(150) not null default \'\' comment \'中图\';
ALTER TABLE p39_goods ADD big_logo varchar(150) not null default \'\' comment \'大图\';
ALTER TABLE p39_goods ADD mbig_logo varchar(150) not null default \'\' comment \'特大图\';

    2、在页面中add.html中增加文件上传按钮,注意表单一定要加上enctype="multipart/form-data" 才能上传文件

 3、在模型类GoodsModel.class.php中的_before_insert()函数中,执行上传和缩略图

在tp手册中有实例

 

protected function _before_insert(&$data, $option)
        {
            /**************处理LOGO******************/
            //判断有没有选择图片
            if($_FILES[\'logo\'][\'error\'] == 0){
                $upload = new \\Think\\Upload();    //实例化上传类
                $upload->maxSize = 1024*1024;    //1M
                $upload->exts = array(\'jpg\', \'gif\', \'png\', \'jpeg\');    //设置附件上传类型
                $upload->rootPath = \'./Public/Uploads/\';        //设置附件上传根目录
                $upload->savePath = \'Goods/\';        //设置附件上传子目录
                //上传文件
                $info =  $upload->upload();
                if(!$info){
                    //获取失败原因把错误信息保存到模型的error属性中,然后在控制器里调用$model—>getError()获取错误信息并由控制器打印
                    $this->error = $upload->getError();
                    return FALSE;
                }else{
                    //上传成功,并生成缩略图
                    //先拼成原图上的路径
                    $logo = $info[\'logo\'][\'savepath\'] . $info[\'logo\'][\'savename\'];
                    //拼出缩略图的路径和名称
                    $mbiglogo = $info[\'logo\'][\'savepath\'] .\'mbig_\'. $info[\'logo\'][\'savename\'];
                    $biglogo = $info[\'logo\'][\'savepath\'] .\'big_\'. $info[\'logo\'][\'savename\'];
                    $midlogo = $info[\'logo\'][\'savepath\'] .\'mid_\'. $info[\'logo\'][\'savename\'];
                    $smlogo = $info[\'logo\'][\'savepath\'] .\'sm_\'. $info[\'logo\'][\'savename\'];
                    $image = new \\Think\\Image();
                    //打开要生成缩略图的图片
                    $image->open(\'./Public/Uploads/\'.$logo);
                    //生成缩略图
                    $image->thumb(700, 700)->save(\'./Public/Uploads/\'.$mbiglogo);
                    $image->thumb(350, 350)->save(\'./Public/Uploads/\'.$biglogo);
                    $image->thumb(130, 130)->save(\'./Public/Uploads/\'.$midlogo);
                    $image->thumb(50, 50)->save(\'./Public/Uploads/\'.$smlogo);
                    /**************把路径放到表单中*****************/
                    $data[\'logo\'] = $logo;
                    $data[\'mbig_logo\'] = $mbiglogo;
                    $data[\'big_logo\'] = $biglogo;
                    $data[\'mid_logo\'] = $midlogo;
                    $data[\'sm_logo\'] = $smlogo;
                }
            }
            //获取当前时间并添加到表单中,这样就会插入数据库中
            $data[\'addtime\'] = date(\'Y-m-d H:i:s\', time());
            //过滤这个字段
            $data[\'goods_desc\'] = removeXSS($_POST[\'goods_desc\']);
        }
图片处理

 

 

 

以上是关于php后台商品添加,需要两个表单,一个用于提交上传图片,一个用于提交商品数据到数据库。的主要内容,如果未能解决你的问题,请参考以下文章

app中 模拟表单上传图片

用python复制form表单的问题?

PHP表单中含上传图片的问题,哪里不对

完成后台管理系统功能KindEditor富文本编辑器的使用以及商品添加的实现

用python复制form表单的一个问题?

VUE项目实战56商品添加功能-提交添加的商品