1

I am really new into frameworks and into ZF3, but I need to make a API, with the following logic. I receive parameters, I store them in an bd and if the call is action is to be made at this point(call Manager), I send it to the (provider caller). I was able to the first part, and the second, but now, I don't know how to do the last one... I have the following code:

IndexController.php

use Application\Service\CallManager;
use Application\Service\TropoCaller;
use Application\Service\NexmoCaller;



class IndexController extends AbstractActionController
{
 /**
 * Entity manager.
 * @var Doctrine\ORM\EntityManager 
 */
private $entityManager;

/**
 * Call manager.
 * @var Application\Service\CallManager 
 */
private $callManager;

/**
 * Call manager.
 * @var Application\Service\NexmoCaller
 */
private $NexmoCaller;

/**
 * Call manager.
 * @var Application\Service\TropoCaller
 */
private $TropoCaller;

/**
 * Constructor is used for injecting dependencies into the controller.
 */
public function __construct($entityManager, $callManager, $NexmoCaller, $TropoCaller) 
{
    $this->entityManager = $entityManager;
    $this->callManager = $callManager;

    $this->NexmoCaller = $NexmoCaller;
    $this->TropoCaller = $TropoCaller;
}

public function contactUSAction()
{
    $form= new ButtoncallForm();

    // Check whether this post is a POST request.
    if ($this->getRequest()->isPost()) {

        // Get POST data.
        $data = $this->params()->fromPost();

        // Fill form with data.
        $form->setData($data);
        if ($form->isValid()) {

            // Get validated form data.
            $data = $form->getData();

            // Use post manager service to add new call to the database             
            $this->callManager->CallManager($data);



            return $this->redirect()->toRoute('application', 
                    ['action'=>'thankYou']);
        }
    }

 return new ViewModel([

        'form' => $form,
        ]);
 }

public function thankYouAction() 
{
    return new ViewModel();
}

}

IndexControllerFactory.php

   <?php
namespace Application\Controller\Factory;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Application\Service\CallManager;
use Application\Service\TropoCaller;
use Application\Service\NexmoCaller;
use Application\Controller\IndexController;
/**
 * This is the factory for IndexController. Its purpose is to instantiate the
 * controller.
 */
class IndexControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $entityManager = $container->get('doctrine.entitymanager.orm_default');
        $callManager = $container->get(CallManager::class);
        $NexmoCaller = $container->get(NexmoCaller::class);
        $TropoCaller = $container->get(TropoCaller::class);

        // Instantiate the controller and inject dependencies
        return new IndexController($entityManager, $callManager, $NexmoCaller, $TropoCaller);
    }
}

My CallManager.php

<?php

namespace Application\Service;

use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Application\Entity\CallRequested;
use Doctrine\ORM\EntityManager;
use Stomp\Client;
use Stomp\StatefulStomp;
use Stomp\Network\Connection;
use Stomp\Transport\Message;
use Application\Service\NexmoCaller;
use Application\Service\TropoCaller;

class CallManager
{
   /**
   * Doctrine entity manager.
   * @var Doctrine\ORM\EntityManager
   */
    private $entityManager;

   /**
   * @var Application\Service\NexmoCaller
   */
    private $NexmoCaller;

    /**
    * @var Application\Service\TropoCaller
    */
    private $TropoCaller;
  // Constructor method is used to inject dependencies to the controller.
  public function __construct($entityManager) 
  {
    $this->entityManager = $entityManager;


  }

    public function CallManager($data) 
    {
    $callRequested= new CallRequested;
    $callRequested-> setClientContact($data['clientContact']);
    $callRequested-> setProvider($data['provider']);
    $callRequested-> setCallCenter($data['callCenterContact']);
    $whenCall= $data['schedule'];
    $language= $data['language'];
    $date = new \DateTime();
    $callRequested-> setRequestTime($date);


    $provider=$data['provider'];
    $tropo='Tropo';
    //var_dump($data);


    $this->entityManager->persist($callRequested);
    $this->entityManager->flush();

    $id=$callRequested->getID();
    //var_dump($callRequested->getID());
    $data=array($id,$data);
    $data=json_encode($data, true);

//confirmar onde usar esta lógica
    if($whenCall==='1')
    { echo "Vamos establecer a ligaçao \n";
        if (stripos($provider, $tropo) !== false) {


                                            $destination  = '/queue/tropozend';
                                            $messages = 1;
                                            $size = 256;

                                            $DATA = "calls";

                                            $body = $data;


                                              try {
                                               $connection = new Connection('tcp://192.168.64.3:61613');
                                                $con1 = new StatefulStomp(new Client($connection));


                                                  $con1->send($destination, new Message($body));

                                                    //echo "Message sent $body \n" ;

                                              } catch(StompException $e) {
                                                echo $e->getMessage();

                                                // TropoCall();

                                              }



    } 
    else{                                     
                                              $destination  = '/queue/nexmozend';
                                              $messages = 1;
                                              $size = 256;

                                              $DATA = "calls";

                                              $body = $data;

                                              try {
                                               $connection = new Connection('tcp://192.168.64.3:61613');
                                                $con1 = new StatefulStomp(new Client($connection));


                                                  $con1->send($destination, new Message($body));

                                                    //echo "Message sent $body \n" ;


                                                    } catch(StompException $e) {
                                                echo $e->getMessage();
                                                    }

                                                    }
                                                   // NexmoCall();

     }
     else {echo "Vamos agendar a sua chamada \n"; 
 }


}
}

I created the NexmoCaller and TropoCaller, but don't know how to called them. Here is one example of the logic: class NexmoCaller

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


    public function NexmoCall()
    {

            $service= new NexmoCaller();
            $serviceManager->set(NexmoCaller::class, $service); 

$key = file_get_contents('scripts/application.key');

$basic  = new \Nexmo\Client\Credentials\Basic($keyNexmo, $secret);
$keypair = new \Nexmo\Client\Credentials\Keypair($key, $application_id);
$client = new \Nexmo\Client(new \Nexmo\Client\Credentials\Container($basic, $keypair));

$jwt = generate_jwt($application_id, $key);


header('Content-Type: application/json', 'Authorization: Bearer'.$jwt); 

$destination  = '/queue/nexmozend';


      $connection = new Connection('tcp://192.168.64.3:61613');
      $stomp = new StatefulStomp(new Client($connection));
      $stomp->subscribe($destination);


      echo "Waiting for messages...\n";
        while(true) {
                     $frame = $stomp->read();
                     $body = $frame->getBody();
                     //echo($frame);
                     echo "message received $body \n";
                     //echo $stomp->read()->body, PHP_EOL;
                    //print_r($frame = $stomp->read());
                    //print_r($stomp->read()->body);
                    break;
                    }


//codificar o json como é necessário       
$json = json_decode($body, true);
var_dump($json);

}

}

My config.module.php

'controllers' => [
        'factories' => [
            Controller\IndexController::class => Controller\Factory\IndexControllerFactory::class,

        ],
    ],
    'service_manager' => [
        'factories' => [
                    Service\CallManager::class => Service\Factory\CallManagerFactory::class,
                    Service\NexmoCaller::class => InvokableFactory::class,
                    Service\TropoCaller::class => InvokableFactory::class,
        ],            
    ],

I have tried several aproaches but none of them creates the manager or calls it... Plus, I haven't found any case of using a service inside a service, so i am not even sure it is possible... One of the solutions I've tried was: -constructing in my call manager:

   /**
   * Doctrine entity manager.
   * @var Doctrine\ORM\EntityManager
   */
    private $entityManager;

   /**
   * @var Application\Service\NexmoCaller
   */
    private $NexmoCaller;

    /**
    * @var Application\Service\TropoCaller
    */
    private $TropoCaller;
     public function __construct($entityManager, $NexmoCaller, 
       $TropoCaller) 
      {
        $this->entityManager = $entityManager;
        $this->NexmoCaller = $NexmoCaller;
        $this->TropoCaller = $TropoCaller;

       }

And I get this error:

Too few arguments to function Application\Service\CallManager::__construct(), 1 passed in /opt/lampp/htdocs/buttoncall/skeleton-application/module/Application/src/Service/Factory/CallManagerFactory.php on line 15 and exactly 3 expected

Or simply by calling:

 $this->NexmoCaller->NexmoCaller();

And get this: Call to a member function NexmoCaller() on null

I used answer gaven, in my Factory:

<?php
namespace Application\Service\Factory;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Application\Service\CallManager;
use Application\Service\NexmoCaller;
use Application\Service\TropoCaller;

class CallManagerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $entityManager = $container->get('doctrine.entitymanager.orm_default');
         $nexmoCaller = $container->get(NexmoCaller::class);
        $tropoCaller = $container->get(TropoCaller::class);

        return new $requestedName(
            $entityManager, 
            $nexmoCaller, 
            $tropoCaller
    );


    }
}

And get this: Call to a member function NexmoCaller() on null

What should I do?

ines pelaez
  • 473
  • 1
  • 3
  • 10
  • 1
    what does not work ? what is the error you get. Don't worry you can call a service inside a service. – Unex Sep 12 '17 at 15:37
  • @Unex I've updated my question with what I tried and the error I got. – ines pelaez Sep 12 '17 at 16:27
  • Thanks for the update, the answer provided by @JFloresI should be working. This is a weird error you are having now. Have you tried adding `memory_limit=-1` into your php.ini file ? This could also be linked to xdebug being misconfigured and returning much much much much informations – Unex Sep 13 '17 at 08:36
  • @Unex I've set it to -1, like you said and now: Out of memory (allocated 983564288) (tried to allocate 262144 bytes) – ines pelaez Sep 13 '17 at 08:53
  • Seems like an infinite loop somewhere. Try to use very simple method from each manager just to display that you can call them. You will find the error. Services are correctly loaded, this issue must come from your code – Unex Sep 13 '17 at 08:58
  • i get: Call to a member function NexmoCall() on null – ines pelaez Sep 13 '17 at 15:17
  • In your CallManagerFactory, try to print out `echo NexmoCaller::class;` and see if it outputs the correct path of the class – evilReiko Sep 14 '17 at 08:40
  • It means that your line `$nexmoCaller = $container->get(NexmoCaller::class);` does not return a nexmoCall class. Instead of `Service\NexmoCaller::class => InvokableFactory::class,` in your service-manager config, try to register it into an 'invokables' key (and not 'factories'). `invokables' => array( NexmoCaller::class => NexmoCaller::class, ),` You can search for example on service-manager configuration in zf3 documentation – Unex Sep 15 '17 at 09:41

1 Answers1

1

From what I understand you are trying to use the NexmoCaller and TropoCaller inside of the CallManager but you haven't injected them.

You are on the right path creating the constructor:

public function __construct($entityManager, $NexmoCaller, $TropoCaller) 
{
    $this->entityManager = $entityManager;
    $this->NexmoCaller = $NexmoCaller;
    $this->TropoCaller = $TropoCaller;
}

But while you are expecting 3 parameter the error tells us that the CallManagerFactory is only sending 1.

To solve this modify the CallManagerFactory so it looks something like this:

public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
    $entityManager = $container->get('doctrine.entitymanager.orm_default');
    $nexmoCaller = $container->get(NexmoCaller::class);
    $tropoCaller = $container->get(TropoCaller::class);

    return new $requestedName(
        $entityManager, 
        $nexmoCaller, 
        $tropoCaller
    );
}
JFloresI
  • 91
  • 1
  • 3
  • I think I have a memory problem, using that solution. ( and i've already tried increase memory limit..) Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 262144 bytes) – ines pelaez Sep 13 '17 at 08:25
  • @inespelaez memory issues are usually caused by infinite loop. I can see you have `while(true)` in NexmoCall() function. – evilReiko Sep 14 '17 at 08:50
  • The memory issue was solved, it returns the function NULL when i call the services, now.. – ines pelaez Sep 14 '17 at 09:10