【问题标题】:CakePHP 3 - Use SQL function in select() by default in table objectCakePHP 3 - 在 table 对象中默认使用 select() 中的 SQL 函数
【发布时间】:2020-04-21 23:50:14
【问题描述】:

我正在为带有一些 POINT 列的数据库设置系统。我使用食谱示例构建了一个自定义类型,它似乎正在工作。但是,要处理POINTs,我需要以特殊方式SELECT

SELECT ST_AsText(location) as location ...

查询生成器并不难:

$this->Houses->find()->select(['location' => 'ST_AsText(location)'])

但是,我希望默认情况下发生这种情况。

我正在考虑使用beforeFind 事件,但我找不到以下伪代码的正确函数:

public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
{
    if 'location' in query->getSelectedFields():
         replace 'location' by 'location' => 'ST_AsText(location)'
}

当要包含字段时,如何将字段替换为函数? 理想情况下,即使我还没有从控制器调用 ->select(...)

关于 CakePHP 话语的较早的类似问题: https://discourse.cakephp.org/t/read-data-from-spatial-mysql-field-point-polygon/2124

【问题讨论】:

    标签: cakephp orm model cakephp-3.0


    【解决方案1】:

    CakePHP 3.5 Always apply asText() MySQL function to Spatial field找到我的解决方案。

    这适用于 CakePHP 3.8。我决定将事件处理放在一个行为中以便于重用:

    <?php
    // src/Model/Behavior/SpatialBehavior.php    
    
    namespace App\Model\Behavior;
    
    use Cake\ORM\Behavior;
    use Cake\ORM\Table;
    use Cake\Event\Event;
    use ArrayObject;
    use Cake\ORM\Query;
    
    /**
     * Spatial behavior
     * 
     * Make sure spatial columns are loaded as text when needed.
     * 
     * @property \Cake\ORM\Table $_table
     */
    class SpatialBehavior extends Behavior
    {
    
        /**
         * Default configuration.
         *
         * @var array
         */
        protected $_defaultConfig = [];
    
        /**
         * Callback before each find is executed
         * 
         * @param Event $event
         * @param Query $query
         * @param ArrayObject $options
         * @param type $primary
         */
        public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
        {
            $query->traverse(function (&$value) use ($query)
            {
                if (is_array($value) && empty($value))
                {
                    // Built up standard query when ->select() was never used
                    //$query->all(); // Execute query to learn columns
                    $query->select($this->_table);
                }
    
                $defaultTypes = $query->getDefaultTypes();
    
                foreach ($value as $key => $field)
                {
                    if (in_array($defaultTypes[$field], ['point', 'polygon']))
                    {
                        $value[$key] = $query->func()->ST_AsText([
                            $this->_table->aliasField($field) => 'identifier'
                        ]);
                    }
                }
    
                $query->select($value);
            }, ['select']);
        }
    
    }
    

    在我的表格对象中:

    class HousesTable extends Table
    {
        public function initialize(array $config)
        {
            //...
            $this->addBehavior('Spatial');
            //...
        }
    

    【讨论】:

      猜你喜欢
      • 2013-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-16
      • 1970-01-01
      相关资源
      最近更新 更多