PHP: Class extends problem "Call to private method ... from context ..." - wordpress

I have 3 classes in WordPress (the question itself is unrelated to it):
class WP_Widget
class Theme_Widget extends WP_Widget
class Specific_Widget extends Theme_Widget
Essentially Theme_Widget contains some extension functions to the basic WP_Widget.
Inside Specific_Widget I call one of Theme_Widget's methods:
class Specific_Widget {
function __construct() {
$this->some_method_that_belongs_to_Theme_Widget();
}
}
When I instantiate Specific_Widget, PHP throws a fatal error as follows:
Fatal error: Call to private method Theme_Widget::some_method_that_belongs_to_Theme_Widget() from context 'Specific_Widget' in ...
Do you have an idea as to how I can resolve this? This is the first time I've received this error from PHP. Could it be derive from WordPress itself?

You must declare your method protected, rather than private, if you wish child classes to be able to use it.

use protected function if you would to access a child functions from your extended class's without passing the protected function in URLs
for example
protected function somemethod() { // your code goes here }

Related

Can't create test that extends WebTestCase in Symfony

I'm having difficulty creating functional test for my bundle. Whenever I create a test class that extends Symfony\Bundle\FrameworkBundle\Test\WebTestCase and launch bin/phpunit, I get following error:
Fatal error: Cannot declare class <MyTestClass>, because the name is already in use in <path/to/my/test/class> on line <some_line>
I've got some unit tests running just fine. If I extend PHPUnit\Framework\TestCase for example, I get no problems launching my tests (but obviously I'm losing the functionality I need from WebTestCase).
My test class looks as follows:
<?php
namespace Some\Namespace\MyBundle\Test\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class UserControllerTest extends WebTestCase
{
public function setUp()
{
$client = self::createClient();
}
public function testCreateUser()
{
}
}
By the looks of it, it's the self::createClient(); that causes the problem. However I do need the client to send some requests

Symfony 4 : Call to a member function get() on null

class EtudiantController extends AbstractController
{
private $etudiant ;
private $form ;
public function __construct()
{
$this->etudiant = new Etudiant();
$this->form = $this->createForm(EtudiantType::class, new Etudiant());
}
}
** i'v got an error when instantiate a form in a constructor using the createForm() function **
Here is the wrong way to solve your problem:
class EtudiantController extends AbstractController
{
private $form;
public function __construct(FormFactoryInterface $formFactory)
{
$this->form = $formFactory->create(TextType::class, new Etudiant());
}
}
I say it is wrong (even though it will work) because creating things like forms really should be done in individual controller actions, not hidden in the constructor. You might be trying to apply Dont Repeat Yourself (DRY) but in cases like this, Don't Confuse Your Future Self takes precedence.
And as far as why injecting the form factory is necessary, I would once again urge you to look at the Symfony source code for AbstractController as well as ControllerTrait. Understanding how dependency injection works is critical to being able to effectively use the framework.

BaseController to handle client factory

I want to build a base controller that I can put some reusable methods so I do not have to put a bunch of repeat code in all my controllers. So I built a BaseController.cs
public class BaseController : Controller
{
public IHttpClientFactory _clientFactory;
public BaseController(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
}
Then in one of my contollers I do public class TokenController : BaseController. But then it wants me to add the following but then it gives me errors
public TokenController(IHttpClientFactory clientFactory)
{
// I guess something goes here
}
But then VS Code tells me
There is no argument given that corresponds to the required formal parameter 'clientFactory' of 'BaseController.BaseController(IHttpClientFactory)' (CS7036)
What am I missing here? I been in JS world to long :)
When inheriting classes without default constructors you have to pass parameters to them using the following syntax:
public TokenController(IHttpClientFactory clientFactory) : base (clientFactory)
{
/* other initializations */
}
So add the following expression: : base (clientFactory)
See more information here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/using-constructors

Symfony Call to a member function get() on null

I use Symfony components in own framework. I installed DI component and tried to get it in my BaseController but all the time I get the same error:
Call to a member function get() on null
My base controller:
abstract class BaseController implements ContainerAwareInterface
{
use ContainerAwareTrait;
...
}
And when I try to access $this->container->get('ser_id'); return call to a member function.
How to slove this?
Update:
only work if i include in my controller service container
$this->service_container = include __DIR__ .'/../../../container.php';
and use it like this:
$this->service_container->get('id');

I have no access to container in my controller

I am trying to access a service in a Symfony Controller
$session = $this->get('session');
But I get the next error:
PHP Fatal error: Call to a member function get() on a non-object
I thought that Symfony2 had the controllers defined as services by default.
Note: this question was originally asked by Dbugger, but he removed it for no reason, while it was already answered.
Using the container in controllers
get() is only a shortcut function provided by the Symfony base Controller class to access the container.
Your controller must extend this class to use this function:
namespace Acme\ExampleBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
// your actions
}
If you don't want to depend on this class (for some reasons) you can extend ContainerAware to get the container injected and use it like in the get() shortcut:
namespace Acme\ExampleBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerAware;
class DefaultController extends ContainerAware
{
public function exampleAction()
{
$myService = $this->container->get('my_service');
// do something
}
}
Creating controllers on your own
Controllers are not defined as services per default, you can define them, but it's not needed to get the container. If a request is made, the routing framework determines the controller, which need to be called. Then the controller gets constructed and the container is injected via the setContainer() method.
But if you construct the controller on your own (in a test or anywhere else), you have to inject the container on your own.
$controller = new DefaultController();
$controller->setContainer($container);
// $container comes trough DI or anything else.

Resources