I want to replace (if that's not possible: remove) a class variable from outside the class.
The class is like this:
class Frontend {
protected function __construct() {
add_action( 'wp_head', array( $this, 'debug_marker' ), 2 );
}
public function debug_marker() {
$marker = sprintf(
'<!-- This is some advertisement HTML to advertise our product -->',
);
return $marker;
}
}
How can I replace $marker? If that's not possible, how can I remove it in any way?
The variable is inaccessible as long as it is private and inside the class, to use it would have to be public and still create the object, or you can create a method to be able to modify it.
<?php
class Frontend {
private $marker = '';
public function debug_marker() {
$marker = "<!-- This is some advertisement HTML to advertise our product -->";
}
Public function SetMarker($var){
$this->marker = $var;
}
Public function GetMarker(){
return $this->marker;
}
}
$front = new Frontend();
$front->SetMarker("Hello");
echo $front->GetMarker();
So you can modify your variable with this metod when you want, but only if you have the instance of the class
Related
I'm trying to modify the plugin function in the original PHP class named My_Widget_Admin which i have copied over from a plugin to my theme, but get Fatal error Too few arguments to function My_Widget_Admin
Here is the code i added in my theme :
class Custom_Admin extends My_Widget_Admin {
function item_select() {
// Code
}
}
$new = new Custom_Admin;
$new->item_select();
I think it has something to do with this code from the plugin :
private $_instance;
private $_widget_object;
function __construct( $instance, $widget_object ) {
$this->_instance = $instance;
$this->_widget_object = $widget_object;
$this->form();
}
I need to pass these 2 arguments $instance, $widget_object to the new function Custom_Admin.
How do i do that?
Passing arguments to a constructor must be done when the class gets instantiated. This is done with the new keyword.
class Custom_Admin extends My_Widget_Admin {
function item_select() {
// Code
}
}
$new = new Custom_Admin($instance, $widget_object);
$new->item_select();
Firstly:
On main.php I can use $this->tester1 to share the variable between functions, therefore do I need the public $tester1; at the top of my file - it seems to work fine without it?
Secondly:
I am attempting to get the variable set in main.php on other.php, if I remove $this->tester1 = 'test'; from the function and set public $tester1 to = 'test'; then echo $this->tester1; on either file will output fine.
However instead of 'test' I need the variable to be = get_option( 'my_option' ); which needs to be called after the __construct on the init action, and therefore needs to be within the function mymainfunction.
If I try to set the variable in that function and try to access it via other.php it says unexpected PUBLIC, if I remove public from the variable then the output is Undefined property: MyMainClass::$tester1
The output of the get_option is a line of text.
I think I am nearly there with this but missing something simple - hopefully! :)
Here are my files:
main.php
class MyMainClass {
public $tester1;
public function __construct() {
add_action( 'init', array( &$this, 'mymainfunction' ) );
}
public function mymainfunction() {
$this->tester1 = 'test';
echo $this->tester1;
}
}
other.php
class MyOtherClass {
public function __construct() {
add_action( 'init', array(&$this, 'myotherfunction' ) );
}
public function myotherfunction() {
require_once 'main.php';
$getvariables = new MyMainClass();
echo 'tester1 is:' . $getvariables->tester1;
}
}
Firstly:
If I'm not wrong, declaration without any explicit visibility keyword are defined as public.
Secondly:
You are including a class in the middle of a method of another one.. Seems quite strange to me.. "require_once" just insert the content of a file, where the instruction is called. So my guess is that it's mess up with PHP syntax. In order to try to help you, would you try to replace your "other.php" by something like :
require_once 'main.php';
class MyOtherClass {
public function __construct() {
add_action( 'init', array(&$this, 'myotherfunction' ) );
}
public function myotherfunction() {
$getvariables = new MyMainClass();
echo 'tester1 is:' . $getvariables->tester1;
}
}
But to be honest, I don't know what you are trying to do, but something like this would be simplier, right ?
main.php
class MyMainClass {
public $tester1;
public function __construct() {
$this->tester1 = 'test1';
}
}
other.php
require_once 'main.php';
class MyOtherClass {
public function __construct() {
$main = new MyMainClass();
echo 'tester1 is:' . $main->tester1;
}
}
I'm writing a class - called MenuBuilder - in PHP 7 which is intended to build navigation menus in a web application.
The way in which the class works is by building up an output buffer which holds the markup for the menus.
It starts off by declaring an empty variable inside class MenuBuilder:
private $output_buffer = '';
There is a method to add to it:
protected function add_to_output_buffer($input = '') {
if ($input !== '') {
$this->output_buffer .= $input;
}
}
And a method to display the menu markup:
public function render() {
echo $this->output_buffer;
}
So far quite straightforward. Here's the problem... When I add a link to the menu I use this method:
public function add_menu_item($item) {
$this->menu_items[] = $item;
}
This builds up an array ($this->menu_items) and there is then another method which cycles through the items in it to add them to the output buffer. It's quite long but a shortened version of it is here:
public function create_links() {
foreach ($this->menu_items as $item) {
$output = '';
$output = ''.$item['text'].'';
$this->add_to_output_buffer($output);
}
}
There is quite a lot of logic in create_links() because various classes and other things get applied to the links, but essentially it has to work like this because it needs to loop through the full array of links.
The problem:
If I want to add random HTML at any point in the menu, I have a function to do this:
public function add_misc_html($html = '') {
$this->output_buffer .= $html;
}
But in my script which uses these functions, it doesn't know the order in which things are being called. An example:
$MenuBuilder = new MenuBuilder;
$MenuBuilder->add_menu_item(['text' => 'Link 1', 'link' => '#']);
$MenuBuilder->add_menu_item(['text' => 'Link 2', 'link' => '#']);
$MenuBuilder->add_misc_html('<h1>testing add_misc_html</h1>');
$MenuBuilder->add_menu_item(['text' => 'Link 3', 'link' => '#']);
$MenuBuilder->create_links();
$MenuBuilder->render();
So the problem is that the desired output is:
Link 1
Link 2
<h1>testing add_misc_html</h1>
Link 3
But this won't work, because when I call create_links() it's not aware of add_misc_html and where this is called in the overall structure of the calls to MenuBuilder
What ways can I achieve the desired output? Please note that add_misc_html() needs to work anywhere it gets called, prior to render(). There is a whole load of other stuff in the class to open the menu and close it, so it needs to be able to modify the $this->output_buffer at any point.
This is because your add_misc_html writes directly to your output buffer, where add_menu_item modifies the structure of your object, you can't mix these calls. You must first write your modified object state to the buffer and only then write "misc" HTML to the buffer. This is pretty bad though.
There are many solutions you can come up with but the one I will suggest to you is to not have an output buffer at all, and possibly extend the logic of the class with a couple other classes.
class MenuBuilder {
protected $items = [];
public function add(MenuItem $item) {
$this->items[] = $item;
}
public function render() {
return join('', $this->items);
}
}
Where you will have different types of menu items, like Link and Misc that are used in your example.
interface MenuItem {
public function __toString();
}
class LinkMenuItem implements MenuItem {
protected $link;
protected $text;
public function __construct($link, $text) {
$this->link = $link;
$this->text = $text;
}
public function __toString() {
return ''. $this->text .'';
}
}
class MiscMenuItem implements MenuItem {
protected $html;
public function __construct($html) {
$this->html = $html;
}
public function __toString() {
return $this->html;
}
}
And now your class will be used like this.
$builder = new MenuBuilder();
$builder->add(new LinkMenuItem('#', 'Link 1'));
$builder->add(new LinkMenuItem('#', 'Link 2'));
$builder->add(new MiscMenuItem('<h1>Testing html</h1>');
$builder->add(new LinkMenuItem('#', 'Link 3'));
And when you want to render.
$builder->render();
Edit
Based on the discussion in the comments I am coming to think that you are having trouble rendering the objects as HTML hierarchically. Again there are a number of ways you can go about this, I am just proposing one
You can add a base class that your other menu items will extend
abstract class ParentMenuItem extends MenuItem {
protected $children = [];
public function addChild(MenuItem $child) {
$this->children[] = $child;
}
public function __toString() {
return '<ul>' . join(null, $this->children) . '</ul>';
}
}
Then your LinkMenuItem will look like this
class LinkMenuItem extends ParentMenuItem {
protected $link;
protected $text;
public function __construct($link, $text) {
$this->link = $link;
$this->text = $text;
}
public function __toString() {
return ''. $this->text .'' . parent::__toString();
}
}
When you want to add children you will add them to the menu item they belong to (duh?)
$builder = new MenuBuilder();
$link1 = new LinkMenuItem('#', 'Link 1');
$link1->addChild(new LinkMenuItem('#', 'Child1'));
$link1->addChild(new LinkMenuItem('#', 'Child2'));
$builder->add($link1);
$builder->add(new LinkMenuItem('#', 'Link 2'));
$builder->add(new MiscMenuItem('<h1>Testing html</h1>'));
$builder->add(new LinkMenuItem('#', 'Link 3'));
You can also enable chaining to avoid using variables and all kinds of other good stuff like factories etc.
I have the following code, perform a global function within a class to fill the functions of wordpress, the problem is that the only way that I could get a variable public class is as follows
class Core {
public $notice;
function __construct(){
$this->core_function();
}
function core_function(){
global $globalvar;
$globalvar = $this;
function notice_global(){
global $globalvar;
return $globalvar->notice;
}
}
function set_notice(){
$this->notice = array('Warning');
}
}
$GP = new Core();
$GP->set_notice();
var_dump(notice_global());
Any other ideas or suggestions, this code is correct or not?
As you said in the comments, you need global function due to wordpress hook method (for a plugin, I suppose).
This is not necessary: there is a way to pass an object method (not a whole object) to wordpress.
You can try in this way:
class Core {
public $notice;
function get_notice()
{ return $this->notice; }
function set_notice()
{ $this->notice = array('Warning'); }
}
$GP = new Core();
$GP->set_notice();
add_action( 'save_post', array( $GP, 'get_notice' ) );
Or - for a better flexibility - in this way:
class Core {
public $notice;
function get_notice()
{ return $this->notice; }
function set_notice()
{ $this->notice = array('Warning'); }
function add_wp_action( $hook, $method )
{ add_action( $hook, array( $this, $method ) ); }
}
$GP = new Core();
$GP->set_notice();
$GP->add_wp_action( 'save_post', 'get_notice' );
By this way, you can directly set all your wp hooks in the class and call they directly with an object method, without using globals variables or function tricks.
I'm not sure if I'm understanding you right, but notice_global can be moved out of that class.
Globals have scope outside of classes
There is no need for these functions. You've defined $notice as public property. You can access it like this: $GP->notice;
You might also want to read documentation on visibility of methods and properties.
I have a simple question regarding PHP Classes.
Multiple times I have seen other class-frameworks etc use method calls like.
$post->data->text();
I like this functionality, rather than just doing something like this.
$post->dataReturnAsText();
But i'm not quite sure how they created this functionality to have perhaps a 'sub-method'? Hope someone can point me in the right direction....
The example you provide has nothing special:
<?php
class Post{
public $data;
}
class Data{
public function text(){
}
}
$post = new Post;
$post->data = new Data;
$post->data->text();
However, you've probably found it in the context of method chaining (very popular in JavaScript libraries):
<?php
class Foo{
public function doThis(){
return $this;
}
public function doThat(){
return $this;
}
}
$foo = new Foo;
$foo->doThis()->doThat()->doThis();
In this case, data is simply a attribute of the class, and it contains another object:
class data
{
public function text()
{
}
}
class thing
{
public $data;
}
$thing = new thing();
$thing->data = new data();
$thing->data->text();
its probably a just that the "data" is a a public property of $post containing an object wth a text property for example :
class Textable {
public $text;
function __construct($intext) {
$this->text = $intext;
}
}
class Post {
public $data;
function __construct() {
$data = new Textable("jabberwocky");
}
}
this will allow you to do :
$post = new Post();
echo( $post->data->text ); // print out "jabberwocky"
of course the right OOP way is to make the property private and allow access useing a getter function but that besides the point...