I am working on Magento 2. I want to use other module's block function to get some data. How can I call that block function in my module's model file ?
The two ways to call you a block class method in custom module class
1) using constructor dependency
like that
public function __construct(Namespace\ModuleName\Helper\Data $helper)
{
$this->helper = $helper;
}
public function MyFunction()
{ $this->helper->HelperDemo();
}
2) using method dependency
public function execute(Namespace\ModuleName\Helper\Data $helper)
{
$helper->HelperDemo();
}
for more detail visit the below link
https://devdocs.magento.com/guides/v2.3/extension-dev-guide/depend-inj.html
Related
how do they achieve, that Illuminate\Database\Eloquent\Relations\Relation has access to all query builder functions?
I see they have a $query property, but does not explain how all its methods are available inside relation
If you are aware of php magic methods then you will know __call method
this method will be called when you initialize a php object and you try to call a method which is not available in the class. By using __call method from the Illuminate\Database\Eloquent\Relations\Relation class they are forwarding the call to Illuminate\Database\Eloquent\Builder. I will explain it very clearly by pointing out the code.
Inside the laravel framework there is a trait named as ForwardsCalls . This trait is used in many classes to handle the call forwarding to another class.
So here is how the call from the Relation class is forwarded to Builder class. While initilting the new Relation class Builder class will be initialized. So when you try to call a method from reltion class which is not available it will call __call method. After that it will look for a available macros . So when a macros method is not found. Then it will use forwardDecoratedCallTo from ForwardsCalls Trait.
So forwardDecoratedCallTo will accept 3 arguments namely $object, $method and $parameters. Whereas
$object will be $this->query which has a Illuminate\Database\Eloquent\Builder instance.
$method will be the method the you try to access from Builder Method.
$parameters will be the all the parameters that is be passed to the method.
I will try to Demonstrate will the example without the traits and helpers from laravel
class ClassTwo {
public function classTwoMethodOne()
{
dd(__FUNCTION__.' has been called');
}
public function classTwoMethodTwo()
{
dd(__FUNCTION__.' has been called');
}
public function classTwoMethodThree()
{
//you cannot call this method dynamically
dd(__FUNCTION__.' has been called');
}
}
class ClassOne {
public function classOneMethodOne()
{
dd(__FUNCTION__.' has been called');
}
public function classOneMethodTwo()
{
dd(__FUNCTION__.' has been called');
}
public function __call($methodName, $arguments)
{
$methodsTobeForwarededtoClassTwo = [
'classTwoMethodOne',
'classTwoMethodTwo',
// 'classTwoMethodThree'
//i have commented this method so you cannot access it
//from dynamic calls
];
if(in_array($methodName,$methodsTobeForwarededtoClassTwo))
{
return (new ClassTwo)->{$methodName}($arguments);
}
dd(sprintf(
'Call to undefined method ClassTwo::%s()', $methodName
));
}
}
So here comes the testing part.
$classOneobj = new ClassOne;
Basic Test
dump($classOneobj->classOneMethodOne()); will output as classOneMethodOne has been called
dump($classOneobj->classOneMethodTwo()); will output as classOneMethodTwo has been called
Dynamic Call Test
dump($classOneobj->classTwoMethodOne()); will output as classTwoMethodOne has been called
dump($classOneobj->classTwoMethodTwo()); will output as classOneMethodTwo has been called
dump($classOneobj->classTwoMethodThree()); will output as Call to undefined method ClassTwo::classTwoMethodThree() Because i have commented that method in __call function in ClassOne.
If you still need clarity please post a comment
I have this code in the HomeController#index:
$towns = Town::all();
return Redirect::to('home')
->with('towns', $towns);
Is there any way I can tell Laravel to execute that lines of code before the end of methods and controllers I define without me copying and pasting those lines of code in every method?
You don't need to do that, you can just share this data with all views by using the view()->share() method in a service provider:
view()->share('towns', Town::all());
You can also use a view composer for that:
public function compose(View $view)
{
$view->with('towns', Town::all());
}
You can extend all controllers from your basic controller. Use Controller.php on app/Http/Controllers/controller.php or create new one.
Add myThreeLines to base controller.
controller.php:
function myThreeLines(){
$towns = Town::all();
return Redirect::to('home')
->with('towns', $towns);
}
class TestController extend Controller{
function index(){
return $this->myThreeLines();
}
}
I feel I repeat myself in Laravel (4) controllers. For example, I need some $variables for every view. I get them from cache or database. Because geting and processing them take some lines of codes (between 5-100 lines), I repeat them in every controller function. This is especially a problem when updating functions (They increase complexity).
How can I avoid this without any negative effect?
Note: $variables are mostly not global variables.
There are many ways to go about this, but it sounds like the variables are more specific to your View's than your controllers.
You can easily share variables across your views in the boot method of your AppServiceProvider.
view()->share('variables', function(){
//you can share whatever you want here and it will be availble in all views.
});
You can create a static helper class (all static functions)
e.g.
class VarHelper {
public static function getVars() {
return [];
}
}
You can create your own basecontroller you extend in every other controller
e.g.
class MyController extends Controller {
public function getVars() {
return [];
}
}
class BlaController extends MyController {
public function doBla() {
$vars = $this->getVars();
}
}
creating the function inside the controller and call it in the other functions
use a Trait
And probably more solutions
Create a trait with a method to set all of the necessary variables.
use View;
trait SharedControllerVariables {
public function loadUsersSubscription() {
View::make('user_subscription_variable_1', [...data...]);
View::make('user_subscription_variable_2', [...data...]);
}
}
Then call it in your controller constructor:
class MyController extends Controller {
use SharedControllerVariables;
public function __construct() {
$this->loadUsersSubscription();
}
}
Is it possible to call a function in a certain module every request?
Let say I have module name called 'configuration', on this module, I have a list of controllers and list of functions/methods. What I want is to automatically pass my "Menu" to the View without manually passing it on each methods and controllers.
This menu is only available when inside the 'configuration module.
// I have extended the base controller to create common functions
ConfigureController extends \BaseController
{
protected function processMenu() {
}
}
// One of my controller that needs to render processMenu()
SetupController extends ConfigureController
{
public index()
{
// I want to optimize this portion so that I do not have to call it evertime
$pass_to_view = $this->processMenu();
// I need to pass it again and again
return View::make('setup')->with('data', $pass_to_view );
}
}
PS. sample code only
Thank you in advance!
Use the BaseController constructor method __construct() and within the SetupController's constructor call parent::__construct();
This is where the view composers come handy.
Put your menu in a partial, include it in you layout, then register a view composer (doc here: http://laravel.com/docs/4.2/responses#view-composers).
You can put your register code anywhere, for instance you could create a file composers.php in app and include it in your app/start/global.php.
I have a plugin: Simple Configurable Products. I've upgraded to 1.8.1 but have an issue with showing the price - it stops rendering the page.
I have found the line that's causing the issue:
parent::_toHtml();
The class that is calling that is as follows:
class OrganicInternet_SimpleConfigurableProducts_Catalog_Block_Product_Price
extends Mage_Catalog_Block_Product_Price
{
public function _toHtml() {
// Do some stuff
return parent::_toHtml();
}
}
So as I see it, the parent class should be: Mage_Catalog_Block_Product_Price. And the line that calls this should simply call the function _toHtml(). Taking this line out means it works, but returns no price. Ideally I need it to render the default/base price html.
Thanks in advance
Try calling it like this:
class OrganicInternet_SimpleConfigurableProducts_Catalog_Block_Product_Price
extends Mage_Catalog_Block_Product_Price {
public function _toHtml() {
// Do some stuff
return Mage_Catalog_Block_Product_Price::_toHtml();
}
}
Call the object by name instead of by parent::_toHtml()