Symfony框架下跨实体取值导出CSV的相关问题咨询
问题原因与解决方案
1. 报错"Only variables should be passed by reference"的解决
你出现这个报错有两个核心错误:
- 语法误用:PHP中
array_push的正确调用方式是第一个参数传入目标数组,后续参数为要追加的元素,你写的$array.array_push(...)是将字符串拼接符.错误用成了对象调用符,同时调用逻辑完全错误。 - 不必要的引用传递:foreach中
&$p的引用符号完全不需要,你没有修改原$parcels数组中元素的需求,去掉引用即可消除传引用警告。
2. 跨实体取值的实现
你不需要用QueryBuilder或者SQL,只要你的Doctrine实体关联关系(比如Parcel和DeliveryOrder、DeliveryOrder和Product的关联映射,比如@ManyToOne注解)配置正确,直接通过链式调用getter方法获取关联实体属性是Doctrine原生支持的标准用法,完全符合你的要求。
唯一需要注意的是如果关联字段配置了懒加载,大量数据下会出现N+1查询问题,如果数据量不大可以忽略,数据量多的话可以在查询时预加载关联实体即可。
3. 生成CSV对应多维数组的修正
你现在的写法会把所有行的字段都塞到一维数组里,正确的做法是每次循环生成一个对应单行CSV的一维数组,再把这个数组追加到总数组中。
另外注意PHP中字符串拼接用.而不是+,你的getCode()+"0"+$p->getNumber()逻辑会被识别为数字加法,需要修正。还有\DateTime::createFromFormat('Ymd',$dateToday)的写法错误,$dateToday本身就是DateTime对象,不需要再转换。
修正后的完整代码
$parcelRepo = $this->getDoctrine()->getRepository(Parcel::class); // 注意:如果date_add是存储的日期格式(不含时间),需要格式化掉时间部分,否则匹配不到当天数据 $dateToday = new \DateTime("today"); $parcels = $parcelRepo->findBy([ 'date_add' => $dateToday ]); $csvData = []; // 去掉不必要的引用& foreach ($parcels as $p) { // 单次循环生成一行数据的数组 $row = [ $p->getDeliveryOrder()->getProduct()->getAccount()->getCoclico(), "1", "", $p->getDeliveryOrder()->getUser()->getLogin(), $p->getDeliveryOrder()->getProduct()->getCode(), $p->getInternalReference(), // 改用.做字符串拼接 $p->getDeliveryOrder()->getProduct()->getCode() . "0" . $p->getNumber(), "121", $p->getName(), $p->getAddress4(), $p->getAddress1(), $p->getAddress2(), $p->getAddress3(), "téléphone", //TODO $p->getPostalCode(), $p->getCity(), // 直接按需格式化日期即可 $dateToday->format('Ymd'), "", "", "0" ]; // 把行追加到总数组 $csvData[] = $row; }
后续你直接把$csvData传给CSV生成类即可,每一个子数组对应CSV的一行。
内容的提问来源于stack exchange,提问作者user7986773
相关产品推荐
相关产品推荐

