1

I working on a web socket app using ratchet and symfony 2.8 to connect to database and changing value in a certain column if someone connect to the server but I get error in this line

    $sql = $this->container->get('database_connection');

the full error message

An error has occurred: Notice: Undefined property: check\roomsBundle\Sockets\Chat::$container

my injection in the services.yml code

services:
     database_connection:
         class: check\roomsBundle\Sockets\Chat
         arguments: ["@service_container"] 

my Chat.php code

<?php
namespace check\roomsBundle\Sockets;
use tuto\testBundle\Entity\Users;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class Chat implements MessageComponentInterface  {


    protected $clients;
    //protected $db;
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);

        echo "New connection! ({$conn->resourceId})\n";

        $sql = $this->container->get('database_connection');
        $users = $sql->query("UPDATE user SET ONoff= '1' WHERE UserId='2'");


    }
}
mrsharko
  • 285
  • 2
  • 9
  • 22

3 Answers3

2

Ok so there's a few things that you'll need to fix in order to solve your problem.

services:
     database_connection:
         class: check\roomsBundle\Sockets\Chat
         arguments: ["@service_container"] 

What this is doing is when it calls the constructor it's going to pass in the service container, however using the constructor to pass in your container isn't favorable, but rather instead you should implement the Symfony\Component\DependencyInjection\ContainerAwareInterface interface and then implement the method setContainer and optional a getContainer method.

/**
 * @param ContainerInterface|NULL $container
 */
public function setContainer(
    ContainerInterface $container = NULL
)
{
    $this->container = $container;
    return $this;
}

/**
 * @return ContainerInterface
 */
protected function getContainer()
{
    return $this->container;
}

And then after that update your service to call this method when initializing it.

services:
     chat_service: # renamed because this is your chat service, not your database connection
         class: check\roomsBundle\Sockets\Chat
         calls:
             - [setContainer, ["@service_container"]]
Jonathan
  • 2,778
  • 13
  • 23
  • i get this error inerAwareInterface::setContainer() cannot contain body in – mrsharko Mar 20 '17 at 07:23
  • Did you want to complete the error message you get? – Jonathan Mar 20 '17 at 15:30
  • PHP Fatal error: Interface function Symfony\Component\DependencyInjection\ContainerAwareInterface::setContainer() cannot contain body in /opt/lampp/htdocs/x/1/sym/thesym/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/ContainerAwareInterface.php on line 24 – mrsharko Mar 21 '17 at 01:05
  • the error on this line public function setContainer( ContainerInterface $container = NULL ) – mrsharko Mar 21 '17 at 01:05
  • Its seems as though you've modified this file. `vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/ContainerAwareInterface.php`, you should *never* modify anything in the `vendor` folder. The changes I've provided were mean't to be done in the chat.php file, or some other class inherited by it, using the `extends` keyword. – Jonathan Mar 21 '17 at 16:22
  • i get this error massage for this line $sql = $this->container->get('database_connection'); i tried to changes it to $sql = $this->get('database_connection'); but i still get the same error – mrsharko Mar 22 '17 at 00:08
  • I'll repeat again. You've changed the above mentioned file, you shouldn't be doing that. You need to revert that file to it's previous state. Assuming you're using composer just delete the entire `vendor` folder and run `composer install` again. – Jonathan Mar 22 '17 at 01:10
1

Your service is fine you just need little changes in your chat.php class

use Symfony\Component\DependencyInjection\ContainerInterface as Container;

class Chat implements MessageComponentInterface  {

protected $clients;
private $container;
//protected $db;
public function __construct(Container $container) {
    $this->clients = new \SplObjectStorage;
    $this->container = $container;
}

Now u can use $this->container

Updated

Try to inject entity manager

services:
  database_connection:
    class: check\roomsBundle\Sockets\Chat
    arguments: 
        - @doctrine.orm.default_entity_manager

in chat.php do like this

use Doctrine\ORM\EntityManager;
class Chat implements MessageComponentInterface  {

   protected $clients;
   protected $em;
   public function __construct(EntityManager $em) {
       $this->clients = new \SplObjectStorage;
       $this->em = $em;
   }
$this->em->getRepository('yorrepo')->updateFuntion();

Now try to call from some repo to update

Azam Alvi
  • 6,918
  • 8
  • 62
  • 89
  • i get this error [Symfony\Component\Debug\Exception\FatalThrowableError] Type error: Argument 1 passed to check\roomsBundle\Sockets\Chat::__construc t() must implement interface rInterface, none given, called in – mrsharko Mar 20 '17 at 09:34
-1

Injecting the service container is generally considered as a bad idea.

you should consider to inject database_connection service .

There are few ways to do that. Have a look at Types of Injection.

services:
     chat_service:
         class: check\roomsBundle\Sockets\Chat
         arguments: ["@database_connection"]

your class

protected $connection;

public function __construct($connection) {
    $this->connection = $connection;
}

Even if you want to go ahead with injecting the service container, the above link has relavent documentation that will help you to solve the issue you are facing.

Community
  • 1
  • 1
Vamsi Krishna B
  • 11,377
  • 15
  • 68
  • 94
  • added exaple code, requesting the user who downvoted to comment on why they did so. – Vamsi Krishna B Mar 20 '17 at 03:48
  • thank you for answer i get this error when i try your code [Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException] Circular reference detected for service "database_connection", path: "datab ase_connection -> database_connection". – mrsharko Mar 20 '17 at 06:57
  • In the example from the answer, the service id should be something different than `database_connection`. You could also change the id of the injected service. However, as the class name is something about a chat, the service should rather not be named like something related to a database connection. – xabbuh Mar 20 '17 at 14:27
  • @xabbuh , thanks xabbbuh.totally missed to catch the circular reference error when I posted the the anser.. Un-related to your comment : my answer was downvoted before I added the code example, I thought it was downvoted due to non presence of an example. – Vamsi Krishna B Mar 20 '17 at 15:08
  • [Symfony\Component\Debug\Exception\ContextErrorException] Warning: Missing argument 1 for check\roomsBundle\Sockets\Chat::__construct (), called in /opt/lampp/htdocs/x/1/sym/thesym/src/check/roomsBun dle/Command/SocketCommand.php on line 41 and defined – mrsharko Mar 21 '17 at 01:01