Symfony 2.8+Twig环境下Google Maps API无法读取locations数组求助
解决Symfony 2.8中Twig生成Google Maps标记点数组的问题
你遇到的核心问题主要是locations数组结构错误,以及可能存在的变量作用域/执行顺序问题,我来一步步帮你修正:
问题根源分析
- 数组结构错误:你用
locations.push.apply(locations, [event_name, event_lat, event_lng, event_id]);的写法,会把数组里的每个元素单独拆分添加到locations中,最终得到的是一维数组(比如["活动1", 52.7, 23.4, 1, "活动2", ...]),但你的initMap函数期望的是二维数组(每个元素是包含名称、经纬度、ID的子数组),这就导致循环时locations[i][1]这类取值会报错。 - 作用域/执行顺序:如果把Twig循环移到initMap外,要确保Google Maps的初始化函数在Twig渲染完locations之后执行;如果移到函数内,要保证Twig循环的语法符合JS数组的格式要求。
修正后的代码方案
方案1:在initMap外生成正确的二维数组
<script> // 正确生成二维结构的locations数组 var locations = []; {% for event in incoming_events %} // 直接将每个事件的信息作为子数组push进去 locations.push([ {{ event.name|json_encode|raw }}, {{ event.geoMarker.lat|json_encode|raw }}, {{ event.geoMarker.lng|json_encode|raw }}, {{ event.id|json_encode|raw }} ]); {% endfor %} function initMap() { var event_one = {lat: 52.742943, lng: 23.450317}; var map = new google.maps.Map(document.getElementById('tab-mapawydarzen'), { zoom: 6, center: event_one, }); var infowindow = new google.maps.InfoWindow(); var marker, i; // 现在数组结构正确,可以正常循环遍历标记点 for (i = 0; i < locations.length; i++) { marker = new google.maps.Marker({ position: new google.maps.LatLng(locations[i][1], locations[i][2]), icon: '../img/pins/notactive.png', map: map }); google.maps.event.addListener(marker, 'click', (function(marker, i) { return function() { marker.setIcon('../img/pins/active.png'); infowindow.setContent(locations[i][0]); infowindow.open(map, marker); } })(marker, i)); } } </script> <!-- 务必确保Google Maps脚本在自定义脚本之后加载,或使用callback参数确保初始化时机 --> <script async defer src="https://maps.googleapis.com/maps/api/js?key=你的API密钥&callback=initMap"></script>
方案2:直接在initMap函数内生成数组(彻底避免作用域问题)
<script> function initMap() { // 直接在函数内部用Twig循环生成符合格式的二维数组 var locations = [ {% for event in incoming_events %} [ {{ event.name|json_encode|raw }}, {{ event.geoMarker.lat|json_encode|raw }}, {{ event.geoMarker.lng|json_encode|raw }}, {{ event.id|json_encode|raw }} ]{% if not loop.last %},{% endif %} {% endfor %} ]; var event_one = {lat: 52.742943, lng: 23.450317}; var map = new google.maps.Map(document.getElementById('tab-mapawydarzen'), { zoom: 6, center: event_one, }); var infowindow = new google.maps.InfoWindow(); var marker, i; for (i = 0; i < locations.length; i++) { marker = new google.maps.Marker({ position: new google.maps.LatLng(locations[i][1], locations[i][2]), icon: '../img/pins/notactive.png', map: map }); google.maps.event.addListener(marker, 'click', (function(marker, i) { return function() { marker.setIcon('../img/pins/active.png'); infowindow.setContent(locations[i][0]); infowindow.open(map, marker); } })(marker, i)); } } </script> <script async defer src="https://maps.googleapis.com/maps/api/js?key=你的API密钥&callback=initMap"></script>
关键注意事项
- 数组结构正确性:一定要保证locations是二维数组,每个子数组对应一个标记点的完整信息,这样后续循环中的纬度、取值才能正常工作。
- Google Maps加载时机:必须让自定义脚本先于Google Maps脚本加载,或者使用
callback=initMap参数,确保Google Maps加载完成后再执行你的初始化函数,避免出现map对象未就绪的情况。 - Twig转义处理:你已经用到了
|json_encode|raw,这是正确的做法,能确保字符串类的字段(比如活动名称)正确转义,避免触发JS语法错误。
内容的提问来源于stack exchange,提问作者Calix
相关产品推荐
相关产品推荐

