js中with的用法

with语句用于设置代码在特定对象中的作用域。

它的语法:

with(expression)statement

例如:

var sMessage = "hello";

with(sMessage){

    alert(toUpperCase());//输出"HELLO"

}

在这个例子中,with语句用于字符串,所以在调用toUpperCase()方法时,浏览器将检查该方法是否是本地的函数。如果不是,它将检查伪对象sMessage,看toUpperCase是否为该对象的方法,然后alert输出"HELLO",因为浏览器在解释程序时找到了字符串"hello"的toUpperCase()方法。

在W3School上的一段代码的解释

<html>

<head>

<script type="text/javascript">

function validate_required(field,alerttxt) {

    with (field) {

        if (value==null||value=="") {

            alert(alerttxt);return false;

        }else {

            return true;

        }

    }

}

function validate_form(thisform) {

    with (thisform) {

        if (validate_required(email,"Email must be filled out!")==false) {

            email.focus();return false;

        }

    }

}

</script>

</head>

<body>

<form action="submitpage.htm" onsubmit="return validate_form(this)" method="post">

Email: <input type="text" name="email" size="30">

<input type="submit" value="Submit">

</form>

</body>

</html>

提交表单时,执行validate_form方法,并把表单对象作为参数传入方法中,在validate_form方法中,先判断validate_required方法,由于该方法是公共的,所以可以直接找到,而作为参数的对象email在当前作用域中不存在,所以需要到thisform这个表单对象的作用域中查找name属性是email的表单元素,找到后,执行validate_required方法,在validate_required方法中需要查找value对象,而在validate_required方法的作用域中找不到value属性,因此需要到field中查找(field这时就是name等于email表单元素),field中存在value属性,如果该属性的值为空,给出提示信息并返回false,否则返回true,如果validate_required方法返回true,表单成功提交,如果返回false,email获得焦点并且表单不提交。

<think>我们正在讨论FastAdmin框架,用户现在询问的是如何使用with方法进行关联查询。在FastAdmin(基于ThinkPHP)中,with方法用于预加载关联模型数据,避免N+1查询问题。 根据用户上一次的问题,我们之前讨论了在buildparams方法中如何添加表前缀,而这次是关于关联查询的。因此,我们需要结合ThinkPHP的关联查询和FastAdmin的使用方式来回答。 在FastAdmin中,通常我们会在模型(Model)中定义关联关系,然后在控制器(Controller)中使用with方法来预加载关联数据。 步骤: 1. 在模型中定义关联方法(例如,一对一、一对多等)。 2. 在控制器中,使用with方法指定要预加载的关联关系,然后进行查询。 示例: 假设我们有两个表:`user`(用户表)和`profile`(用户信息表),一个用户对应一个信息(一对一关系)。 第一步:在User模型中定义关联关系(app/admin/model/User.php): ```php namespace app\admin\model; use think\Model; class User extends Model { // 定义与Profile模型的关联(一对一) public function profile() { // 参数1:关联模型类名 // 参数2:外键,在profile表中指向user表的字段 // 参数3:主键,user表的主键 return $this->hasOne('Profile', 'user_id', 'id'); } } ``` 第二步:在控制器中使用with方法预加载关联数据(例如,User控制器): ```php public function index() { if ($this->request->isAjax()) { // 获取请求参数(排序、分页等) list($where, $sort, $order, $offset, $limit) = $this->buildparams(); // 使用with方法预加载profile关联,这样在获取用户数据时会同时获取关联的profile数据 $list = User::with('profile') ->where($where) ->order($sort, $order) ->limit($offset, $limit) ->select(); // 处理数据并返回 $total = User::where($where)->count(); $result = array("total" => $total, "rows" => $list); return json($result); } return $this->view->fetch(); } ``` 注意:在FastAdmin的表格中,我们通常使用`$this->model`来操作,所以也可以这样写: ```php $list = $this->model ->with('profile') ->where($where) ->order($sort, $order) ->limit($offset, $limit) ->select(); ``` 第三步:在视图中(JS部分)配置表格列时,我们可以使用关联模型的字段,例如: ```javascript columns: [ {field: 'id', title: 'ID'}, {field: 'username', title: '用户名'}, {field: 'profile.phone', title: '电话'}, // 使用点语法表示关联模型的字段 // ... ] ``` 这样,在表格中就会显示关联模型profile的phone字段。 另外,如果关联关系是一对多,比如一个用户有多个地址(Address模型),那么在模型中定义: ```php // 在User模型中 public function addresses() { return $this->hasMany('Address', 'user_id', 'id'); } ``` 在控制器中同样使用with预加载: ```php $list = User::with('addresses')->select(); ``` 在前端表格中,如果需要显示多个地址,可能需要使用自定义模板列,因为一对多返回的是数组。 注意:使用with方法时,ThinkPHP会使用两个查询(主模型一个查询,关联模型一个查询)来获取数据,而不是N+1次查询,因此效率较高。 如果需要在关联查询中指定字段,可以在with方法中传入数组: ```php $list = User::with(['profile' => function($query) { $query->field('id,user_id,phone,email'); }])->select(); ``` 或者在模型中定义关联时指定字段: ```php public function profile() { return $this->hasOne('Profile', 'user_id', 'id')->field('id,user_id,phone,email'); } ``` 但注意,在关联模型中定义field时,必须包含关联键(user_id)和主键(id),否则可能无法正确关联。 在FastAdmin中,如果关联查询需要作为搜索条件,那么可能需要重写buildparams方法,如之前讨论的添加表前缀,或者使用JOIN查询。但是,使用with方法主要是用于数据展示,并不影响WHERE条件的构建(WHERE条件还是作用于主表)。 如果需要在关联表上添加搜索条件,可以使用JOIN或者使用闭包查询,例如: ```php $list = User::with(['profile' => function($query) { $query->where('phone', 'like', '%123%'); }])->where($where)->select(); ``` 但是注意,上面的闭包条件是在关联模型查询时应用的,并不会影响主模型的查询(即不会影响主查询的WHERE条件)。如果要在主查询中关联表条件过滤,应该使用JOIN或者使用子查询。 因此,在FastAdmin中,如果要在表格的搜索条件中包含关联表的字段,通常我们会使用JOIN(如之前的问题中所述),然后在buildparams中处理字段前缀。而with方法主要用于在获取到主表数据后,同时获取关联数据。 总结:在FastAdmin中,使用with方法进行关联查询的步骤: 1. 在模型中定义关联关系。 2. 在控制器中使用with方法预加载关联模型。 3. 在前端表格配置中,使用点语法(如'profile.phone')来显示关联模型的字段。 如果需要对关联表进行搜索,建议使用JOIN方式,以便在buildparams中能够处理搜索条件。 相关问题: 1. FastAdmin中如何定义模型关联? 2. 如何优化FastAdmin中的关联查询性能? 3. 在FastAdmin中,如何实现关联表字段的搜索? 4. 使用with预加载和JOIN查询有什么区别?</think>在 FastAdmin 中使用 `with` 方法进行关联查询,是 ThinkPHP ORM 的核心功能之一,能高效加载关联模型数据。以下是完整指南: --- ### 一、基础关联查询实现 #### 1. 定义模型关联关系 在模型中声明关联方法(如 `user` 模型关联 `profile` 模型): ```php // application/admin/model/User.php class User extends Model { // 定义一对一关联 public function profile() { return $this->hasOne('Profile', 'user_id', 'id'); } } ``` #### 2. 控制器中使用 `with` 预加载 ```php // 控制器方法 public function index() { if ($this->request->isAjax()) { list($where, $sort, $order, $offset, $limit) = $this->buildparams(); $list = $this->model ->with('profile') // 关键预加载语句 ->where($where) ->order($sort, $order) ->paginate($limit); return json($result); } return $this->view->fetch(); } ``` --- ### 二、高级关联查询技巧 #### 1. 嵌套关联加载(多层关联) ```php // 加载用户及其档案+地址 $list = $this->model ->with(['profile' => function($query) { $query->with('address'); // 嵌套加载 }]) ->select(); ``` #### 2. 关联条件过滤 ```php ->with(['profile' => function($query) { $query->where('status', 1); // 只加载激活状态的档案 }]) ``` #### 3. 字段选择优化 ```php ->with(['profile' => function($query) { $query->field('id,user_id,realname'); // 仅选择必要字段 }]) ``` --- ### 三、前端配置示例 在 JS 列配置中使用点语法访问关联字段: ```javascript columns: [{ field: 'id', title: 'ID' }, { field: 'profile.realname', // 访问关联模型字段 title: __('Realname'), operate: 'LIKE' // 支持关联字段搜索 }] ``` --- ### 四、性能优化建议 1. **避免 N+1 查询** 始终使用 `with` 预加载替代遍历中的惰性加载 2. **字段选择性加载** 结合 `field()` 限制主表和关联表字段: ```php ->field('user.id,user.name,profile.phone') ->with('profile') ``` 3. **大数据量分页优化** 使用 `withJoin` 替代 `with` 减少查询次数: ```php ->withJoin(['profile' => ['realname']], 'LEFT') ``` 4. **缓存关联数据** 对稳定数据启用缓存提升性能: ```php ->with(['profile' => function($query) { $query->cache(300); // 缓存5分钟 }]) ``` --- ### 五、常见问题解决 **问题:关联数据未加载** 检查模型关联方法名是否与 `with()` 参数一致,并确保外键关系正确 **问题:SQL 字段冲突** 为同名字段添加表前缀: ```php ->field('user.name AS username, profile.name AS profile_name') ``` **问题:关联表搜索失效** 在 `buildparams` 中处理关联字段前缀(参考[上期解答](^1)): ```php // 在 buildparams 方法中添加 if (strpos($k, '.') === false) { $prefixedKey = $this->model->getTable() . '.' . $k; } ``` > 提示:调试时可开启 SQL 日志: > ```php > Db::getConnection()->getLog(true); > ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值