Call to a member function has() on null - php

im learning symfony. I have a twig using twig extension and i found that i cannot call a function from other controller inside twig extension.
so i have decide to use a service since the twig extension is using the service.
so i tried to call a function from controller in the service and call the function from the service in the twig extension.
Then, i have an error message that [Call to a member function has() on null], where $doct = $this->getDoctrine()->getManager(); in the controller.
this is the function in the controller that i'm trying to use
edited
namespace Customize\Controller;
use Customize\Entity\CustomRing;
use Customize\Entity\Ring;
use Customize\Repository\CustomProductRepository;
use Eccube\Controller\AbstractController;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\Product;
use Eccube\Entity\ProductClass;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\ProductClassRepository;
use Eccube\Service\CartService;
use Eccube\Service\OrderHelper;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Service\PurchaseFlow\PurchaseFlow;
use Eccube\Service\PurchaseFlow\PurchaseFlowResult;
use Google\Service\Monitoring\Custom;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class CartController extends AbstractController
{
/**
* #var ProductClassRepository
*/
protected $productClassRepository;
/**
* #var CartService
*/
protected $cartService;
/**
* #var PurchaseFlow
*/
protected $purchaseFlow;
/**
* #var BaseInfo
*/
protected $baseInfo;
/**
* #var CustomProductRepository
*/
protected $customProductRepository;
/**
* CartController constructor.
*
* #param ProductClassRepository $productClassRepository
* #param CartService $cartService
* #param PurchaseFlow $cartPurchaseFlow
* #param BaseInfoRepository $baseInfoRepository
* #param CustomProductRepository $customProductRepository
*/
public function __construct(
ProductClassRepository $productClassRepository,
CartService $cartService,
PurchaseFlow $cartPurchaseFlow,
BaseInfoRepository $baseInfoRepository,
CustomProductRepository $customProductRepository
) {
$this->productClassRepository = $productClassRepository;
$this->cartService = $cartService;
$this->purchaseFlow = $cartPurchaseFlow;
$this->baseInfo = $baseInfoRepository->get();
$this->customProductRepository = $customProductRepository;
}
public function image_route(){
$Carts = $this->cartService->getCarts();
$doct = $this->getDoctrine()->getManager();
$custom_images = array();
$Custom_product = $this->customProductRepository->customProductFindByName();
$Product = $doct->getRepository(Product::class)->find($Custom_product[0]->getId());
foreach ($Carts as $Cart) {
$items = $Cart->getCartItems();
foreach($items as $item ){
if($item->getProductClass()->getProduct()->getId() == $Product->getId()){
$custom = $item->getProductClass()->getCode();
$custom = $doct->getRepository(CustomRing::class)->find($custom);
$ring = $doct->getRepository(Ring::class)->find($custom->getRingBaseId());
$upload_directory= $this->getParameter('uploads_directory');
$ring_shape = $ring->getRingShape();
$ring_type = $ring->getRingType();
$upload = $upload_directory.'/customRing/ring/'.$ring_shape.'/'.$ring_type.'/';
$images = glob($upload."*.{jpg,png,jpeg,JPG,JPEG,PNG}", GLOB_BRACE);
for($i=0;$i<count($images);$i++){
$aa = explode('save_image/', $images[$i]);
$images[$i] = $aa[1];
}
array_push($custom_images,$images[0]);
}
}
}
return $custom_images;
use Customize\Controller\CartController;
/**
* #var CartController
*/
protected $cartController;
public function __construct(
SessionInterface $session,
EntityManagerInterface $entityManager,
ProductClassRepository $productClassRepository,
CartRepository $cartRepository,
CartItemComparator $cartItemComparator,
CartItemAllocator $cartItemAllocator,
OrderRepository $orderRepository,
TokenStorageInterface $tokenStorage,
AuthorizationCheckerInterface $authorizationChecker,
CartController $CartController
) {
$this->session = $session;
$this->entityManager = $entityManager;
$this->productClassRepository = $productClassRepository;
$this->cartRepository = $cartRepository;
$this->cartItemComparator = $cartItemComparator;
$this->cartItemAllocator = $cartItemAllocator;
$this->orderRepository = $orderRepository;
$this->tokenStorage = $tokenStorage;
$this->authorizationChecker = $authorizationChecker;
$this->cartController = $CartController;
}
/*other functions
.
.
*/
public function imagess(){
$temp = $this->cartController->image_route();
return $temp;
}
and this is the twig extension
use Eccube\Service\CartService;
class CartServiceExtension extends AbstractExtension
{
/**
* #var CartService
*/
protected $cartService;
public function get_image_route(){
$t = $this->cartService->imagess();
return $t;
//return ['11', '12'];
}
}
The line i got error in controller is
$doct = $this->getDoctrine()->getManager();
and when go inside getDoctrine()
trait ControllerTrait{
/**
* Shortcut to return the Doctrine Registry service.
*
* #return ManagerRegistry
*
* #throws \LogicException If DoctrineBundle is not available
*
* #final
*/
protected function getDoctrine()
{
if (!$this->container->has('doctrine')) {
throw new \LogicException('The DoctrineBundle is not registered in your application. Try running "composer require symfony/orm-pack".');
}
return $this->container->get('doctrine');
}
I don't know why but it seems has() function inside getDoctrine() returns null
how can i use the function from the controller so that i can pass the values of $custom_images into the twig?

To get Doctrine in any controller action, you can do away with that function/trait entirely and just inject the EntityManagerInterface into your action.
For example:
class SomeCustomController extends AbstractController
{
public function someControllerAction(Request $request, EntityManagerInterface $em): Response
{
// business logic
}
}

Related

Accessing Properties from Classes inside of traits

I'm trying to write a unit test for the startedAt() method using mocks however the problem I'm facing is that I don't think I can access the builder instance from inside that startedAt() method.
To test the startedAt() method I created a fixture class called ExampleFilters and had it extend the parent class of Filters. Inside of the ExampleFilters class I import the FiltersByStartDate trait.
Does anyone have any suggestions on how I can access the builder property from the FiltersByStartDate trait?
Any ideas on this?
<?php
namespace App\Filters\Concerns;
trait FiltersByStartDate
{
/**
* Filter a query to include models of a specific date started.
*
* #param array $startedAt
* #return \Illuminate\Database\Eloquent\Builder
*/
public function startedAt($startedAt)
{
if (isset($startedAt[1])) {
$this->builder->whereHas('currentEmployment', function ($query) use ($startedAt) {
$query->whereBetween('started_at', [
$startedAt[0],
$startedAt[1]
]);
});
} else {
$this->builder->whereHas('currentEmployment', function ($query) use ($startedAt) {
$query->whereDate('started_at', $startedAt[0]);
});
}
return $this->builder;
}
}
<?php
namespace Tests\Fixtures;
use App\Filters\Concerns\FiltersByStartDate;
use App\Filters\Filters;
class ExampleFilters extends Filters
{
use FiltersByStartDate;
}
<?php
namespace App\Filters;
use Illuminate\Http\Request;
abstract class Filters
{
/**
* #var \Illuminate\Http\Request
*/
protected $request;
/**
* The Eloquent builder.
*
* #var \Illuminate\Database\Eloquent\Builder
*/
protected $builder;
/**
* Registered filters to operate upon
*
* #var array
*/
protected $filters = [];
/**
* Create a new class instance.
*
* #param \Illuminate\Http\Request $request
*/
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* Apply the filters.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #return \Illuminate\Database\Eloquent\Builder
*/
public function apply($builder)
{
$this->builder = $builder;
foreach ($this->getFilters() as $filter => $value) {
if (method_exists($this, $filter)) {
$this->$filter($value);
}
}
return $this->builder;
}
/**
* Fetch all relevant filters from the request.
*
* #return array
*/
public function getFilters()
{
return array_filter($this->request->only($this->filters));
}
}
<?php
namespace Tests\Unit\Filters\Concerns;
use Illuminate\Database\Query\Builder;
use Tests\Fixtures\ExampleFilters;
use Tests\TestCase;
/*
* #group filters
*/
class FiltersByStartDateTest extends TestCase
{
/* #var Tests\Fixtures\ExampleFilters */
protected $subject;
public function setUp(): void
{
$this->subject = app(ExampleFilters::class);
}
/** #test */
public function models_can_be_filtered_by_their_start_date()
{
// $this->markTestIncomplete();
$dateSet = ['2020-01-01 00:00:00'];
$mock = \Mockery::mock(Builder::class)
->shouldReceive('whereHas', \Mockery::any())
->shouldReceive('whereDate')
->withArgs(['started_at', $dateSet])
->once()
->andReturn(true)
->getMock();
dd($this->subject->startedAt($dateSet));
$builderMockFromDate = $this->subject->startedAt($dateSet);
$this->assertSame($builderMockFromDate, $mock);
}
}

Symfony 3.4 cannot load fixtures on Test: Error: Call to a member function get() on null

I have the following phpunit test for testing the controllers:
The DefaultControllerTest:
namespace Tests\AppBundle\Controller;
use Tests\AppBundle\Controller\BasicHttpController;
use AppBundle\DataFixtures\Test\DummyUserFixtures;
/**
* #testtype Functional
*/
class DefaultControllerTest extends BasicHttpController
{
/**
* {#inheritdoc}
*/
public function setUp()
{
$fixture = new DummyUserFixtures();
$fixture->load($this->entityManager);
}
/**
* Testing the Behavior when visiting the index page
*/
public function testIndex()
{
$client = $this->client;
$router=$client->getContainer()->get('router');
$crawler = $client->request('GET', '/');
$response=$client->getResponse();
$this->assertTrue($client->getResponse()->isRedirect());
$this->assertEquals($router->getRouteCollection()->get('fos_user_security_login')->getPath(),$response->headers->get('Location'));
//#todo Create Dummy Users
// $this->checkPanelAfterSucessfullLogin($crawler);
}
}
That extends the following test BasicHttpController (try to apply the DRY principle):
namespace Tests\AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
class BasicHttpController extends WebTestCase
{
protected $entityManager=null;
protected $client=null;
/**
* {#inheritdoc}
*/
public function __construct()
{
parent::__construct();
$this->client = static::createClient();
$container = $this->client->getContainer();
$doctrine = $container->get('doctrine');
$this->entityManager=$doctrine->getManager();
}
/**
* Remove all entities from the database
*/
protected function truncateEntities()
{
$purger = new ORMPurger($this->entityManager());
$purger->purge();
}
/**
* {#inheritdoc}
*/
public function tearDown()
{
$this->truncateEntities();
}
/**
* #param username String the user's username
* #param passwoρd String the user's password
*/
protected function checkPanelAfterSucessfullLogin($crawler,string $username,string $password)
{
//Submitting the form
$form=$crawler->selectButton('_submit')->form();
$form['_username']=$username;
$form['_password']=$password;
$crawler=$crawler->submit($form);
$response=$client->getResponse();
$this->assertTrue($client->getResponse()->isRedirect());
$client->followRedirect();
//Checking header
$headerDom=$crawler->filter('header')->childen()->filter('nav.navbar')->children();
$this->assertCount(1,$headerDom->find('a.navbar-brand')); //homepage link
$this->assertCount(1,$headerDom->find('a.btn-danger')); //Logout button
}
}
As you can see I try to load the following fixture:
namespace AppBundle\DataFixtures\Test;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\Common\Persistence\ObjectManager;
class DummyUserFixtures extends AbstractFixture implements OrderedFixtureInterface,ContainerAwareInterface
{
/**
* #var ContainerInterface
*/
private $container=null;
/**
* {#inheritDoc}
*/
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
/**
* Generic function that creates a user with provided information.
* #param $name {String} The user's name
* #param $surname {String} The user's surname
* #param $username {String} The user's username
* #param $password {String} The user's password
* #param $email {String} The user's recovery email
* #param $role {String} The user's system role
* #param $phone {String | null} The user's phone number
* #param $organization {String|null} The user's organization
* #param $occupation {String|null} The user's occupation
*
* #return AppBundle\Entity\User
*/
private function createUser($name,$surname,$username,$password,$email,$role,$phone=null,$organization=null,$occupation=null)
{
$fosUserManager=$this->container->get('fos_user.user_manager');
/**
* #var AppBundle\Entity\User
*/
$user=$fosUserManager->createUser();
$user->setUsername($username);
$user->setEmail($email);
$user->setPlainPassword($password);
$user->setEnabled(true);
$user->setRoles(array($role));
$user->setName($name);
$user->setSurname($surname);
if($phone){
$user->setPhone($phone);
}
if($organization){
$user->setOrganization($organization);
}
if($occupation){
$user->setOccupation($occupation);
}
$fosUserManager->updateUser($user, true);
return $user;
}
/**
* {#inheritDoc}
*/
public function load(ObjectManager $manager)
{
$this->createUser('John','Doe','jdoe','simplepasswd','jdoe#example.com','ROLE_USER','+3021456742324','Acme Products','Soft Engineer');
$this->createUser('Jackie','Chan','jchan','thesimplepasswd','jackiechan#example.com','ROLE_ADMIN','+302141232324','Holywood','Actor');
$this->createUser('Chuck','Norris','chuck_norris','unhackablepasswd','chucknorris#example.com','ROLE_SUPERADMIN',null,'Universe','Master');
}
public function getOrder()
{
return 1;
}
}
But for some reason I get the following error:
There was 1 error:
1) Tests\AppBundle\Controller\DefaultControllerTest::testIndex
Error: Call to a member function get() on null
/home/vagrant/code/src/AppBundle/DataFixtures/Test/DummyUserFixtures.php:50
/home/vagrant/code/src/AppBundle/DataFixtures/Test/DummyUserFixtures.php:87
/home/vagrant/code/tests/AppBundle/Controller/DefaultControllerTest.php:19
Further debugging has proved that the error is triggered by the following line in DummyUserFixtures:
$fosUserManager=$this->container->get('fos_user.user_manager');
So do you know how to load the data via fixtures?
In order to get it working you should set the service container you generate from the static::createClient() method and pass it via the $fixture->setContainer($container)
So a good approach is to define the container as protected instance variable to the BasicHttpController so any Test class (eg. the DefaultControllerTest in your case) is able to load the fixtures accordingly.
So using the setUp method and instance variables of BasicHttpController should be the following:
//Namespace declaration goes there
class BasicHttpController extends WebTestCase
{
protected $entityManager=null;
protected $client=null;
protected $container=null;
/**
* {#inheritdoc}
*/
public function setUp()
{
$this->client = static::createClient();
$this->container = $this->client->getContainer();
$doctrine = $this->container->get('doctrine');
$this->entityManager=$doctrine->getManager();
}
// Rest methods here
}
Note: on classes that are getting inherited from BasicHttpController you can define the setUp like that:
public function setUp()
{
parent::setUp();
// Add extra stuff here
}
So you can do more setUp bootstrapping before tests.

Persisting Updated Objects in Symfony

I have a symfony application where I am attempting to update an entity in the database using a setter. However when I update the entity and call $this->em->flush() the entity is not persisted to the database.
Here is my service:
<?php
namespace AppBundle\Service;
use AppBundle\Exceptions\UserNotFoundException;
use Doctrine\ORM\EntityManager;
use AppBundle\Entity\User;
/**
* Class MyService
* #package AppBundle\Service
*/
class MyService extends BaseService {
/**
* #var EntityManager
*/
protected $em;
/**
* #var User
*/
protected $user;
/**
* MyService constructor.
* #param EntityManager $em
*/
public function __construct(EntityManager $em){
$this->em = $em;
}
/**
* See if a user email exists
* #param string $email
* #return bool
*/
public function checkEmailExists($email){
$this->user = $this->em
->getRepository('AppBundle:User')
->findOneBy(['email' => $email]);
return !(is_null($this->user));
}
/**
* add credit to a users account
* #param User $user
* #param integer $credit
*/
public function addCredit(User $user, $credit){
$user->addCredit($credit);
$this->em->flush();
}
/**
* add a credit to a users account
* #param $email
* #param $credit
*/
public function addCreditByEmail($email, $credit){
if(!($this->checkEmailExists($email))){
throw new UserNotFoundException(sprintf('User with email %s not found.', $email));
}
$this->addCredit($this->user, $credit);
}
}
Here is my test:
<?php
namespace AppBundle\Tests\Service;
use AppBundle\DataFixtures\ORM\PurchaseFixture;
use AppBundle\Entity\Vendor;
use AppBundle\Repository\OfferRepository;
use AppBundle\Tests\TestCase;
use AppBundle\Entity\Offer;
use AppBundle\DataFixtures\ORM\OfferFixture;
use AppBundle\DataFixtures\ORM\PaymentSystemFixture;
/**
* Class UserOfferServiceTest
* #package AppBundle\Tests\Service
*/
class MyServiceTest extends TestCase implements ServiceTestInterface
{
function __construct($name = null, array $data = [], $dataName = '')
{
$this->setFixtures([
'AppBundle\DataFixtures\ORM\CityFixture',
'AppBundle\DataFixtures\ORM\CountryFixture',
'AppBundle\DataFixtures\ORM\PaymentSystemFixture',
'AppBundle\DAtaFixtures\ORM\UserFixture',
]);
parent::__construct($name, $data, $dataName);
}
/**
* test the checkEmailExists() of app.vendor
*/
public function testCheckEmailExists(){
$myService = $this->getService();
$this->assertTrue($myService->checkEmailExists('user1#user1.com'));
$this->assertFalse($myService->checkEmailExists($this->fake()->safeEmail));
}
/**
* test the addCredit functionality
*/
public function testAddCredit(){
$myService = $this->getService();
$user = $this->getUser();
$this->assertEquals(0, $user->getCredit());
$toAdd = $this->fake()->numberBetween(1, 500);
$myService->addCredit($user, $toAdd);
$this->assertEquals($toAdd, $user->getCredit());
}
/**
* test the addCreditByEmail functionality
*/
public function testAddCreditByEmail(){
$myService = $this->getService();
$user = $this->getUser();
$email = $this->getUser()->getEmail();
$this->assertEquals(0, $user->getCredit());
$toAdd = $this->fake()->numberBetween(1, 500);
$myService->addCreditByEmail($email, $toAdd);
$updatedUser = $this->getEntityManager()
->getRepository('AppBundle:User')
->findOneBy(['email' => $email]);
$this->assertEquals($toAdd, $updatedUser->getCredit());
}
/**
* #return \AppBundle\Service\VendorService|object
*/
public function getService(){
$this->seedDatabase();
$this->client = $this->createClient();
return $this->client->getContainer()->get('app.admin_kiosk');
}
}
The testAddCredit() test passes (because I'm checking the same object), but the testAddCreditByEmail fails with the following error: 1) AppBundle\Tests\Service\MyServiceTest::testAddCreditByEmail
Failed asserting that null matches expected 149.
I've tried persisting the entity, flushing the entity (like: $this->em->flush($user)) all to no avail. Please let me know how I can fix this.
I found the issue.
In the test case I just had to refresh the entity by doing $this->getEntityManager()->refresh($user) (on the original $user entity). Thanks!

how to get current url and base path in my view helper function using zf2

This function is in helper I am using zf2 version 2.4 I am beginner in zend please help me.
I tried this:
function getUrlArray(){
$helperUrl = new Url(); // use Zend\View\Helper\Url;
$op = $helperUrl->url();
print_r($op);
}
I am getting this error:
Fatal error: Call to undefined method Zend\View\Helper\Url::url()
Try this ViewHelper :
<?php
namespace YourNamespace\View\Helper\Service;
use YourNamespace\View\Helper\CurrentUri;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class CurrentUriFactory implements FactoryInterface
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return CurrentUri
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$helper = new CurrentUri();
$helper->setRequest($serviceLocator->getServiceLocator()->get('Request'));
return $helper;
}
}
<?php
namespace YourNamespace\View\Helper;
use Zend\Stdlib\RequestInterface;
use Zend\View\Helper\AbstractHelper;
/**
* Helper: $this->currentUri();
*/
class CurrentUri extends AbstractHelper
{
/**
* #var \Zend\Http\PhpEnvironment\Request
*/
protected $request;
/**
* #return string
* #see \Zend\Http\PhpEnvironment\Request
* #see \Zend\Uri\Uri
*/
public function __invoke()
{
return $this->getRequest()->getUri()->toString();
}
/**
* #return \Zend\Http\PhpEnvironment\Request
*/
public function getRequest()
{
return $this->request;
}
/**
* #param RequestInterface $request
* #return CurrentUri
*/
public function setRequest(RequestInterface $request)
{
$this->request = $request;
return $this;
}
}

Symfony2 how to get entity manager in Listener

Im trying to insert data into database in onKernelRequest using doctrine
//** src/MPN/CRMBundle/Listener/AnalyticsListener.php
namespace MPN\CRMBundle\Listener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use MPN\CRMBundle\Manager\AnalyticsManager;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Response;
use Doctrine\ORM\EntityManager;
use vRonn\StatisticsBundle\Entity\Statistics as Statistics;
class AnalyticsListener
{
/**
* #var AnalyticsManager
*/
private $am;
private $em;
public function __construct(AnalyticsManager $am)
{
$this->am = $am;
}
public function onKernelRequest(GetResponseEvent $event)
{
if (!$event->isMasterRequest()) {
return;
}
$request = $event->getRequest();
$session = $request->getSession();
$uri = $request->getRequestUri();
$route = $request->get('_route');
if (!preg_match('#^/(app_dev\.php/)?(admin|js|media|_[^/]+)/?.*#', $uri)) {
// add page view count
$this->am->addPageView();
//Here is how i try to insert data
$d = new Statistics();
$d->setType(1);
$d->setName('blabla');
$d->setValue('val');
$em = $this->am->em->getRepository('vRonnStatisticsBundle:Statistics');
$em->persist($d);
$em->flush();
if (!$session->has('visitor') || $session->get('visitor') < time()) {
$session->set('visitor', time() + (24 * 60 * 60));
$this->am->addVisitor();
}
$this->am->save();
}
}
but i get error below
Undefined method 'persist'. The method name must start with either
findBy or findOneBy!
Here is the manager which i take the entity manager from, i take entity from here because i tried both $this->get('doctrine') or $this->getDoctrine() inside onKernelRequest but error
//** src/MPN/CRMBundle/Manager/AnalyticsManager.php
namespace MPN\CRMBundle\Manager;
use Doctrine\ORM\EntityManager;
use MPN\CRMBundle\Entity\Analytics;
use MPN\CRMBundle\Service\DateTimeBuilder;
class AnalyticsManager
{
/**
* #var EntityManager
*/
public $em;
/**
* #var DateTimeBuilder
*/
private $dateTimeBuilder;
/**
* #var array
*/
private $analytics;
public function __construct(EntityManager $em, DateTimeBuilder $dateTimeBuilder)
{
$this->em = $em;
$this->dateTimeBuilder = $dateTimeBuilder;
$this->setup();
}
/**
* Flushes the data to the database.
*
* #return void
*/
public function save()
{
$this->em->flush();
}
}
It looks like you're setting $em to a repository, not an entity manager. If you just do $em = $this->am->em it oughta work.

Categories