craue / CraueGeoBundle

Doctrine functions for calculating geographical distances in your Symfony project.
MIT License
124 stars 15 forks source link

Support / Instructions for symfony4 #17

Closed klemens-u closed 5 years ago

klemens-u commented 6 years ago

Hi, first of all I'm a complete noob to symfony4, so sorry about that :-)

Could you please help me with the installation in a new symfony4 project?

Thanks for any help!

klemens-u commented 6 years ago

Fixture loading worked when I extended Fixture and copied your fixture code to my custom fixture class:

<?php

namespace App\DataFixtures;

use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use Craue\GeoBundle\Entity\GeoPostalCode;

class MyGeonamesPostalCodeDataFixtures extends Fixture {

    protected $batchSize = 1000;

    public function load(ObjectManager $manager) {
        $this->clearPostalCodesTable($manager);

        $this->addEntries($manager, __DIR__ . '/../../data/geo/AT.txt');
    }

    protected function getRepository(ObjectManager $manager) {
        return $manager->getRepository('Craue\GeoBundle\Entity\GeoPostalCode');
    }

    protected function clearPostalCodesTable(ObjectManager $manager) {
        foreach ($this->getRepository($manager)->findAll() as $entity) {
            $manager->remove($entity);
        }
        $manager->flush();
    }

    /**
     * @param ObjectManager $manager
     * @param string $filename
     * @return int Number of entries actually added.
     */
    protected function addEntries(ObjectManager $manager, $filename) {
        $repo = $this->getRepository($manager);

        $entriesAdded = 0;
        $currentBatchEntries = array();

        $fcontents = file($filename);
        for ($i = 0, $numLines = count($fcontents); $i < $numLines; ++$i) {
            $line = trim($fcontents[$i]);
            $arr = explode("\t", $line);

            // skip if no lat/lng values
            if (!array_key_exists(9, $arr) || !array_key_exists(10, $arr)) {
                continue;
            }

            $country = $arr[0];
            $postalCode = $arr[1];

            // skip duplicate entries in current batch
            if (in_array($country.'-'.$postalCode, $currentBatchEntries)) {
                continue;
            }

            // skip duplicate entries already persisted
            if ($repo->findOneBy(array('country' => $country, 'postalCode' => $postalCode)) !== null) {
                continue;
            }

            $entity = new GeoPostalCode();
            $entity->setCountry($country);
            $entity->setPostalCode($postalCode);
            $entity->setLat((float) $arr[9]);
            $entity->setLng((float) $arr[10]);
            $manager->persist($entity);

            ++$entriesAdded;
            $currentBatchEntries[] = $country.'-'.$postalCode;

            if ((($i + 1) % $this->batchSize) === 0) {
                $manager->flush();
                $manager->clear();
                $currentBatchEntries = array();
                echo '.'; // progress indicator
            }
        }

        $manager->flush(); // Flush for the last batch, which doesn't reach the batch size in most cases. (fixes #2)

        echo ' ', $entriesAdded, "\n";

        return $entriesAdded;
    }
}
craue commented 5 years ago

It took a while, but with DoctrineFixturesBundle 3.1 specific fixtures can be loaded again. I've updated the README file to add basic instructions. Feel free to respond if anything is unclear or doesn't work.