Override protected method in Laravel Illuminate class - php

I'd like to override the following method in Laravel's Illuminate\Foundation\Vite class:
/**
* Generate a script tag for the given URL.
*
* #param string $url
* #return string
*/
protected function makeScriptTag($url)
{
return sprintf('<script type="module" src="%s"></script>', $url);
}
...by adding a "defer" attribute to the script tag. How would I go about doing this, as this is a protected function?

May be like that :
<?php
namespace myApp;
use Illuminate\Foundation\Vite as IllVite;
class myClass extends IllVite{
//...
protected function makeScriptTag($url){
return sprintf('<script type="module" src="%s" defer></script>', $url);
}
//...
}
In the controller(s) which call "Vite", change :
use Illuminate\Foundation\Vite;
by
use myApp\myClass;

The svgta is right, if you use that method in another place in your app.
But, if you want to change only that particular behavior, and not to use it in other places, then you can rewrite the original class and replace it by binding changed class to the app in app/Providers/AppServiceProvider:
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(
'Illuminate\Foundation\Vite', // original class that will be replaced
'App\VendorRewrites\ViteChanged' // custom class that will be injected
);
}
............
Another post that can help: Laravel 6-7 How Can I Override/Change a Vendor Class?

Related

Laravel container returning multiple Singleton instances

I've created a CustomProvider, added it to the app.php array of providers and registered a class as singleton:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\ReserveCart;
class CustomProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->singleton('App\ReserveCart', function($app){
return new ReserveCart;
});
}
}
but everytime I request for the object with $rc = resolve('App\ReserveCart'); it keeps giving me different instances of the object instead of a single one (I've done some echo tracking).
Also tried passing the dependency to methods acording to Laravel Documentation. e.g
public function foo(App\ReserveCart $rc){
//
}
but the issue persists.
Is the output below same ?
$rc = resolve('App\ReserveCart');
$rc1 = resolve('App\ReserveCart');
dd(spl_object_hash($rc), spl_object_hash($rc1));

How to access current placeholder value?

Symfony 3.4.
I have annotations for my controller:
/**
*
* #Route("/{prefix}", requirements={"prefix":"daily_task|event"})
*/
class TaskController extends Controller
and want to access current {prefix} value directly from controller's methods (which aren't routed actions). How to get it's value?
Finally: $this->get('request_stack')->getCurrentRequest()->get('prefix')
Symfony will pass you the variables automatically if you use them as function parameters, like this:
/**
*
* #Route("/{prefix}", requirements={"prefix":"daily_task|event"})
*/
class TaskController extends Controller {
/**
* #Route("/{_locale}/some/path", name="_some_route_name")
*/
public function actualAction($prefix, $_locale) { /* ... */ }
}
Alternatively you can use the whole request like this:
/**
*
* #Route("/{prefix}", requirements={"prefix":"daily_task|event"})
*/
class TaskController extends Controller {
/**
* #Route("/{_locale}/some/path", name="_some_route_name")
*/
public function actualAction(Request $request) {
$prefix = $request->get('prefix');
}
}

Calling a CommandController from ActionController in PHP/TYPO3 Extbase

I wrote a Command Controller that handles data import from an URL.
pseudo-syntax is like this:
class ImportCommandController extends \TYPO3\CMS\Extbase\Mvc\Controller\CommandController
{
public function importCommand($auth){
$data = file_get_content();
}
}
this works.
But when I try to call that command from the Action Controller of my backend Module I get errors.
Heres the code:
ActionController:
class ImportController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
/**
* #var \Vendor\MyExt\Command\ImportCommandController importCommandCtrl
* #inject
*/
protected $importCommandCtrl;
public function importAction()//($url,$usr,$pass)
{
//$this->importCommandCtrl = GeneralUtility::makeInstance('Vendor\MyExt\Command\ImportCommandController');
$this->importCommandCtrl->testCommand();
}
}
When I call importAction() like this, I get:
"Call to a member function testCommand() on null"
When I uncomment the makeInstance, I get:
"Call to a member function get() on null"
Sadly, this topic is documente rather poorly in the TYPO3 Docs.
Can someone help me on this or point me to the right direction?
I'd like to slightly alter the answer already given by René and add some code examples. I also recommend to put your import logic into a dedicated class, e.g. ImportService:
namespace Vendor\MyExt\Service;
use TYPO3\CMS\Core\SingletonInterface;
class ImportService implements SingletonInterface
{
public function importData()
{
// import logic goes here
}
}
You can now inject this class as a dependency of your CommandController and your ActionController:
class ImportController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
/**
* #var \Vendor\MyExt\Service\ImportService
* #inject
*/
protected $importService;
public function importAction()
{
$this->importService->importData();
}
}
class ImportCommandController extends \TYPO3\CMS\Extbase\Mvc\Controller\CommandControlle
{
/**
* #var \Vendor\MyExt\Service\ImportService
* #inject
*/
protected $importService;
public function importCommand()
{
$this->importService->importData();
}
}
The use of an CommandController in an ActionController is not recommended because they have different envoiroment variables.
If you want to use some code on more position it's recommanded to use Utility classes.
So create an Class in the my_ext/Classes/Utility/ directory call the class something like ImportUtility and try to code your import independed from some controller.

Forward with another template

I'm facing a problem with the forward method of Symfony (v2.3).
Basicly, I have two controllers in two distinct bundles. Let's say DesktopBundle for a desktop version of the app, and MobileBundle for the mobile version.
I want to reuse code of an action of the DesktopBundle into an action of MobileBundle. What I do now is a forward :
DesktopController
namespace Acme\DesktopBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/**
* #Route("/")
*/
class IndexController extends Controller
{
/**
* #Route("", name="desktopIndex")
* #Template()
*/
public function indexAction()
{
/* some code I don't want to duplicate */
return array(
'some' => 'var'
);
}
}
MobileController
namespace Acme\MobileBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/**
* #Route("/")
*/
class IndexController extends Controller
{
/**
* #Route("", name="mobileIndex")
* #Template()
*/
public function indexAction()
{
return $this->forward('AcmeDesktopBundle:Index:index');
}
}
Now it works, but obviously the Response object is returned with the rendered template of the desktop version of the indexAction.
What I would like, is to get the variables and then render the template of the mobile version.
What I tried is to pass a variable into the forward method and then render the action conditionally into the desktop version:
return $this->forward(
'acmeDesktopBundle:Index:index',
array('mobile' => true)
);
This would work, but I don't really want to change to code inside the DesktopBundle but only the MobileBundle. Is there a way to achieve this ? I am missing something, or should I go to an entirely different solution ?
Forwarding means to redirect to the given page, but without changing the url on the client. I.e. redirect on the server side. If you want only access the return value of the action, simply call it. With the #Template annotation this is made very easy.
namespace Acme\MobileBundle\Controller;
use Acme\DesktopBundle\Controller\IndexController as DesktopController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/**
* #Route("/")
*/
class IndexController extends Controller
{
/**
* #Route("", name="mobileIndex")
* #Template()
*/
public function indexAction()
{
$desktop = new DesktopController();
$desktop->setContainer($this->container);
$values = $desktop->indexAction();
// do something with it
return $values;
}
}

calling a php class function syntax

I am currently looking a this piece of code from a module called ZfcUser for Zend 2:
namespace ZfcUser\Controller;
use Zend\Form\Form;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Stdlib\ResponseInterface as Response;
use Zend\Stdlib\Parameters;
use Zend\View\Model\ViewModel;
use ZfcUser\Service\User as UserService;
use ZfcUser\Options\UserControllerOptionsInterface;
class UserController extends AbstractActionController
{
/**
* #var UserService
*/
protected $userService;
.
.
public function indexAction()
{
if (!$this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('zfcuser/login');
}
return new ViewModel();
}
.
.
}
In the namespace ZfcUser\Controller\Plugin:
namespace ZfcUser\Controller\Plugin;
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager;
use ZfcUser\Authentication\Adapter\AdapterChain as AuthAdapter;
class ZfcUserAuthentication extends AbstractPlugin implements ServiceManagerAwareInterface
{
/**
* #var AuthAdapter
*/
protected $authAdapter;
.
.
/**
* Proxy convenience method
*
* #return mixed
*/
public function hasIdentity()
{
return $this->getAuthService()->hasIdentity();
}
/**
* Get authService.
*
* #return AuthenticationService
*/
public function getAuthService()
{
if (null === $this->authService) {
$this->authService = $this->getServiceManager()->get('zfcuser_auth_service');
}
return $this->authService;
}
My Questions:
From indexAction(), the controller plugin is called without being instantiated ($this->zfcUserAuthentication()->hasIdentity()), do controller plugins always work like this?.
What really happens in the hasIdentity()? I see getAuthService() returning something but not hasIdentity().I am not familiar with this type of advanced class implementation of function calling so I would truly appreciate any explanation here or topic I should look into.
I can't answer your first question, but regarding your second question:
The getAuthService() method in your code returns an AuthenticationService object, which has a hasIdentity() method.
So there are two different hasIdentity() methods:
In the AuthenticationService class (source code here).
In the ZfcUserAuthentication class which you're looking at.
This line of code in the ZfcUserAuthentication class:
return $this->getAuthService()->hasIdentity();
does three things:
$this->getAuthService() returns an AuthenticationService object.
The hasIdentity() method of that AuthenticationService object is then called, and it returns a boolean.
That boolean is then returned.
Imagine splitting the code into two parts:
// Get AuthenticationService object Call a method of that object
$this->getAuthService() ->hasIdentity();
Hope that helps!
All sorts of plugins in Zend Framework are managed by plugin managers, which are subclasses of AbstractPluginManager which is subclasss of ServiceManager.
$this->zfcUserAuthentication() proxies by AbstractController to pluginmanager internally.
AuthenticationService::hasIdentity() checks if something was added to storage during successful authentication attempt in this or previous request:
See here

Categories