Try and data to database and get an error.:
Uncaught Error: Call to a member function persist() on null in
public function addNewPostAction()
{
// Create new Post entity..
// $entityManager = $container->get('doctrine.entitymanager.orm_default');
$post = new Post();
$post->setTitle('Top 10+ Books about Zend Framework 3');
$post->setContent('Post body goes here');
$post->setStatus(Post::STATUS_PUBLISHED);
$currentDate = date('Y-m-d H:i:s');
$post->setDateCreated($currentDate);
$this->entityManager->persist($post);
$this->entityManager->flush();
}
UPDATE:
Error:
Zend\Mvc\Controller\PluginManager::get was unable to fetch or create an instance for get
public function addNewPostAction()
{
// Create new Post entity..
// $entityManager = $container->get('doctrine.entitymanager.orm_default');
$post = new Post();
$post->setTitle('Top 10+ Books about Zend Framework 3');
$post->setContent('Post body goes here');
$post->setStatus(Post::STATUS_PUBLISHED);
$currentDate = date('Y-m-d H:i:s');
$dm = $this->get('doctrine.odm.mongodb.document_manager');
$dm->persist($post);
$dm->flush();
}
From the 2 samples above, it is obvious you are trying to get doctrine `s entity manager.
1st sample:
$this->entityManager
probably the property $entityManager of the controller is not set, also from the commented code
$entityManager = $container->get('doctrine.entitymanager.orm_default');
it is obvious you are trying to get entity manager.
2nd sample:
$this->get('doctrine.odm.mongodb.document_manager');
I assume this is from a symfony example.
Anyway to get the doctrine manager in your controller, you have to inject it, change your controller constructor to accept it as an argument:
class IndexController extends AbstractActionController
{
private $doctrineManager;
public function __construct($doctrineManager)
{
$this->doctrineManager = $doctrineManager;
}
and then inject the doctrine manager to your controller factory in your module.config.php:
'controllers' => [
'factories' => [
Controller\IndexController::class => function ($container) {
return new Controller\IndexController(
$container->get('doctrine.odm.mongodb.document_manager')
);
},
// ...
],
],
Side note: the error "Zend\Mvc\Controller\PluginManager::get was unable to fetch or create an instance for get" is thrown because zend tries any undefined methods to resolve them to a plugin, eg. if you define a plugin with name myAwesomePlugin, you can access it in your action as:
$this->myAwesomePlugin();
Related
Now, I know this question has been asked a lot, but I searched and searched but I just can't figure it out and I've been stuck for hours now. I'm really sorry if it turnes out to be a really dumb mistake (It probably will).
So, I have my Controller which instatiates the editAction() function when a button on my website is pressed. It checks if the request is a _POST request, passes on the data and checks if the input given is valid, all this works fine.
I then try to access a function in my Manager class. And that's where the error is happening and my website spits out:
"Call to a member function updateJob() on null".
Now, PhpStorm is not saying there's an error or a warning, it recognizes the jobManager class and I've checked the namespaces and class names, but all are correct. The variables are also defined correctly, as far as I can see. I'd be really thankful if someone could tell me what I am doing wrong. The code is below.
current state after adding $jobManager to __construct:
class IndexController extends AbstractActionController
{
/**
* Entity manager.
* #var EntityManager
*/
private $entityManager;
/**
* Post manager.
* #var JobManager
*/
private $jobManager;
public function __construct($entityManager, $jobManager)
{
$this->entityManager = $entityManager;
/***
* Edit from comment advice:
* I have added this line to my __construct
* But this does not solve the issue.
***/
$this->jobManager = $jobManager;
}
public function indexAction()
{
// Get recent jobs
$jobs = $this->entityManager->getRepository(Jobs::class)
->findBy(['status'=>Jobs::STATUS_READY]
);
// Render the view template
return new ViewModel([
'jobs' => $jobs
]);
}
public function editAction()
{
// Create the form.
$form = new JobForm();
// Get post ID.
$jobId = $this->params()->fromRoute('id', -1);
// Find existing job in the database.
$jobs = $this->entityManager->getRepository(Jobs::class)
->findOneById($jobId);
if ($jobs == null) {
$this->getResponse()->setStatusCode(404);
return;
}
// Check whether this job 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 job manager service to add new post to database.
$this->jobManager->updateJob( $jobs, $data);
// Redirect the user to "backups" page.
return $this->redirect()->toRoute('backups');
}
} else {
$data = [
'id' => $jobs->getId(),
'jobName' => $jobs->getJobName(),
'status' => $jobs->getStatus(),
'vmId' => $jobs->getVmId(),
'targetfolderPrefix' => $jobs->getTargetFolderPrefix(),
'numberOfBackups' => $jobs->getNumberOfBackups(),
'lastBackupUsed' => $jobs->getLastBackupUsed(),
'repeat' => $jobs->getRepeat(),
'scheduleRunAtMinute' => $jobs->getScheduleRunAtMinute(),
'scheduleRunAtHour' => $jobs->getScheduleRunAtHour(),
'scheduleRunAtDOW' => $jobs->getScheduleRunAtDOW(),
'hostId' => $jobs->getHostId()
];
$form->setData($data);
}
// Render the view template.
return new ViewModel([
'form' => $form,
'jobs' => $jobs
]);
}
}
What is wrong
$this->jobManager->updateJob( $jobs, $data);
You are telling PHP:
"In $this class, look in the jobManager object and run the method updateJob with these variables.... "
But in $this class you have written:
/**
* Post manager.
* #var JobManager
*/
private $jobManager;
But you have nowhere set jobManager to be anything. You have no setter function in the class as well as no other function setting what a jobManager variable actually is... so jobManager can never be anything.
So what you're in effect doing is saying to PHP
"In $this class, look in the jobManager empty null-space and run the method updateJob with these variables..."
This is clearly not going to end well.
How to fix it
You need to set what jobManager is before you can use it, as referenced by Xatenev. Typically when you construct the class or using a Setter method, if preferred.
ONE:
public function __construct(EntityManager $entityManager, JobManager $jobManagerVar)
{
$this->entityManager = $entityManager;
$this->jobManager = $jobManagerVar;
}
Alternatively - if ->jobManager method needs to be defined after the object IndexController is created; then you need to use a Setter class (because the jobManager var is *private*.
Thus TWO:
class IndexController extends AbstractActionController
{
...
public function setJobManager($jobManagerVar){
$this->jobManager = $jobManagerVar
}
...
}
And then when you instantiate the IndexController you can do:
// ONE from above:
$theClass = new IndexController($entity,$jobManager);
or
// TWO from above
$theClass = new IndexController($entity);
...
$theClass->setJobManager($jobManger);
There are various other nuances as to methods of setting values in classes, I'm not going to go over them all, it will depend on what's going on in your wider project.
I have the following event listener but want to set a viewVar from it and having some issues figuring out how. If I can't or shouldn't, what would be the best way when I need $products available to the View?
File is ./Products/Lib/Event/Products.php.
<?php
App::uses('CakeEventListener', 'Event');
class Products implements CakeEventListener {
public function implementedEvents() {
return array(
'View.beforeRender' => 'get_products',
);
}
public function get_products($event) {
$this->Product = ClassRegistry::init('Products.Product');
$products = $this->Product->find('all', array(
'fields' => array('Product.*', 'Content.title')
));
$this->set('products', $products);
}
}
Returns Fatal error: Uncaught Error: Call to undefined method Products::set().
You are subscribing to an event triggered by a View object, hence the subject of the event will be that object, and you can access it in your listener method via the event objects subject() method, like:
$event->subject()->set('products', $products);
See also
API > CakeEvent::subject()
API > View::render()
API > View::set()
can anyone tell me how to override actioncreate and actionupdate method yii2 rest api..
class CabController extends ActiveController
{
public $modelClass = 'api\modules\v1\models\Cab';
public function actions(){
$actions = parent::actions();
unset($actions['create']);
unset($actions['update']);
return $actions;
}
public function actionCreate(){
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$model = $this->modelClass;
$model->load(Yii::$app->request->post());
$cur_time = date('Y-m-d H:i:s');
$model->date_created = $cur_time;
$$model->save(false);
}
If i do like this mean i got error like 500 internal server error and error message like Call to a member function load() on a non-object ..how to solve this issue..
Thanks...
You are not creating object, instead you are assigning string api\modules\v1\models\Cab to $model variable. Change assigning part to:
$model = new $this->modelClass;
In case of "Class not found" error add leading backslash to class name: \api\modules\v1\models\Cab.
Related answers about creating object from string:
Creating PHP class instance with a string
Dynamically create PHP object based on string
How to create object from String?
I am new to unit testing and trying to test a controller method in Laravel 5.1 and Mockery.
I am trying to test a registerEmail method I wrote, below:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Response;
use Mailchimp;
use Validator;
/**
* Class ApiController
* #package App\Http\Controllers
*/
class ApiController extends Controller
{
protected $mailchimpListId = null;
protected $mailchimp = null;
public function __construct(Mailchimp $mailchimp)
{
$this->mailchimp = $mailchimp;
$this->mailchimpListId = env('MAILCHIMP_LIST_ID');
}
/**
* #param Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function registerEmail(Request $request)
{
$this->validate($request, [
'email' => 'required|email',
]);
$email = $request->get('email');
try {
$subscribed = $this->mailchimp->lists->subscribe($this->mailchimpListId, [ 'email' => $email ]);
//var_dump($subscribed);
} catch (\Mailchimp_List_AlreadySubscribed $e) {
return Response::json([ 'mailchimpListAlreadySubscribed' => $e->getMessage() ], 422);
} catch (\Mailchimp_Error $e) {
return Response::json([ 'mailchimpError' => $e->getMessage() ], 422);
}
return Response::json([ 'success' => true ]);
}
}
I am attempting to mock the Mailchimp object to work in this situation.
So far, my test looks as follows:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class HomeRouteTest extends TestCase
{
use WithoutMiddleware;
public function testMailchimpReturnsDuplicate() {
$listMock = Mockery::mock('Mailchimp_Lists')
->shouldReceive('subscribe')
->once()
->andThrow(\Mailchimp_List_AlreadySubscribed::class);
$mailchimp = Mockery::mock('Mailchimp')->lists = $listMock;
$this->post('/api/register-email', ['email'=>'duplicate#email.com'])->assertJson(
'{"mailchimpListAlreadySubscribed": "duplicate#email.com is already subscribed to the list."}'
);
}
}
I have phpUnit returning a failed test.
HomeRouteTest::testMailchimpReturnsDuplicate
Mockery\Exception\InvalidCountException: Method subscribe() from Mockery_0_Mailchimp_Lists should be called exactly 1 times but called 0 times.
Also, if I assert the status code is 422, phpUnit reports it is receiving a status code 200.
It works fine when I test it manually, but I imagine I am overlooking something fairly easy.
I managed to solve it myself. I eventually moved the subscribe into a seperate Job class, and was able to test that be redefining the Mailchimp class in the test file.
class Mailchimp {
public $lists;
public function __construct($lists) {
$this->lists = $lists;
}
}
class Mailchimp_List_AlreadySubscribed extends Exception {}
And one test
public function testSubscribeToMailchimp() {
// create job
$subscriber = factory(App\Models\Subscriber::class)->create();
$job = new App\Jobs\SubscribeToList($subscriber);
// set up Mailchimp mock
$lists = Mockery::mock()
->shouldReceive('subscribe')
->once()
->andReturn(true)
->getMock();
$mailchimp = new Mailchimp($lists);
// handle job
$job->handle($mailchimp);
// subscriber should be marked subscribed
$this->assertTrue($subscriber->subscribed);
}
Mockery will expect the class being passed in to the controller be a mock object as you can see here in their docs:
class Temperature
{
public function __construct($service)
{
$this->_service = $service;
}
}
Unit Test
$service = m::mock('service');
$service->shouldReceive('readTemp')->times(3)->andReturn(10, 12, 14);
$temperature = new Temperature($service);
In laravel IoC it autoloads the classes and injects them, but since its not autoloading Mailchimp_Lists class it won't be a mock object. Mailchimp is requiring the class atop it's main class require_once 'Mailchimp/Lists.php';
Then Mailchimp is then loading the class automatically in the constructor
$this->lists = new Mailchimp_Lists($this);
I don't think you'll be able to mock that class very easily out of the box. Since there isn't away to pass in the mock object to Mailchimp class and have it replace the instance of the real Mailchimp_Lists
I see you are trying to overwrite the lists member variable with a new Mock before you call the controller. Are you certain that the lists object is being replaced with you mocked one? Try seeing what the classes are in the controller when it gets loaded and see if it is in fact getting overridden.
I'm writing a custom renderer and following this tutorial that explains how to instantiate PhpRenderer object.
class CustomRenderer implements RendererInterface
{
.....
public function render( $nameOrModel, $values = null )
{
.....
$renderer = new \Zend\View\Renderer\PhpRenderer();
$renderer->setResolver( $this->resolver ); // $this->resolver Zend\View\Resolver\AggregateResolver
return $renderer->render( $model ); // $model Zend\View\Model\ViewModel
.....
Renderer is constantly throwing errors like
'Zend\View\HelperPluginManager::get was unable to fetch or create an
instance for translate
or
'No base path provided' in Zend\View\Helper\BasePath
etc. Basically everything that has to do with helpers in template does not work. Also, tried this code in controller, or with clean model but no luck. Resolver and model are correct.
How to properly instantiate new PhpRenderer object.