zend framework 2 dose not access database from console application - php

I am trying to run a controller from console, which is going to be used for a cron job. When I run the following Code Block in a http controller, it works perfectly.
But when I use the same Code Block in a console controller and call it from Command Line, I get database error message:
"Statement could not be executed (3D000 - 1046 - No database selected"
I can't understand why it is not getting the database name and perhaps other parameters from config's local.php.
Any hint is appreciated
// CODE BLOCK IN CONTROLLER
$sm = $this->getServiceLocator();
$dbAdapter = $sm->get('Mymodule\Service\Db');
$actualDatabaseTableName = 'Operator';
$OperatorTableGateway = new TableGateway($actualDatabaseTableName,$dbAdapter);
$table = new OperatorTable($OperatorTableGateway);
$result = $table->getOperatorList();
var_dump($result->current());
And model class is
namespace Mydodule\Model;
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\Sql\Select;
class OperatorTable {
protected $tableGateway;
public function __construct(TableGateway $tableGateway) {
$this->tableGateway = $tableGateway;
}
public function getOperatorList() {
$select = new Select('Operator');
$select->columns(array(
'opId'=>'OperatorID',
'ocode'=>'OperatorCode'
));
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
}

So I finally found the issue. It is all about Environment value.
The HTTPS request was getting EVN value from apache setting.
And the setting in application.config.php was
$env = getenv('APP_ENV') ? : 'prod';
and since my prod.local.php was kind a empty, I did not work.
So what I learned is if you use Console application, the env value setting in apache will not kick in, or atleast in my case, and instead Console will use the setting in application.config.php

Related

Relationship is working in Laravel Tinker but not within controller

I made a manyToMany relationship and want to return that in my php code which is not working, but when I run the same code in tinker it is working for some reason. What am I missing?
// Firma
public function auftraege()
{
return $this->belongsToMany("Auftrag", 'auftraege_firma');
}
// Auftrag
public function firmen()
{
return $this->belongsToMany("Firma", 'auftraege_firma');
}
// works in tinker
$firma = App\Firma::first();
$firma->auftraege
// Does not work in php Controller
$firma = App\Firma::first();
return $firma->auftraege
Getting 500 Error
Looking at your controller code, I can only notice two things. Change your controller code like this:
$firma = \App\Firma::first();
return $firma->auftraege;
You are missing \ before the App namespace and also the semicolon is missing in the return statement.
Please also change the relationshps like this:
public function auftraege()
{
return $this->belongsToMany(Auftrag::class, 'auftraege_firma');
}
public function firmen()
{
return $this->belongsToMany(Firma::class, 'auftraege_firma');
}
The reason it was working from tinker is that by default tinker sets the namespace to App for the current tinker session. That's why even though you didn't specify the App namespace, tinker was able to parse the proper namespace.

Zend xmlrpc error

I have this error with Zend (v1) XmlRpc client :
Uncaught exception 'Zend_XmlRpc_Client_FaultException' with message 'Failed to parse response'.
It's the error status 651.
The call never reaches the class/method requested, it seems that the call is not fired like it was blocked or something. I'm in debug on the method called and it's not triggered.
PHP version is 5.4.
EDIT
Here is the code :
Caller class :
require_once 'library/Zend/XmlRpc/Client.php';
class FrontService
{
private $client;
public function __construct($xmlRpc)
{
$this->client = new Zend_XmlRpc_Client($xmlRpc);
}
public function call($name, $params = array())
{
return $this->client->call($name, $params);
}
}
Call to the class :
$this->_fs = new FrontService(HM_Config::getParam("amf-url"));
$editos = $this->_fs->call('getEdito',$params_home);
Code called :
include_once realpath(dirname(__FILE__) .'/..')
.'/application/bootstrap.php';
require_once '_config.php';
require_once 'DirectDbConnectionV2.php';
class FrontGateway extends DirectDbConnectionV2
{
public static $smStatic;
function __construct()
{
mysql_query("SET NAMES 'utf8'");
$this->sm = self::$smStatic;
$this->log = new Log();
$this->log->set_file('amfDbConnection');
$this->log->write('construct bordel');
}
}
FrontGateway::$smStatic = $sm;
$controllerManager = $sm->get('EditoWebsiteMVC\ControllerManager');
$controllerManager->run('EditoWebsite\Controller\UIGateway', 'xmlRpc');
Code that should be executed :
namespace EditoWebsite\Controller;
use EditoWebsiteMVC\AbstractController;
use EditoWebsiteMVC\ViewRender\CLI as CLIViewRender;
use EditoWebsiteMVC\ViewRender\HTMLTemplate as HTMLTemplateViewRender;
use Zend_XmlRpc_Server as XmlRpcServer;
class UIGatewayController extends AbstractController
{
public function xmlRpcAction()
{
$svr = new XmlRpcServer();
$svr->setClass('FrontGateway');
echo $svr->handle();
exit;
}
}
The code in the getEdito method from the DirectDbConnectionV2 is never reached.
Is there something I need to enable on the server ? or a port that I need to open ?
EDIT EDIT
I should mention that the code is working on another server that I've access to, is there anything I should compare / check to maybe solve that issue ?
Thanks a lot
I don't think there's enough info to even make a guess, but let me try.
I've faced similar issue, where requests sent never reached the server. It turned out to be that Zend_Http_Client_Adapter_Socket adapter is binding to an IPv6 and due to routing issues request never got to the server.
In the end, what solved the issue was:
$client->getAdapter()->setStreamContext(array(
'socket' => array('bindto' => '0:0'),
));
where $client is an instance of Zend_Http_Client.
Again, it's just a shot in the dark, but could be worth trying. :)
Edit:
In your case, you should add following to FrontService constructor:
$this->client->getHttpClient()->getAdapter()->setStreamContext(array(
'socket' => array('bindto' => '0:0'),
));
Edit Edit:
Since back on 1.9.0 there's no getAdapter on Zend_Http_Client, you have to create adapter yourself and pass it to http client:
public function __construct($xmlRpc)
{
$this->client = new Zend_XmlRpc_Client($xmlRpc);
$adapter = Zend_Http_Client_Adapter_Socket();
$adapter->setStreamContext(array(
'socket' => array('bindto' => '0:0'),
));
$this->client->getHttpClient()->setAdapter($adapter);
}
Cheers.

Mocking a service called by a controller from a WebTestCase

I have an API written using Symfony2 that I'm trying to write post hoc tests for. One of the endpoints uses an email service to send a password reset email to the user. I'd like to mock out this service so that I can check that the right information is sent to the service, and also prevent an email from actually being sent.
Here's the route I'm trying to test:
/**
* #Route("/me/password/resets")
* #Method({"POST"})
*/
public function requestResetAction(Request $request)
{
$userRepository = $this->get('app.repository.user_repository');
$userPasswordResetRepository = $this->get('app.repository.user_password_reset_repository');
$emailService = $this->get('app.service.email_service');
$authenticationLimitsService = $this->get('app.service.authentication_limits_service');
$now = new \DateTime();
$requestParams = $this->getRequestParams($request);
if (empty($requestParams->username)) {
throw new BadRequestHttpException("username parameter is missing");
}
$user = $userRepository->findOneByUsername($requestParams->username);
if ($user) {
if ($authenticationLimitsService->isUserBanned($user, $now)) {
throw new BadRequestHttpException("User temporarily banned because of repeated authentication failures");
}
$userPasswordResetRepository->deleteAllForUser($user);
$reset = $userPasswordResetRepository->createForUser($user);
$userPasswordResetRepository->saveUserPasswordReset($reset);
$authenticationLimitsService->logUserAction($user, UserAuthenticationLog::ACTION_PASSWORD_RESET, $now);
$emailService->sendPasswordResetEmail($user, $reset);
}
// We return 201 Created for every request so that we don't accidently
// leak the existence of usernames
return $this->jsonResponse("Created", $code=201);
}
I then have an ApiTestCase class that extends the Symfony WebTestCase to provide helper methods. This class contains a setup method that tries to mock the email service:
class ApiTestCase extends WebTestCase {
public function setup() {
$this->client = static::createClient(array(
'environment' => 'test'
));
$mockEmailService = $this->getMockBuilder(EmailService::class)
->disableOriginalConstructor()
->getMock();
$this->mockEmailService = $mockEmailService;
}
And then in my actual test cases I'm trying to do something like this:
class CreatePasswordResetTest extends ApiTestCase {
public function testSendsEmail() {
$this->mockEmailService->expects($this->once())
->method('sendPasswordResetEmail');
$this->post(
"/me/password/resets",
array(),
array("username" => $this->user->getUsername())
);
}
}
So now the trick is to get the controller to use the mocked version of the email service. I have read about several different ways to achieve this, so far I've not had much luck.
Method 1: Use container->set()
See How to mock Symfony 2 service in a functional test?
In the setup() method tell the container what it should return when it's asked for the email service:
static::$kernel->getContainer()->set('app.service.email_service', $this->mockEmailService);
# or
$this->client->getContainer()->set('app.service.email_service', $this->mockEmailService);
This does not effect the controller at all. It still calls the original service. Some write ups I've seen mention that the mocked service is 'reset' after a single call. I'm not even seeing my first call mocked out so I'm not certain this issue is affecting me yet.
Is there another container I should be calling set on?
Or am I mocking out the service too late?
Method 2: AppTestKernel
See: http://blog.lyrixx.info/2013/04/12/symfony2-how-to-mock-services-during-functional-tests.html
See: Symfony2 phpunit functional test custom user authentication fails after redirect (session related)
This one pulls me out of my depth when it comes to PHP and Symfony2 stuff (I'm not really a PHP dev).
The goal seems to be to change some kind of foundation class of the website to allow my mock service to be injected very early in the request.
I have a new AppTestKernel:
<?php
// app/AppTestKernel.php
require_once __DIR__.'/AppKernel.php';
class AppTestKernel extends AppKernel
{
private $kernelModifier = null;
public function boot()
{
parent::boot();
if ($kernelModifier = $this->kernelModifier) {
$kernelModifier($this);
$this->kernelModifier = null;
};
}
public function setKernelModifier(\Closure $kernelModifier)
{
$this->kernelModifier = $kernelModifier;
// We force the kernel to shutdown to be sure the next request will boot it
$this->shutdown();
}
}
And a new method in my ApiTestCase:
// https://stackoverflow.com/a/19705215
protected static function getKernelClass(){
$dir = isset($_SERVER['KERNEL_DIR']) ? $_SERVER['KERNEL_DIR'] : static::getPhpUnitXmlDir();
$finder = new Finder();
$finder->name('*TestKernel.php')->depth(0)->in($dir);
$results = iterator_to_array($finder);
if (!count($results)) {
throw new \RuntimeException('Either set KERNEL_DIR in your phpunit.xml according to http://symfony.com/doc/current/book/testing.html#your-first-functional-test or override the WebTestCase::createKernel() method.');
}
$file = current($results);
$class = $file->getBasename('.php');
require_once $file;
return $class;
}
Then I alter my setup() to use the kernel modifier:
public function setup() {
...
$mockEmailService = $this->getMockBuilder(EmailService::class)
->disableOriginalConstructor()
->getMock();
static::$kernel->setKernelModifier(function($kernel) use ($mockEmailService) {
$kernel->getContainer()->set('app.service.email_service', $mockEmailService);
});
$this->mockEmailService = $mockEmailService;
}
This works! However I now can't access the container in my other tests when I'm trying to do something like this:
$c = $this->client->getKernel()->getContainer();
$repo = $c->get('app.repository.user_password_reset_repository');
$resets = $repo->findByUser($user);
The getContainer() method returns null.
Should I be using the container differently?
Do I need to inject the container into the new kernel? It extends the original kernel so I don't really know why/how it's any different when it comes to the container stuff.
Method 3: Replace the service in config_test.yml
See: Symfony/PHPUnit mock services
This method requires that I write a new service class that overrides the email service. Writing a fixed mock class like this seems less useful than a regular dynamic mock. How can I test that certain methods have been called with certain parameters?
Method 4: Setup everything inside the test
Going on #Matteo's suggestion I wrote a test that did this:
public function testSendsEmail() {
$mockEmailService = $this->getMockBuilder(EmailService::class)
->disableOriginalConstructor()
->getMock();
$mockEmailService->expects($this->once())
->method('sendPasswordResetEmail');
static::$kernel->getContainer()->set('app.service.email_service', $mockEmailService);
$this->client->getContainer()->set('app.service.email_service', $mockEmailService);
$this->post(
"/me/password/resets",
array(),
array("username" => $this->user->getUsername())
);
}
This test fails because the expected method sendPasswordResetEmail wasn't called:
There was 1 failure:
1) Tests\Integration\Api\MePassword\CreatePasswordResetTest::testSendsEmail
Expectation failed for method name is equal to <string:sendPasswordResetEmail> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
Thanks to Cered's advice I've managed to get something working that can test that the emails I expect to be sent actually are. I haven't been able to actually get the mocking to work so I'm a bit reluctant to mark this as "the" answer.
Here's a test that checks that an email is sent:
public function testSendsEmail() {
$this->client->enableProfiler();
$this->post(
"/me/password/resets",
array(),
array("username" => $this->user->getUsername())
);
$mailCollector = $this->client->getProfile()->getCollector('swiftmailer');
$this->assertEquals(1, $mailCollector->getMessageCount());
$collectedMessages = $mailCollector->getMessages();
$message = $collectedMessages[0];
$this->assertInstanceOf('Swift_Message', $message);
$this->assertEquals('Reset your password', $message->getSubject());
$this->assertEquals('info#example.com', key($message->getFrom()));
$this->assertEquals($this->user->getEmail(), key($message->getTo()));
$this->assertContains(
'This link is valid for 24 hours only.',
$message->getBody()
);
$resets = $this->getResets($this->user);
$this->assertContains(
$resets[0]->getToken(),
$message->getBody()
);
}
It works by enabling the Symfony profiler and inspecting the swiftmailer service. It's documented here: http://symfony.com/doc/current/email/testing.html

ZF2 - Job queue to create a PDF file using SlmQueueBeanstalkd and DOMPDFModule

I'm trying to run a job queue to create a PDF file using SlmQueueBeanstalkd and DOMPDFModule in ZF".
Here's what I'm doing in my controller:
public function reporteAction()
{
$job = new TareaReporte();
$queueManager = $this->serviceLocator->get('SlmQueue\Queue\QueuePluginManager');
$queue = $queueManager->get('myQueue');
$queue->push($job);
...
}
This is the job:
namespace Application\Job;
use SlmQueue\Job\AbstractJob;
use SlmQueue\Queue\QueueAwareInterface;
use SlmQueue\Queue\QueueInterface;
use DOMPDFModule\View\Model\PdfModel;
class TareaReporte extends AbstractJob implements QueueAwareInterface
{
protected $queue;
public function getQueue()
{
return $this->queue;
}
public function setQueue(QueueInterface $queue)
{
$this->queue = $queue;
}
public function execute()
{
$sm = $this->getQueue()->getJobPluginManager()->getServiceLocator();
$empresaTable = $sm->get('Application\Model\EmpresaTable');
$registros = $empresaTable->listadoCompleto();
$model = new PdfModel(array('registros' => $registros));
$model->setOption('paperSize', 'letter');
$model->setOption('paperOrientation', 'portrait');
$model->setTemplate('empresa/reporte-pdf');
$output = $sm->get('viewPdfrenderer')->render($model);
$filename = "/path/to/pdf/file.pdf";
file_put_contents($filename, $output);
}
}
The first time you run it, the file is created and the work is successful, however, if you run a second time, the task is buried and the file is not created.
It seems that stays in an endless cycle when trying to render the model a second time.
I've had a similar issue and it turned out it was because of the way ZendPdf\PdfDocument reuses it's object factory. Are you using ZendPdf\PdfDocument?
You might need to correctly close factory.
class MyDocument extends PdfDocument
{
public function __destruct()
{
$this->_objFactory->close();
}
}
Try to add this or something similar to the PdfDocument class...
update : it seem you are not using PdfDocument, however I suspect this is the issue is the same. Are you able to regenerate a second PDF in a normal http request? It is your job to make sure the environment is equal on each run.
If you are unable to overcome this problem a short-term quick solution would be to set max_runs configuration for SlmQueue to 1. That way the worker is stopped after each job and this reset to a vanilla state...

error not found model after upload into hosting

In localhost, it works fine. After uploading into my hosting i got this error. I'm using zend framework 1.12.
Fatal error: Class 'Application_Models_DBTable_Kereta' not found in /home/mysite/public_html/application/controllers/CarController.php
others post said the problem is because the case sensitivity of file names. But i tried to change and nothing happens. See my attachment for the structured of my project. The attachment shown application and model names.
edited : This problem occurs to all my models class.. can't find models..
Controller code :
class CarController extends Zend_Controller_Action
{
public function init()
{
/* Initialize action controller here */
//klu login sbgai admin, papar layout admin, klu login sbgai user, papar layout user laaaa,
Zend_Session::start();//start session
$session = new Zend_Session_Namespace("MyNamespace");
$id_pengguna = $session->id_pengguna;
$kategori = $session->kategori;
if($kategori==3)
{
$this->_helper->layout->setLayout('layoutadmin');
}
else
{
}
}
public function indexAction()
{
// $albums = new Application_Model_DbTable_Albums();
//$this->view->albums = $albums->fetchAll();
}
public function reservationAction()
{
if($this->getRequest()->isPost())
{
$jadual_tarikhmula = $this->getRequest()->getPost("jadual_tarikhmula");
$jadual_tarikhtamat = $this->getRequest()->getPost("jadual_tarikhtamat");
$jadual_masamula1 = $this->getRequest()->getPost("jadual_masamula1");
$jadual_masamula2 = $this->getRequest()->getPost("jadual_masamula2");
$jadual_masatamat1 = $this->getRequest()->getPost("jadual_masatamat1");
$jadual_masatamat2 = $this->getRequest()->getPost("jadual_masatamat2");
$simpan = array($jadual_tarikhmula,$jadual_tarikhmula,$jadual_masamula1,$jadual_masatamat1);
$papar = $this->view->dataReserve= $simpan;
$db = new Application_Model_DbTable_Kereta();
$paparkereta = $this->view->reserve = $db->getReservationCar($jadual_tarikhmula,$jadual_tarikhmula,$jadual_masamula1,$jadual_masatamat1);
$this->view->dataWujud = count($paparkereta);
$gambar = $this->view->gambarKereta = $db->getGambarKereta($paparkereta[0]['id_kereta'],false);
}
}
}
Your folder name is DbTable and your model class name is ..._DBTable_... ?
Note that Linux is case-sensitive directory or filename.
And did you add this line to .ini file?
Appnamespace = "Application"
Are you sure you don't have another class named Kereta in /home/mysite/public_html/application/controllers/CarController.php ?
Also, consider cleaning the symfony cache with symfony cc. It's the cache for autoload that is giving you this error I guess.

Categories