Ответы пользователя по тегу PHP
  • Как изменить поля в модели через n-времени в Yii2?

    @Holyboom Автор вопроса
    junior fullstack
    короч как сделал .
    поставил плагин для yii "composer require --prefer-dist yiisoft/yii2-queue"
    в common/config/main добавил
    'components' => [
            'queue' => [
                'class' => \yii\queue\file\Queue::class,
                'path' => '@console/runtime/queue',
                'as log' => \yii\queue\LogBehavior::class,
            ],
    'bootstrap' => [
            'queue',
        ],


    создал класс отвечающий за таски
    <?php
    class QueueHelper
    {
        public static function setTask ($task) {
            Yii::$app->queue->push($task);
        }
        public static function setDelayTask ($task , $delay = 5) {  // delay  - задержка выполнения в сек
            Yii::$app->queue->delay($delay)->push($task);
        }
    }


    и класс с самой таской
    class TaskEndEvent extends BaseObject implements \yii\queue\JobInterface
    {
        public $idTask;
        public function execute($queue)
        {
            $e = Events::findOne($this->idTask);
            if ($e->status != 1 ){
                $e->ended_at = $e->creation_at + 7200 ;
                $e->status = 1 ;
                $e->save(false);
            }
        }
    }


    и сделал вызов при сохранении
    public function afterSave($insert, $changedAttributes)
        {
            parent::afterSave($insert, $changedAttributes);
            if ($this->status != 1){
                QueueHelper::setDelayTask(new TaskEndEvent(['idTask'=>$this->id]), 7200);
            }
        }


    и кроном запустил проверку на наличие актуальных таск
    cron run * * * * * /usr/bin/php /var/www/my_project/yii queue/run


    можно повесить слушатель таск в консоли
    yii queue/listen
    Ответ написан
    Комментировать
  • Как получить гео-точки из видимой области на карте при изменении угла карты?

    @Holyboom Автор вопроса
    junior fullstack
    короче как я решил этот вопрос.
    тк мне не нужна супер точность я использовал такую формулу :
    //dist расстояние , в моем случает от центра карты до лев верх угла карты в метрах.
    // те это то расстояние от центра на котором мы поставим наши точки 
    // a  = угол на который наклонить точки относительно нулевого азимута.
    // lat и  long координаты точки в центре экрана 
    var p180= 180/pi;
          var dx =  p180 * ((cos(a / 180 * pi) * dist) / 6378137) ;
          var dy =  p180 * ((sin(a / 180 * pi) * dist) / 6378137) ;
          var toplat = latitude + dy;
          var toplng = longitude + dx / cos(latitude);
          var bottomlat = latitude - dy;
          var bottomlng = longitude - dx / cos(latitude);
    Ответ написан
    Комментировать
  • Как сделать двойную группировку в запросе SQL в ElasticSearch?

    @Holyboom Автор вопроса
    junior fullstack
    Короче решил вопрос так

    $topLeftLat = $_POST['topLeftLat'];
            $topLefiLng = $_POST['topLeftLng'];
            $bottomRightLat = $_POST['bottomRightLat'];
            $bottomRightLng = $_POST['bottomRightLng'];
            $zoom = $_POST['zoom'];
    
            $params['bool']['filter'][]['bool']['must']=
                [
                    [
                        "exists" => [
                            "field" => "location"
                        ]
                    ],
                    [
                        "geo_bounding_box" => [
                            "location" => [
                                "top_left" => $topLeftLat.','.$topLefiLng,
                                "bottom_right" => $bottomRightLat.','.$bottomRightLng
                            ]
                        ]
                    ]
                ];
            $query = ElasticObj::find();
            $p = ($zoom > 10 )? 10 : 8-(6-$zoom);
                $query->addAggregate('gridSplit', [
                    'geotile_grid' => [
                        'bounds' => [
                            "top_left" => $topLeftLat.','.$topLefiLng,
                            "bottom_right" => $bottomRightLat.','.$bottomRightLng
                        ],
                        "field" => "location",
                        "precision" => $p,
                        "size" => 65535,
                        "shard_size" => 65535
                    ],
                    'aggs' => [
                        'gridCentroid' => [
                            'geo_centroid' => [
                                'field' => 'location'
                            ]
                        ]
                    ]
                ]);
                $query->query($params);
                $dataProvider = new ActiveDataProvider([
                    'query' => $query,
                ]);
                $aggregations = $dataProvider->getAggregations();
    Ответ написан
    Комментировать
  • Как сделать множественный поиск по БД?

    @Holyboom Автор вопроса
    junior fullstack
    Короче вариант с поисковым движком типа сфинкс или подобного не подходит , тк мой проект сейчас находится не на выделенном серваке и у меня нет прав запуска различных служб.
    покачто вышел из ситуации как

    SELECT s.* ,st.`name` AS type_name ,  group_concat(DISTINCT benefits.name SEPARATOR ' ') as concat_bn, st.alias as spot_type_alias, benefits.alias as benefit_alias, CONCAT(" ", group_concat(DISTINCT benefits.id SEPARATOR ' ')  ," ")  as concat_bn_id,
      // для полей s.name , s.track, st.name , st.alias ,benefits.name , benefits.alias в каждой таблице создаем полнотекстовый индекс. 
      // 
      // тут считаем релевантность запроса
      MATCH(s.name , s.track) AGAINST('+$query') as score,
      MATCH(st.name , st.alias) AGAINST('+$query') as stcore,
      MATCH(benefits.name , benefits.alias) AGAINST('+$query') as bncore,
       (                // тут считаем расстояние до точки (тк я ищу точки ) (опционально)
                        6371 *
                        acos(cos(radians($lat)) *
                        cos(radians(s.lat)) *
                        cos(radians(s.lng) -
                        radians($lng)) +
                        sin(radians($lat)) *
                        sin(radians(s.lat)))
                        ) AS distance 
    FROM `spots` s
    // прикручиваем связь один к одному для поиска по типу из другой таблицы
    JOIN `spot_type` st ON s.id_spot_type = st.id
    // прикручиваем сводную таблицу для связи многие ко многим для поиска по типам плюшек на точке 
    join spots_benefits
     on spots_benefits.spot = s.id
    join benefits 
     on benefits.id = spots_benefits.benefit
    
    where 
    //собственно сам поиск
      MATCH(s.name, s.track) AGAINST('+$query')
      OR MATCH(st.name, st.alias) AGAINST('+$query')
      OR MATCH(benefits.name, benefits.alias) AGAINST('+$query')
      // групируем элементы из сводных таблиц в одно поле груп_конкат
    group by s.id 
    // ищем по только те что были добавлены в фильтр (опционально) типов 
    HAVING  concat_bn_id like "% 1 %" AND concat_bn_id like '% 2 %' AND  s.id_spot_type = 2
    // сортируем сначала по релевантности, а потом уже по расстоянию
    ORDER BY (score + stcore + bncore) DESC, distance ASC


    как-то так... запрос в принципе быстро обрабатывает (примерно 0,005 - 0,01 ) относительно конечно , но для бд с 20к записей норм
    если у кого есть идеи по оптимизации буду рад вашему мнению ! )
    всем спасибо
    Ответ написан
    Комментировать
  • Алгоритм получения квадрата по координатам?

    @Holyboom Автор вопроса
    junior fullstack
    Сергей Соколов, короче , вроде сделал))
    SET @home = ST_GeomFromText('LINESTRING(
    //Список наших точек через которые идет маршрут 
    53.862263 27.483486,
    53.871521 27.493636,
    53.875594 27.496447,
    53.880938 27.500744,
    53.882699 27.505121,
    53.884246 27.504435,
    53.891446 27.500293,
    53.896630 27.497375,
    53.905348 27.496302,
    53.912531 27.495487,
    53.918726 27.496882)');
    SELECT *, ST_AsText(geo) as Coord,
        // Дистанция считается странно получается вроде правильно , но не уверен насчет точности . 
       // В оригинале в доках написано умножать ее на .001 для км и .00067... для миль
       // но у меня так не работало и показывало до объекта 0,003км хотя по факту до него 300м вот я решил 
             умножать ее на 100 (хотя хз может оно там сантиметрах считает) 
        ST_DISTANCE(@home, geo) * 100 AS dist
        FROM dots
       // дистанция от маршрута в радиусе которой нам нужны точки (в км ) 
        HAVING dist < 1
        ORDER BY dist
        LIMIT 30


    и в итоге будет примерно так
    613cb908956cd964506159.png

    вернет зеленые точки , а красные нет .

    вроде так )
    Ответ написан
  • Как передать данные в переменную?

    @Holyboom
    junior fullstack
    $newVar = $resultDeal->time['date_start']
    Если $resultDeal это тоже ассоциативный массив то
    $newVar = $resultDeal['time']['date_start']
    Ответ написан
    Комментировать