I managed to create this simple plugin that I need it to fire a method when ever an item is added to the cart and a method to fire when a checkout has happend. But those methods wont fire in anyway. I also seen another plugin named stockable in virtuemart that uses plgVmOnAddToCart and it fires there correctly. But in my plugins class it wont fire at all.
Here is my code in my plugin, what can I do to make it work? thank you
<?php
defined('_JEXEC') or die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' ) ;
if (!class_exists('vmCustomPlugin')) require(JPATH_VM_PLUGINS . DS . 'vmcustomplugin.php');
class plgVmAftercheckout extends vmCustomPlugin {
private $stockhandle = 0;
function __construct(& $subject, $config) {
parent::__construct($subject, $config);
$varsToPush = array(
'selectname1'=>array('','char'),'selectname2'=>array('','char'),'selectname3'=>array('','char'),'selectname4'=>array('','char'),
'selectoptions1'=>array('','char'),'selectoptions2'=>array('','char'),'selectoptions3'=>array('','char'),'selectoptions4'=>array('','char')
);
$this->setConfigParameterable('custom_params',$varsToPush);
}
public function plgVmOnAddToCart(&$product){
echo "plgVmOnAddToCart fired";
die();
}
public function plgVmOnUserInvoice(){
echo "plgVmOnUserInvoice fired";
die();
}
}
?>
Ok I found the solution. The problem was the class name. In the joomla 1.5 documentation
http://docs.joomla.org/Creating_a_Plugin_for_Joomla_1.5
it mentions that the class name must follow this rule:
class plg extends JPlugin
But this is not mentiond in any joomla 2.5 documentation, since it is probably considered " an already known rule ".
So my solution was to change the class name from
class plgVmAftercheckout extends vmCustomPlugin {
to
class plgVmCustomAftercheckout extends vmCustomPlugin {
"Custom" because the plugin belongs to a specific group called Custom. So we need to mention the group name in order to make those hook methods observe the events.
Related
class Counter extends Component
{
public $counter = 0;
public $name;
public function mount($name)
{
$this->name = $name;
}
public function render()
{
return view('livewire.counter');
}
}
I'm trying to pass the name variable as parameter to the livewire component call like so #livewire('counter', ['name' => $name]) but receiving "Undefined variable $name" error. I have been following the livewire docs too, still same error. what could possibly be wrong? Thank you.
If $name is not defined, then it is not a property available in the blade file where you are including Livewire. Since we don't know anything about your blade file or controllers, I can't give you a direct answer. However, you should check if $name is set anywhere and if so, if it's available in your blade view. This error is not related to Livewire. If you've simply copied the docs without checking the variables, you might as well set it right away:
#livewire('counter', ['name' => 'Gilles'])
I have bundle in my symfony project and I want to change doctrine.orm.listeners.resolve_target_entity service in this bundle. I make it in compiler pass
symfony/symfony v3.2.3
doctrine/common v2.7.2
doctrine/dbal v2.5.12
doctrine/orm v2.5.6
doctrine/doctrine-bundle 1.6.7
namespace XXX\MyBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use XXX\MyBundle\DependencyInjection\Compiler\PreparePass;
class XXXMyBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new PreparePass());
}
}
namespace XXX\MyBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class PreparePass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->findDefinition('doctrine.orm.listeners.resolve_target_entity');
$definition->addMethodCall('addResolveTargetEntity', array(
'class1', 'class2', array(),
));
$definition->addTag('doctrine.event_subscriber', array());
}
}
Method call is added, tag is added, ./bin/console debug:container shows that everything is ok. But by fact service is not added to doctrine subscribers, there is no code for it in container dump in getDoctrine_Dbal_DefaultConnectionService function.
If I register my bundle before DoctrineBundle it works, if after it doesn't work :) I couldn't find where doctrine.event_subscriber tag is processed.
Is it possible to make it to work regardless of bundles registration order? And where doctrine.event_subscriber tag is processed?
Any help, thanks
How can I in Laravel 5 make global variable which will be available in all Blade templates?
Option 1:
You can use view::share() like so:
<?php namespace App\Http\Controllers;
use View;
//You can create a BaseController:
class BaseController extends Controller {
public $variable1 = "I am Data";
public function __construct() {
$variable2 = "I am Data 2";
View::share ( 'variable1', $this->variable1 );
View::share ( 'variable2', $variable2 );
View::share ( 'variable3', 'I am Data 3' );
View::share ( 'variable4', ['name'=>'Franky','address'=>'Mars'] );
}
}
class HomeController extends BaseController {
//if you have a constructor in other controllers you need call constructor of parent controller (i.e. BaseController) like so:
public function __construct(){
parent::__construct();
}
public function Index(){
//All variable will be available in views
return view('home');
}
}
Option 2:
Use a composer:
Create a composer file at app\Composers\HomeComposer.php
NB: create app\Composers if it does not exists
<?php namespace App\Composers;
class HomeComposer
{
public function compose($view)
{
//Add your variables
$view->with('variable1', 'I am Data')
->with('variable2', 'I am Data 2');
}
}
Then you can attached the composer to any view by doing this
<?php namespace App\Http\Controllers;
use View;
class HomeController extends Controller{
public function __construct(){
View::composers([
'App\Composers\HomeComposer' => ['home'] //attaches HomeComposer to home.blade.php
]);
}
public function Index(){
return view('home');
}
}
Option 3:
Add Composer to a Service Provider, In Laravel 5 I prefer having my composer in App\Providers\ViewServiceProvider
Create a composer file at app\Composers\HomeComposer.php
Add HomeComposer to App\Providers\ViewServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use View;
use App\Composers\HomeComposer;
use Illuminate\Support\Facades\Blade;
class ViewServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//add to all views
view()->composer('*', HomeComposer::class);
//add to only home view
//view()->composer('home', HomeComposer::class);
}
}
Create a new Service Provider as suggested in here
Add your new Service Provider to the configuration file (config/app.php).
In the boot method of your new Service Provider use:
View::share( 'something_cool', 'this is a cool shared variable' );
Now you are ready to use $something_cool in all of your views.
Hope this helps.
Searching for solution of the same problem and found the best solution in Laravel documentation. Just use View::share in AppServiceProvider like this:
View::share('key', 'value');
Details here.
You can do this with view composers. View composers are executed when a template is loaded. You can pass in a Closure with additional functionality for that view. With view composers you can use wildcards. To make a view composer for every view just use a *.
View::composer('*', function($view)
{
$view->with('variable','Test value');
});
You can also do this without a closure as you can see in the docs.
View::composer('*', 'App\Http\ViewComposers\ProfileComposer');
The profile composer class must have a compose method.
View composers are executed when a view is rendered. Laravel has also view creators. These are executed when a view is instantiated.
You can also choose to use a BaseController with a setupLayout method. Then every view which you will load is loaded through the setupLayout method which adds some additional data. However, by using view composers you're pretty sure that the code is executed. But with the BaseController approach you've more flexibility because you can skip the loading of the extra data.
EDIT: As mentioned by Nic Gutierrez you can also use view share.
Also, you can do this in the Route.php file:
view()->share('variableName', $variable);
I would rather use middleware with the view() facade helper. (Laravel 5.x)
Middleware is easier to mantain and does not make a mess in the controllers class tree.
Steps
Create the Middleware
/app/Http/Middleware/TimezoneReset.php
To create a middleware you can run php artisan make:middleware GlobalTimeConfig
share() the data you need shared
<?php
namespace App\Http\Middleware;
use Closure;
class GlobalTimeConfig
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$time_settings = [
'company_timezone' => 'UTC',
'company_date_format' => 'Y-m-d H:i:s',
'display_time' => true,
];
view()->share('time_settings', $time_settings);
return $next($request);
}
}
Register the newly created middleware
Add the middleware to your middleware route group as per example below
/app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\GlobalTimeConfig::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
Access data from templates
Access the data from any template with the given key in the View::share() method call
eg.:
Company timezone: {{ $time_settings['company_timezone'] }}
EDIT:
Nic Gutierrez's Service Provider answer might be a better (or the best) solution.
and you can give array not just View::share('key', 'value');
can put array like View::share(['key'=>'value','key'=>'value'])
You can add in Controller.php file:
use App\Category;
And then:
class Controller extends BaseController {
public function __construct() {
$categories = Category::All();
\View::share('categories', $categories);
}
}
you can flash it into the session, you can define it in the .env file (static vars)
There is a cookbook for adding globals to the twig templating engine, but it doesn't get into doing the same thing for the php engine. How would I do this?
So I might have something like:
# config.yml
someSortOfReferenceToThePHPEngineInstance:
calls:
- [ addGlobals, ["foo", "bar"] ]
- [ addGlobals, ["myService", "#myService"] ]
And then access those like:
// templateName.contentType.php
<?
echo $foo; // echos "bar"
echo $myService->myMethod($foo); // echos the result of modifying "bar" with "myMethod" method of "myService" service
I could not find any documention on this for the PHP engine...
What does work however is:
Config:
//config.yml
parameters:
hello: "YO!"
PHP Template:
// index.html.php
<?php
print $view->container->parameters['hello'];
This does not fit as nicely as the twig convention... Maybe there is better way - I have not debugged any further...
Here are a couple of options:
If you create a base controller that all others inherit from, you can override symfony's render function and add keys to the parameters argument, like:
public function render($view, array $parameters = array(), Response $response = null){
if(!array_key_exists("bar", $parameters){
$parameters["foo"] = $this->get("foo");
}
if(!array_key_exists("bar", $parameters){
$parameters["bar"] = $this->get("bar");
}
return parent::render($view, $parameters, $response);
}
This is the only way I see to modify the "global" variables "globally", though they'll not be available in any views rendered by controllers you don't create (of course, those'll likely be done in Twig anyway and you can use the normal twig means of adding functionality).
The PHP rendering engine has what're called "helpers", which you can access via array keys of $view, like:
$view["foo"]->doSomething();
We created a class for easily making services into helpers:
use Symfony\Component\Templating\Helper\Helper as BaseHelper;
class Helper extends BaseHelper{
protected $name;
public $service;
public function __construct($name, $service){
$this->name = $name;
$this->service = $service;
}
public function __get($name){
if(isset($this->service->$name)){
return $this->service->$name;
}
}
public function __call($name, $arguments){
if(method_exists($this->service, $name)){
return call_user_func_array(array($this->service,$name), $arguments);
}
}
public function getName(){
return $this->name;
}
}
Then in our configuration under the services we'd add:
helper.foo:
class: %helper.class%
arguments:
name: "foo"
helper: "#foo"
tags:
- { name: templating.helper, alias: foo }
This would theoretically be available then to any view files, even those with controllers you don't have control of.
I had a very same problem. For some reason this feature is only available for Twig templating with TwigBundle. Both Twig and PHP templating engines provide possibility to define global variables, but only Twig engine has configuration for that. For me the only real way to achieve that is something you proposed in the question post - to define method calls (and this is the way Twig globals are registered).
Problem is, that with DI extensions you can't access service definition from outside your extension, so you can't add these calls from your DI extension. The way for me was to do that with DI compiler pass.
But I'm also developer of ChillDevViewHelpersBundle and since I was facing this problem in most of my projects I decided to implement it there for common use and you can use 0.1.8 release for this feature.
I`m from Russia, so sorry for bad English.
I want to load template in every page in controller.
For example (library parser in autoload),
class Blog extends CI_Controller {
$header = array(
'header' => 'Welcome to my blog!'
);
$this->parser->parse('header', $header);
function index() {
...
echo "My text";
}
header.php:
<h1>{header}</h1>
<script>
alert("Welcome!");
</script>
But I get an PHP error:
syntax error, unexpected T_VARIABLE, expecting T_FUNCTION in line 6. Line 6:
$header = array(
How can I load header in every page? Thanks.
config.php:
$autoload['libraries'] = array('parser');
controller blog.php:
<?php
class Blog extends Controller {
function __construct()
{
parent::Controller();
$header = array('header' => 'Welcome to my blog!');
$this->parser->parse('header', $header);
}
function index()
{
echo "Мой текст";
}
}
?>
view header.php:
{header}
it works for me..
try calling the array with $this->header
Maybe it's a typing error but in the code from header.php you have typed {header} where I guess it should be {$header}
When loading class properties, like your $header above, php expects the property's visibility to be declared before the variable name. PHP5 has three visibility options: 'public', 'private', or 'protected'. I think this is why you are getting "unexpected T_VARIABLE". The difference between them are described at swik.net as:
To protect from accessibility pollution, PHP v5 introduces 3 prefixes for declaring class methods or variables: public, protected, and private.
Public methods and variables are accessible outside of the class. Protected are only accessible from inside of the class and inherited or parent classes. Private are only accessible from within the class itself.
try this: (I chose 'public' visibility, you can determine which is appropriate for your use)
public $header = array('header'=>'Welcome to my blog");
Next, I think you should call your parser in a constructor, rather than outside of a class method.
function _construct(){
parent::_construct();
$this->parser->parse('header',$this->header);
}
The constructor will be called every time the class is instantiated, loading your parser library method along with it.
Update:
Your comment suggests that the parser isn't working like you expect. I assume you have placed
$this->parser->parse('header,$this->header);
in the constructor function like I suggested. If that isn't working, create a function with the same name as your class and put the parser in there, that function will load every time the class is called, similar to the constructor, but let's see if that does the trick. I suggest taking the parser library out of auto load until you've resolved your problem, just to simplify things.
function blog(){
$this->load->library('parser');
$this->parser->parse('header',$this->header);
}