ecshop的基本操作指示

来源:互联网 发布:数据规律分析软件 编辑:程序博客网 时间:2024/05/16 11:03

1.1 ecshop中最基本的一些知识与操作

    ecshop中的一些公用函数都会放在includes文件夹里,而这些公用函数几乎我们都可以用来参照一下就能轻松做出我们想要的其他功能了。init.php文件中包含以下代码,$smarty->assign('lang', $_LANG); 来设置ecshop的语言包。

     ② ecshop的数据库操作类是很强大的,一些常用的函数如下:

      ECShop的数据操作类文件是includes/cls_mysql.php,类名是cls_mysql。该类主要提供了下面 一些比较有用的方法:

      getAll($sql)和getAllCached($sql, $cached = 'FILEFIRST'):获取所有记录。
      getRow($sql, $limited = false)和getRowCached($sql, $cached = 'FILEFIRST'):获取单行记录。
      getCol($sqlse)和getColCached($sql, $cached = 'FILEFIRST'):获取某栏位的所有值。
      getOne($sql, $limited = false)和getOneCached($sql, $cached = 'FILEFIRST'):获取单个数值。
      query($sql):执行数据库查询。
      autoExecute($table, $field_values, $mode = 'INSERT', $where = ''):数据库表操作。

      1.获取单条记录
      $GLOBALS['db']->getRow($sql);

      getRow方法用来从数据库中获取满足条件的单行记录,或者说是第一条记录。getRowCached是它的缓存版本,cache key是该方法的第二个参数,如果缓存有效,直接返回缓存结果,否则重新执行数据库查询。缓存功能依此类推。

      例如查询数据库表中的某个字段
      $sql = "SELECT level FROM " . $ecs->table('users') . " WHERE user_name = '$vipaccount' ";
      $row = $GLOBALS['db']->getRow($sql);
      $level = $row['level'];
      2.获取单一字段
      $GLOBALS['db']->getOne($sql);
      例如查询产品总数:
      echo $GLOBALS['db']->getOne(‘SELECT COUNT(*) FROM ‘ . $GLOBALS['ecs']->table(‘goods’) ;
      查询单一数据:

      $sql = "SELECT order_amount FROM " . $GLOBALS['ecs']->table('order_info') . " WHERE order_id = '$order_id'";
      $order_amount = $GLOBALS['db']->getOne($sql);

      3.获取所有记录
      $sql = 'SELECT * FROM ' . $GLOBALS['ecs']->table('suppliers') . ' ORDER BY suppliers_name ASC';

      $GLOBALS['db']->getAll($sql);

       4.获取单行记录

       getCol方法用来从数据库中获取满足条件的某个栏位的所有值

      $sql = "SELECT pay_id FROM " . $GLOBALS['ecs']->table('payment');
      $GLOBALS['db']->getCol($sql);

      getCol()得到是一个一维数组,而  getAll()得到的经常是一个二维数组。

      5.执行sql语句
      $GLOBALS['db']->query($sql);  //执行删除(DELETE),插入(INSERT),更新(UPDATE)等操作可用此方法
      6.把数组元素插入数据库
      $parent['goods_number'] = ’1′;
      $parent['parent_id'] = 0;
      $GLOBALS['db']->autoExecute($GLOBALS['ecs']->table(‘cart’), $parent, ‘INSERT’);//table里面是要插入的表,第二个参数是数组

      7.更新数据(数组形式)

      $user = array(“username” => “ego”);

        $GLOBALS['db']->autoExecute($GLOBALS['ecs']->table('users'), $user, 'UPDATE', "user_id = '$user_id'");    

      执行的SQL: UPDATE ecs_users SET username = ‘ego’ WHERE user_id = $user_id 。如果$user 中有两个元素,则 sql中的set 也写两个。

 

    ③echsop中的模板 

    ecshop有强大的模版机制,ECSHOP 结合Dreamweaver实现了一套模版机制,改动模版不再需要上传,而是在后台稍稍动动手设置一下就可以了。
    ecshop采用smarty模板技术,Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。
    在php文件中使用assign方法把php变量传值给模板文件,例如:
    $smarty->assign(‘action’, $action);  //把php中的变量$action传值给模板文件(*.dwt)中的’action’变量,模板文件可用{$action}来输出此值。
    使用display方法来指定当前的模板文件并输出到该文件显示到客户端,例如:$smarty->display(‘user_passport.dwt’);

    

 

  1.2 补习一下前端的知识

    1.输入框内容只可读。

  

     2.在一张背景图片上显示输入框及文字。eg: 做一个登陆页面,在一个图片上书写用户名 ,密码,登陆按钮等。

 

     3.如何获取下拉框中的value值。

复制代码
<</span>body> <</span>form onsubmit="return formValidate()"> <</span>select name="select"id="order_status" onchange="a()"> <</span>option value="11">--请选择订单状态--</</span>option><</span>option value="0">--未确认--</</span>option> <</span>option value="1">--已确认--</</span>option> </</span>select> <</span>select name="select" id="shipping_status"onchange="b()"> <</span>option value="22">--请选择商品配送情况--</</span>option> <</span>optionvalue="0">--未发货--</</span>option> <</span>option value="1">--已发货--</</span>option><</span>option value="2">--已收货--</</span>option> </</span>select> <</span>input type="submit"value="提交" /> </</span>form> </</span>body> </</span>html>
复制代码

 

  javascript方法如下

复制代码
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <</span>htmlxmlns="http://www.w3.org/1999/xhtml"> <</span>head> <</span>meta http-equiv="Content-Type"content="text/html; charset=gb2312" /> <</span>title>无标题文档</</span>title> <</span>scriptlanguage="JavaScript"> function formValidate() { var t1 =document.getElementByIdx_x("order_status"); alert(t1.options[t1.selectedIndex].value); var t2 =document.getElementByIdx_x("shipping_status"); alert(t2.options[t2.selectedIndex].value); returnfalse; } </</span>script> </</span>head>
复制代码

 这样点击提交按钮之后,便可以将value值得到并alert出选择的值。如果要将得到的  order_status 和 shipping_staus 以隐藏地方式写在页面上,则可以在formValidate()方法里加上如下几句

$firstparam = t1.options[t1.selectedIndex].value; $secondparam = t2.options[t2.selectedIndex].value; document.getElementByIdx_x("firstparam").value =$firstparam ; document.getElementByIdx_x("secondparam").value=$secondparam ;

页面上有如下代码,就可以把下拉框中的值赋给firstparam和secondparam。

<</span>tr> <</span>td><</span>input id="firstparam" name="firstparam" type="hidden" value="" /></</span>td> <</span>td><</span>input id="secondparam" name="secondparam" type="hidden" value=""/></</span>td> </</span>tr>

最后将页面的值传递给php代码中。这样写可以得到这两个参数。

$order_status = $_POST['firstparam']; $shipping_status = $_POST['secondparam'];

到此,整个过程完成:用户选择页面下拉框中的值后可以传递给php代码用来进行下一步的操作,比如写sql语句。

    4.检查表单输入的密码是否相同的js函数

    

  1.3 如何在ecshop后台增加左侧导航栏

    1.后台添加导航

      在languages\zh_cn\admin\common.php中增加

 

$_LANG['99_meicheng'] = ‘批量管理’; $_LANG['01_meicheng_user'] = ‘批量添加用户’;

 

    2.添加导航链接

      在 admin\includes\inc_menu.php中增加

$modules['99_meicheng']['01_meicheng_user'] = ‘mc_user.php’;

其中 mc_user.php就是在admin文件夹中控制此次操作的php文件。

  3.后续要添加的有 financial_export.htm,此文件用来展示。在admin\templates中。还有一个是语言文件,名称与admin中的php文件名称相同。在languages\zh_cn\admin中。 

  1.4 ecshop中读取csv文件内容

   1.其实这个可以称的上是php中读取csv文件内容。例子是读取csv中的用户信息,后台注册用户。

    用户操作界面代码:

复制代码
<</span>div class="main-div"> <</span>form action="ck_user.php" method="post"enctype="multipart/form-data" name="theForm" > <</span>table width="100%" id="general-table"><</span>tbody id="1" > <</span>tr> <</span>td class="label">批量导入用户:</</span>td> <</span>td><</span>input name="upfile" type="file" id="upfile" size='35' />   <</span>spanstyle="color:#F00;">*</</span>span>文本为csv格式的:例 user.csv </</span>td> </</span>tr></</span>tbody> <</span>tr> <</span>td class="label"> </</span>td> <</span>td> <</span>inputtype="submit" value="批量添加用户" class="button" /> <</span>input type="hidden" name="act"value="mc_add" /> </</span>td> </</span>tr> </</span>table> </</span>form> </</span>div>
复制代码

其中 enctype="multipart/form-data" 这一点要注意,因为提交的数量是cvs文件。

  后台读取cvs文件以及插入数据库中的代码:内容较多,请稳步这里  http://www.cnblogs.com/chenkaiadd/archive/2013/05/25/3099027.html

   

  

  1.5 ecshop中将数据库表中的数据导出成csv文件

  1.6 ecshop 中前端分页 (包含上架时间、价格、更新时间这一栏的链接、还有页中前一页、后一页、输入数字后点击确定跳转到指定页)

  1.7 ecshop 中后台分页

 

  1.8 ecshop 中ajax使用

    ①首先ecshop是如何定义ajax对象的。

       ecshop中的ajax对象是在js/transport.js文件中定义的。里面是ajax对象文件。声明了一个var Ajax = Transport;对象和一个方法Ajax.call = Transport.run;

    ②ecshop中ajax可以使用两种方式传递数据.一种是get方式,一种是post方式.

    Ajax.call( 'user.php?act=is_registered', 'username=' + username, registed_callback , 'GET', 'TEXT', truetrue );     Ajax.call('user.php?act=return_to_cart', 'order_id=' + orderId, returnToCartResponse, 'POST', 'JSON');

 

    ③ecshop中的 ajax可以是传递text数据,也可以是一个json对象。比如以下代码 里面的goods就是对象.而且是靠json来传递的。返回的结果result也是对象.

复制代码
goods.quick = quick; goods.spec = spec_arr; goods.goods_id = goodsId; goods.number = number; goods.parent = (typeof(parentId) == "undefined") ? 0 : parseInt(parentId); Ajax.call('flow.php?step=add_to_cart', 'goods=' + goods.toJSONString(), addToCartResponse, 'POST', 'JSON');
复制代码

    ④ecshop ajax函数里面.第三个参数就是回掉函数的名称。比如以上代码addToCartResponse 这个函数就是ajax处理结果的回调函数.

    ⑤在ecshop的php代码中,一般是通过get或者post方式来接受函数。比如以下例子,如果接受的是对象。还需要用json数据格式来处理.比如以下

include_once('includes/cls_json.php'); $_POST['goods'] = json_str_iconv($_POST['goods']); 处理的返回结果,也需要是json格式发送给js die($json->encode($result));

下面以ecshop中的用户注册中验证用户名是否存在来分析。

在user_passport.dwt页面中显示注册界面 

复制代码
<</span>form action="user.php" method="post" name="formUser" onsubmit="return register();"><</span>table width="100%" border="0" align="left" cellpadding="5" cellspacing="3"> <</span>tr><</span>td width="13%" align="right">{$lang.label_username}</</span>td> <</span>td width="87%"><</span>input name="username" type="text" size="25" id="username"onblur="is_registered(this.value);" class="inputBg"/> <</span>span id="username_notice"style="color:#FF0000"> *</</span>span> </</span>td> </</span>tr>    <</span>tr>  <</span>td> </</span>td>   <</span>td align="left">   <</span>input name="act"type="hidden" value="act_register" >    <</span>input type="hidden" name="back_act" value="{$back_act}" />    <</span>input name="Submit" type="submit" value="" class="us_Submit_reg">   </</span>td>    </</span>tr> </</span>table> </</span>form>
复制代码

在页面中有  onblur 这个方法,鼠标离开后调用这个方法。然后在user.js中会有is_registered(username)这个方法的实现

复制代码
function is_registered( username ) { var submit_disabled = falsevar unlen = username.replace(/[^\x00-\xff]/g, "**").length; if ( username == '' ) { document.getElementByIdx_x('username_notice').innerHTML = msg_un_blank; var submit_disabled =true; } if ( !chkstr( username ) ) { document.getElementByIdx_x('username_notice').innerHTML =msg_un_format; var submit_disabled = true; } if ( unlen < 3 ) { document.getElementByIdx_x('username_notice').innerHTML = username_shorter; var submit_disabled =true; } if ( unlen > 14 ) { document.getElementByIdx_x('username_notice').innerHTML =msg_un_length; var submit_disabled = true; } if ( submit_disabled ) { document.forms['formUser'].elements['Submit'].disabled = 'disabled'return false; } Ajax.call('user.php?act=is_registered', 'username=' + username, registed_callback , 'GET', 'TEXT', true,true ); }
复制代码

该函数调用 ajax方法。
Ajax.call( 'user.php?act=is_registered', 'username=' + username, registed_callback , 'GET', 'TEXT', true, true ); ajax方法调用  user.php中的  elseif ($action == 'is_registered')  于是user.php页面中有如下代码,主要是调用了check_user 这个方法去数据库查找是否用户名已经注册。

复制代码
elseif ($action == 'is_registered') { include_once(ROOT_PATH . 'includes/lib_passport.php'); $username = trim($_GET['username']); $username = json_str_iconv($username);  //将JSON传递的参数转码 if ($user->check_user($username) || admin_registered($username)) { echo 'false'; } else { echo 'true'; } }
复制代码

check_user方法调用的是 \includes\modules\integrates\ecshop.php里的,不是父类 integrate.php 里面的方法。检查指定用户是否存在及密码是否正确(重载基类check_user函数,支持zc加密方法). 

ajax方法中的第三个参数是一个回调函数的名称,该函数的实现也是在 user.js中。他的参数result正是上面函数echo的值(具体原因我暂时还不明白)

复制代码
function registed_callback(result) { if ( result == "true" ) { document.getElementByIdx_x('username_notice').innerHTML = msg_can_rg; document.forms['formUser'].elements['Submit'].disabled = ''; } else { document.getElementByIdx_x('username_notice').innerHTML = msg_un_registered; document.forms['formUser'].elements['Submit'].disabled = 'disabled'; } }
复制代码

该方法通过返回的结果 来判断在提示信息的文本框中到底显示什么内容。

 在这里看看ajax的介绍,总结的不错。

 

这几天出现了一个问题,就是用自带的ajax.call函数不好用,于是想自己写一个,虽然最后证明自己写完了问题依然存在,可能不是ajax的方法,但是过程还是记录下来。

前台页面代码

<</span>input type="text" onblur=" is_specialed(this.value);

js 里方法如下

复制代码
function is_specialed( service_special ) { if ( service_special == '向店内工作人员获取服务专员号'|| service_special == '') { document.getElementByIdx_x('special_error').innerHTML = "该服务专员号不存在2"; document.getElementByIdx_x('special_error').className = "error"; document.forms['formRegist'].elements['ifCanReg'].value = "1"; } // Ajax.call( 'user.php?act=is_specialed', 'service_special=' + service_special, specialed_callback , 'GET', 'TEXT', true, true ); //加上 自己写的ajax //调用ajaxstart xmlHttp=GetXmlHttpObject(); if (xmlHttp==null) { alert ("您的浏览器不支持AJAX!"); return; } var url="user.php?act=is_specialed"; url=url+"&sid="+Math.random() + "&service_special="+ service_special;xmlHttp.onreadystatechange=function () { //请求状态是4的时候,请求处理完成 if(xmlHttp.readyState==4) { //response是得到的后台输出数据。 var response = xmlHttp.responseText ;//这里将用回调函数用来显示错误提示信息 specialed_callback(response); } } xmlHttp.open("get",url,true); xmlHttp.send(); //调用ajax end //创建xmlhttprequest对象 functionGetXmlHttpObject() { var xmlHttp=nulltry { // Firefox, Opera 8.0+, Safari xmlHttp=newXMLHttpRequest(); } catch (e) { // Internet Explorer try { xmlHttp=newActiveXObject("Msxml2.XMLHTTP"); } catch (e) { xmlHttp=new ActiveXObject("Microsoft.XMLHTTP"); } }return xmlHttp; } function specialed_callback(result) { result = result.replace(/\s/g,""); if ( result == 'true' ) { //document.forms['formRegist'].elements['registsubmit'].disabled = '';document.forms['formRegist'].elements['ifCanReg'].value = "0"; } else { document.getElementByIdx_x('special_error').innerHTML = "该服务专员号不存在"; document.getElementByIdx_x('special_error').className = "error";//document.forms['formRegist'].elements['registsubmit'].disabled = 'disabled';document.forms['formRegist'].elements['ifCanReg'].value = "1"; } }
复制代码

ajax里面使用的是get方法提交的。后台user.js里面可以通过$_GET['service_special'] 和$REQUEST['service_special']来得到。如果用ajax用post方法提交,则可以这样写

xmlHttp.open("POST",url,true); xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");//如果需要像HTML表单那样POST 数据用 setRequestHeader() 来添加 HTTP 头xmlHttp.send("service_special="+service_special);

相应的user.php 利用 $_POST['service_special'] 或$_REQUEST['service_special']来得到数据。代码为

复制代码
elseif ($action == 'is_specialed') { include_once(ROOT_PATH . 'includes/lib_passport.php'); //$service_special = trim($_GET['service_special']); $service_special = trim($_POST['service_special']); //$service_special = trim($_REQUEST['service_special']); //$username = json_str_iconv($username); $sqlspecial = 'SELECT level FROM ' . $GLOBALS['ecs']->table('users') . " WHERE user_name = '$service_special'"$row =$GLOBALS['db']->getRow($sqlspecial); $level = $row['level']; if($level ==1){ echo 'true'; } else { echo 'false'; } }
复制代码

关于用get还是post 官方的说法是

与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。

然而,在以下情况中,请使用 POST 请求:

  • 无法使用缓存文件(更新服务器上的文件或数据库)
  • 向服务器发送大量数据(POST 没有数据量限制)
  • 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

 

 

  1.9 ecshop中的后台权限管理

    ①以 admin\group_buy.php为例来说明权限的运用 。首先说一下,ecshop中每个php文件的头两行都是引用这样两句话,算是初始化吧。

define('IN_ECS', true); require(dirname(__FILE__) . '/includes/init.php');

 

  随后我们看到,后台每个文件在执行方法之前都会有类似这样一个权限检查的方法

admin_priv('group_by');

    ②该方法的实现在admin\includes\lib_main.php中,具体如下图。

复制代码
function admin_priv($priv_str$msg_type = '' , $msg_output = true) { global $_LANGif($_SESSION['action_list'] == 'all') { return true; } if (strpos(',' . $_SESSION['action_list'] . ',', ',' . $priv_str . ',') === false) { $link[] = array('text' => $_LANG['go_back'], 'href' => 'javascript:history.back(-1)'); if ( $msg_output) { sys_msg($_LANG['priv_error'], 0, $link); }return false; } else { return true; } }
复制代码

   从这里我们可以看出,这里运用了php中的  strpos函数。该函数作用为: 返回字符串在另一个字符串中第一次出现的位置。如果没有找到该字符串,则返回 false。

   语法为:strpos(string,find,start) 其中,string 为必需,是被搜索的字符串,find为必需,是要查找的字符。start为可选,是开始搜索的位置。另外一个知识点:如果需要对大小写不敏感的操作,则可以用函数 stripos() 来解决。

  还有一个知识点是php中的   ==是等值,是不判断二者是否是同一数据类型,而  ===是等价它不但要求二者值相等,而且还要求它们的数据类型也相同。

  从类的注释中我们已经很清楚。该函数的功能就是查看 ,'group_by',   这个字符串在不在当前用户的session 中 ,如果不在,则提示用户   对不起,您没有执行此项操作的权限!   并将函数结果返回false,此时程序结束。不能进行到下一步。需要说明的是 admin这个用户,默认的权限为 'all'  ,这一点可以在数据库中的表admin_user中的 action_list 这一字段中对应的值看出。 其它管理员的权限则是由 admin在后台管理的【管理员列表】这一菜单栏下分配的权限,效果如图,一旦打上勾,则具有了该权限,也即admin_user表中的 action_list 字段值就增加一个内容。

   ③那么系统是如何将数据库中的这些action_list 里的值存放到管理员的session中的呢?

    控制后台登陆是在admin\privilege.php里 elseif ($_REQUEST['act'] == 'signin') 方法里有这样一段代码。

复制代码
  $_POST['username'] = isset($_POST['username']) ? trim($_POST['username']) : '';$_POST['password'] = isset($_POST['password']) ? trim($_POST['password']) : ''$sql = "SELECT user_id, user_name, password, last_login, action_list, last_login". " FROM " . $ecs->table('admin_user') . " WHERE user_name = '" . $_POST['username']. "' AND password = '" .md5($_POST['password']) . "'"$row = $db->getRow($sql); if ($row) { // 登录成功set_admin_session($row['user_id'], $row['user_name'], $row['action_list'], $row['last_login']);      .......
复制代码

  可以看到管理员登陆时,利用 set_admin_session 这个方法将数据库中的action_list中的字段设置到SESSION中。

  在admin\includes\lib_main.php里有这个方法的实现。

复制代码
function set_admin_session($user_id$username$action_list$last_time) { $_SESSION['admin_id'] = $user_id$_SESSION['admin_name'] = $username$_SESSION['action_list'] = $action_list;$_SESSION['last_check'] = $last_time// 用于保存最后一次检查订单的时间 }
复制代码

  至此,可以看到整个流程已经非常清楚。管理员在数据库表中有一个字段 action_list, 管理员登陆之后将这个数据设置到$_SESSION 中。以后每次操作时都会调用admin_priv() 这个函数。来检验当前用户是否具有这个权限,如果没有则返回false ,程序终止。

  ④至于上图中点击勾后,便具有该权限。是如何实现的呢,权限等级,子权限等是如何实现的呢?参见:

    ⑤ ecshop中的_SESSION工作原理。

   在ec_shop中有两个表(ecs_sessions和ecs_sessions_data),这两个表用于记录、管理session,默认情况下使用的是myISAM引擎。尝试将这两个表改成memory引擎,提高session读取效率。 

  1、将两个表复制,做好备份:
  CREATE TABLE ecs_sessions_ori SELECT * FROM ecs_sessions;
  CREATE TABLE ecs_sessions_data_ori SELECT * FROM ecs_sessions_data;

  2、将原有的两张表更改成内存表:
  ALTER TABLE `ecs_sessions` ENGINE = MEMORY

  3、ecs_sessions_data表不能更改成内存表:
  因为其中含有text字段,因而这个表不能被作为内存表使用。暂时先不改这个表了。 参考如下Memory引擎的使用场景及特点:

  能像会话(Session)或缓存(Caching)一样方便操作和管理。
  充分发挥内存引擎的特点:高速度,低延迟。
  只读或读为主的访问模式(不适合频繁写)。
  但是内存表的性能受制于单线程的执行效率和写操作时的表锁开销,这就限制了内存表高负载时的扩展性,特别是混合写操作的并发处理。此外,内存表中的数据在服务器重启后会丢失。

  从这里我们可以暂时推断出,可能ecshop中要建这两个表的目的是为了提高效率。这两个表有一个不同点就是  `data` char(255) NOT NULL COMMENT '序列化后的session数据,如果session数据大于255则将数据存到表ecs_sessions_data,此处为空', 而ecs_sessions_data 里的 `data` longtext NOT NULL COMMENT 'session序列化后的数据'。  

  这里又有另一个知识点: ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='session数据表(超过255字节的session内容会保存在该表)';    engine 的意义:参见另一篇:http://www.cnblogs.com/chenkaiadd/archive/2013/04/21/3033964.html

  下面开始讲解 ecshop中的session的原理。

  PHP 中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可用。在函数或方法中无需执行 global $variable; 来访问它们。

$GLOBALS     $_SERVER     $_GET     $_POST     $_FILES     $_COOKIE     $_SESSION    $_REQUEST     $_ENV   这其中就有$_SESSION 

 

 

 

   1.9 ecshop中商品筛选下的品牌显示(左连接的SQL语句的写法)

  ①先看效果图,即点击某一产品分类后,将数据库中的这一类产品的品牌展示出来。
0 0
原创粉丝点击