neo4j-php / neo4j-symfony

Symfony Bundle for the Neo4j Graph Database
MIT License
78 stars 41 forks source link

ServiceNotFoundException in Symfony 4 #49

Closed vzenix closed 5 years ago

vzenix commented 6 years ago

ServiceNotFoundException

The "neo4j.client" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.

My composer.json is it:

{
    "type": "project",
    "license": "proprietary",
    "require": {
        "php": "^7.1.3",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "friendsofsymfony/rest-bundle": "^2.3",
        "graphaware/neo4j-common": "^3.5",
        "graphaware/neo4j-php-ogm": "^1.0@RC",
        "jms/serializer-bundle": "^2.4",
        "neo4j/neo4j-bundle": "^0.4.1",
        "sensio/framework-extra-bundle": "^5.1",
        "symfony/console": "^4.1",
        "symfony/flex": "^1.0",
        "symfony/framework-bundle": "^4.1",
        "symfony/lts": "^4@dev",
        "symfony/yaml": "^4.1"
    },
    "require-dev": {
        "symfony/dotenv": "^4.1"
    },
    "config": {
        "preferred-install": {
            "*": "dist"
        },
        "sort-packages": true
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/"
        }
    },
    "replace": {
        "symfony/polyfill-ctype": "*",
        "symfony/polyfill-iconv": "*",
        "symfony/polyfill-php71": "*",
        "symfony/polyfill-php70": "*",
        "symfony/polyfill-php56": "*"
    },
    "scripts": {
        "auto-scripts": {
            "cache:clear": "symfony-cmd",
            "assets:install %PUBLIC_DIR%": "symfony-cmd"
        },
        "post-install-cmd": [
            "@auto-scripts"
        ],
        "post-update-cmd": [
            "@auto-scripts"
        ]
    },
    "conflict": {
        "symfony/symfony": "*"
    },
    "extra": {
        "symfony": {
            "allow-contrib": false
        }
    }
}

And my code is it:

<?php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use FOS\RestBundle\Controller\Annotations as FOSRest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;

/**
 * @Route("/api/v1")
 */
class DemoController extends Controller
{

    /**
     * Test
     * @FOSRest\Get("/test")
     * @return array
     */
    public function test()
    {
        $client = $this->getNeo4jClient();
        $results = $client->run('MATCH (n:Movie) RETURN n LIMIT 5');
        $element = array();
        foreach ($results->records() as $record) {
            $node = $record->get('n');
            $element[] = $node->get('title'); // "The Matrix"
        }

        $iResponse = new JsonResponse();
        $iResponse->setData(array('demo' => true, 'elements' => $element));
        return $iResponse;
    }

    /**
     * @return \GraphAware\Neo4j\Client\Client
     */
    private function getNeo4jClient()
    {
        return $this->get('neo4j.client');
    }
}
vzenix commented 6 years ago

At the end i solve it apply decorators to the services for do the connection, i put the example if someone have the same problem.

Add to [root symfony]/config/services.yaml

    Neo4j\Neo4jBundle\Factory\ClientFactory:
        alias: neo4j.factory.client
        public: true

    neo4j.connection.custom:
        decorates: neo4j.connection.default
        class: GraphAware\Neo4j\Client\Connection\Connection
        public: true
        arguments: 
            - 'default'
            - '%env(NEO4J_CONNECTION)%'

    neo4j.client.custom:
        decorates: neo4j.client
        class: GraphAware\Neo4j\Client\Client
        public: true
        # pass the old service as an argument
        arguments: ['@neo4j.connection_manager']

Add to [root symfony]/.env and [root symfony]/.env.dist

NEO4J_CONNECTION="http://<username>:<password>@localhost:7474"

Then you need use the new service for clients

    /**
     * @return \GraphAware\Neo4j\Client\Client
     */
    private function getNeo4jClient()
    {
        return $this->container->get('neo4j.client.custom');
    }
Nyholm commented 5 years ago

You should not do $this->get('neo4j.client'); You should never access the container like this. Use dependency injection instead.

isaacquentinmenguebibang commented 5 years ago

for my part I managed to create a service and that's how I did

src/Service/Antispam
<?php
    namespace App\Service\Antispam;

    class OCAntispam{
        private $text;

        public function getText(){
            return $this->text;
        }
        public function setText($text){
            if(is_string($text)){
                $this->text = $text;
            }
        }
        public function isSpam($text){
            return strlen($this->text) < 50;
        }
    }

config/service.yaml

 # add more service definitions when explicit configuration is needed
    # please note that last definitions always *replace* previous ones
    advert_antispam.antispam:
        class: App\Service\Antispam\OCAntispam
        public: true

my controller must inherit controller and not AbstractController

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

AdvertController extends Controller{
$antispams = $this->container->get('advert_antispam.antispam');
            //$antispam = new OCAntispam;
            $text = 'fjfj';
            if($antispams->isSpam($text)){
                throw new \Exception('Votre texte à été détecté comme un spam');
            }
            $content = $twig->render('adverter/add.html.twig');
           return new Response($content);
}

I hope it will help a person

isaacquentinmenguebibang commented 5 years ago

For me here is how I did src/Service/Antispam `<?php namespace App\Service\Antispam;

class OCAntispam{
    private $text;

    public function getText(){
        return $this->text;
    }
    public function setText($text){
        if(is_string($text)){
            $this->text = $text;
        }
    }
    public function isSpam($text){
        return strlen($this->text) < 50;
    }
}`

services.yaml `

add more service definitions when explicit configuration is needed

please note that last definitions always replace previous ones

advert_antispam.antispam: class: App\Service\Antispam\OCAntispam public: true `

in the controller you have to put $antispams = $this->container->get('advert_antispam.antispam'); Our controller must inherit Controller and not AbstractController. I hope it will help a person