Integrate HTML-Code from other classes to own WP plugin - php

I want to write a new Plugin in wordpress. My classes:
the plugin PHP-file:
<?php
/*
plugin-header (working)
*/
// Exit if accessed directly
defined('ABSPATH' || exit());
// Include classes
include('foo.php');
include('boo.php');
//add Init Hook
add_action('admin_menu','bohoo_admin');
function bohoo_admin() {
add_options_page('bohoo', 'someTitle', 'manage_options', __FILE__, 'createView');
}
function createView() {
$foo = new foo();
$boo = new boo();
return $foo->createFooDiv() . $boo->createBooDiv();
}
?>
My foo.php:
<?php
class foo {
public function __construct() {
}
public function createFooDiv() {
return '<div><h2>Hi</h2></div>';
}
}
?>
My boo.php:
<?php
class boo {
public function __construct() {
}
public function createBooDiv() {
return '<div> test </div>';
}
}
?>
Now what I basically tried is: The HTML-code should be in two different files and these should be concatenated and displayed (of course).
The way I understood integrating plugins in WP:
With the add_options_page-method you specify where your plugin is shown and what code is displayed. For the code you use the last argument (in this case the createView-method. This works so far if my createView() in my plugin PHP-file looks like this:
function createView() {
//include HTML-Code directly
?>
<h1>Hello World</h1>
<?php
}
?>
What happens when I include the boo.php and foo.php files instead of including the HTML-Code directly is nothing (So nothing is displayed and there is on error aswell). I am not sure what I am doing wrong, I also tried playing around with the HTML-Code in the return-statements of BOO and FOO, but that did not help either. What am I doing wrong? Or is it simply not possible to do it that way?

You need to print/echo your html content. Change createView to this:
function createView() {
$foo = new foo();
$boo = new boo();
echo $foo->createFooDiv() . $boo->createBooDiv();
}
That's how it's done in the add_options docs page.
And basically when you use php closing and opening tags:
?>
<h1>Some html</h1>
<?php
It's equivalent to printing the content in between:
echo '<h1>Some html</h1>';

Related

PHP - Can't access properties declared in another method when calling methods using AJAX

I apologise if this question is a bit long winded, but it's quite a large chunk of code and I cannot get it to work for the life of me...
I am building a form inside a Wordpress plugin that should gather some data (either through form inputs, API, or a combination of both - such as calling different API endpoints depending on form values). I want to then use these variables (or properties, as they seem to be referred to within classes) in different methods.
Firstly, I have my class and then a method to register my plugin on the Wordpress menu bar:
class EnigmaDMU {
private $enigma_dmu_screen_name;
private static $instance;
static function GetInstance()
{
if (!isset(self::$instance))
{
self::$instance = new self();
}
return self::$instance;
}
// This loads the WP menu page and plugin page
public function PluginMenu() {
$this->enigma_dmu_screen_name = add_menu_page(
'Enigma DMU Post',
'Enigma DMU Post',
'manage_options',
__FILE__,
array($this, 'RenderPage'),
plugins_url('enigma-daily-update/assets/enigma-cube-white.svg',__DIR__)
);
}
I then have another method called 'RenderPage' which contains my form and the HTML elements for my plugin page inside the WP admin:
public function RenderPage(){
?>
<div class='wrap'>
<div class="header-bar">
<h1>Daily Market Update</h1>
....... continued here
At the very bottom of my code, I have a method to initiate the plugin which adds the AJAX handlers (my methods) for certain AJAX actions which are called in my AJAX requests:
public function InitPlugin() {
add_action('admin_menu', array($this, 'PluginMenu'));
add_action('admin_enqueue_scripts', array($this, 'dmu_load_scripts'));
add_action('admin_enqueue_styles', array($this, 'dmu_load_scripts'));
add_action('wp_ajax_btc_data', array($this, 'getBTCData'));
add_action('wp_ajax_test_func', array($this, 'testFunc'));
}
} //this is the closing tag for the Class.
Underneath this, I have some class-related definitions, which admittedly I am unsure what they do - this was part of a larger tutorial I followed to set up this plugin:
$EnigmaDMUpost = EnigmaDMU::GetInstance();
$EnigmaDMUpost->InitPlugin();
?>
Almost there... I also have my handlers (I have included a test handler to simplify this explanation):
public function getBTCData() {
require __DIR__."/vendor/autoload.php";
$client = new GuzzleHttp\Client();
$btc_curl = $client->get('https://api.alternative.me/v1/ticker/bitcoin/',);
$btc_curl_body = $btc_curl->getBody();
$btc_curl_body_json = json_decode($btc_curl_body);
foreach($btc_curl_body_json as $result){
$btc_price_ur = $result->price_usd;
$btc_change_ur = $result->percent_change_24h;
}
$btc_price = round($btc_price_ur, 2);
$btc_change = round($btc_change_ur, 2);
$this->row3b = $btc_change . '%';
echo 'inside: ' . $this->row3b;
die();
}
I am able to echo this value here (row3b) inside my plugin successfully - this works as expected.
However, when I try and call the property from my testFunc, I get nothing:
public function testFunc() {
$test_item = $this->row3b;
echo 'btc dominance = ' . $test_item . '%.';
}
Finally, the relevant areas of my AJAX script are as follows:
jQuery(document).ready(function($) {
$('#dmu_submit').click(function() {
$('#dmu-loader').show();
$('#dmu_submit').attr('disabled', true);
btc_data = {
action: 'btc_data',
dmu_nonce: dmu_vars.dmu_nonce
};
$.post(ajaxurl, btc_data, function(response) {
$('#dmu-results').html(response);
$('#dmu-loader').hide();
$('#dmu_submit').attr('disabled', false);
});
$('#dmu_test_func').click(function() {
$('#dmu-loader').show();
$('#dmu_submit').attr('disabled', true);
test_data = {
action: 'test_func',
dmu_nonce: dmu_vars.dmu_nonce
};
$.post(ajaxurl, test_data, function(response) {
$('#dmu-results-test').html(response);
$('#dmu-loader').hide();
$('#dmu_submit').attr('disabled', false);
});
return false;
});
Any help would be massively appreciated - I know it's a long post, but I feel as if the answer is actually really simple, I just cannot figure it out. It feels as if I'm doing everything right. Thank you!!
It's not completely clear from your code examples which class your testfunc() is in. But $this in php refers to the instance of the class that it resides within, and the ->row3b refers to a property called row3b (a property is a variable that belongs to the class which is usually defined at the top of the class code). If you're calling $this->row3b within the class itself it will work, but if you need to refer to it from outside the class you will need to instantiate a new instance of the class, and then refer to it with the variable name you assign. E.g.
$myInstance = new theclassname(); $myInstance->row3b;
If the row3b is a static property its slightly different again, you can refer to this outside of the class as theclassname::$row3b
Edit: also ensure that the testfunc resides in the same class that the add_actions are in. The $this in the add_action tells wordpress that it should look for your handler in 'this' class.
Edit2: I think you may also need the die() at the end of your testfunc. Wordpress ajax is funny about this.

PHP - Call class function from another class

I am developing an app where I need to log the proccess.
So I was loggin from main.php and now I need to log from another class (class_TestingLog.php)
Next code is how I am trying. Could you tell me what I am doing wrong?
Thank you in advance.
main.php
[...]
#Logging class
include_once("./classes/class_log.php");
$Class_Log = New Class_Log();
#TestingLog Class
include_once("./classes/class_testingLog.php");
$Class_TestingLog = New Class_TestingLog();
[...]
$Class_Log->FreeLog("Test log");
$Class_TestingLog->AnyFuncion();`
[...]
class_log.php
[...]
public function FreeLog($text)
{
// echo $text . "\n"; #mistake
$this->outputText .= text; #correct one
}
[...]
class_testingLog.php
private $Class_Log = '';
[...]
public function __construct()
{
#Requires
require_once("./classes/class_log.php");
$this->Class_Log = New Class_Log();
}
public function AnyFuncion()
{
var_dump($this); #From real file
$this->Class_Log->FreeLog("Test log from another classs");
}
[...]
Browser output
Test log
Browser output expected
Test log
Test log from another classs
===========================================================================
EDIT
I made an error copying FreeLog();
It stores the parameter string value into a private variable instead echo the variable.
You require_once statement inside __construct for Class_TestingLog is invalid and unnecessary. As both files are in the same directory it should be "class_log.php" not "./classes/class_log.php". There is no need for it anyway, as when you include them both in main.php it is loaded already. So try it without the require_once.
EDIT: As discussed in chat do it like this:
in main.php:
$Class_TestingLog = New Class_TestingLog($Class_Log);
in class_testingLog.php:
public function __construct($ClassLog)
{
$this->Class_Log = $ClassLog;
}
This will use the same instance inside the Class_TestingLog class as on the main.php.

unrequire a php file

Im working on a website - just learning to improve my coding.
I have a routing system which works like this:
/config/routes.php:
$route->add('/' , function() {
require_once("/application/pages/index.php");
});
$route->add('/register', function() {
require_once("/application/pages/register.php");
});
$route->add('/login', function() {
require_once("/application/pages/login.php");
});
$route->add('/logout', function() {
require_once("/application/pages/logout.php");
});
$route->add('/panel', function() {
require_once('/application/pages/panel/index.php');
});
And in my index.php:
require_once('application/pages/header.php');
include('config/routes.php');
require_once('application/pages/footer.php');
Everything works fine but I need a different header.php and footer.php for when the user goes into the panel. file: /application/pages/panel/index.php
When I require_once a new header file in the panel/index.php then both the new and old header file is loaded. How can I unrequire the header and footer files in the /panel/index.php so I can require different ones? Any suggestions?
Note: Routing comes from an MVC design pattern, you should keep your controllers separate from your views.
Templates and Views could be kept separate, also. This meaning our directory set-up can look something like this:
- Templates
- header_one.php
- footer_one.php
- header_two.php
- footer_two.php
- Views
- index.php
- someOtherBody.php
Here is a simple, but unfinished (that is your challenge) example of an Object that could do what I am explaining:
class Page {
private $template_path = dirname(dirname(__FILE__)) . '/templates/';
private $view_path = dirname(dirname(__FILE__)) . '/views/';
protected $header;
protected $footer;
protected $body;
public function setHeader($file_name)
{
if(is_readable($this->template_path . $file_name))
{
$this->header = $this->template_path . $file_name;
return $this;
}
// add an exception
}
/* TODO: */
public function setFooter() {}
public function setBody() {}
/* Render page */
public function render()
{
$page = [$this->header,$this->body,$this->footer];
foreach($page as $file)
{
require_once($file);
}
}
}
The idea here is that we can set our page layout, using the above object, within the route method closure, then render / require all the files after the logic.
$route->add('/', function() {
$page = new Page();
$page->setHeader('header_one.php')
->setBody('index.php')
->setFooter('footer_one.php');
/* todo: add your logic here */
$page->render();
});
Each route can now have its own header, footer and body.
Hope this helped.
At your place, I will do something like that :
Use out buffer and check if the file is already required. I give you an quick example but adapt the code for you.
And check the function : http://php.net/manual/en/function.get-included-files.php
$route->add('/panel', function() {
include_once('YOUR_SPECIFIC_PATH/header.php');
require_once('/application/pages/panel/index.php');
include_once('YOUR_SPECIFIC_PATH_header/footer.php');
});
And :
ob_start();
include_once('config/routes.php');
$mainContent = ob_get_contents();
ob_end_clean();
include_once('application/pages/header.php');
echo $mainContent;
include_once('application/pages/footer.php');
I've not the time for help more sorry but I can explain later if you need
This solution requires you to have a header.php and footer.php in each folder where your sub-controllers (application/<module name>/index.php) are.
index.php only call your sub-controllers via routing:
// require not include, because "no routing" = "no web site" ;)
require_once('config/routes.php');
application/pages/index.php include appropriate header/footer w/ relative path
require_once('header.php');
// page code
require_once('footer.php');
application/register/index.php include appropriate header/footer w/ relative path
require_once('header.php');
// page code
require_once('footer.php');
etc
#KDOT , thanks you for your help but using your code I was getting an error that I could not fix:
Call to a member function setBody() on null
but thanks to your code, I managed to rewrite the class my way and now it works ;)
Thanks again #KDOT !
If anyone needs it:
class Page {
private $TEMPLATE_PATH = '/application/templates/';
private $VIEW_PATH = '/application/views/';
protected $header;
protected $footer;
protected $body;
public function __construct($header_file, $body_file, $footer_file) {
$this->header = $this->TEMPLATE_PATH . $header_file;
$this->body = $this->VIEW_PATH . $body_file;
$this->footer = $this->TEMPLATE_PATH . $footer_file;
}
public function render(){
$page = [$this->header, $this->body, $this->footer];
foreach($page as $file) {
require_once($file);
}
}
}
and:
$route->add('/', function() {
$page = new Page('header.php', 'home.php', 'footer.php');
$page->render();
});

PHP Variable to Handle Web Properties

i look around the web for a example of manager PHP Variable think on properties of the web application .
the main problem is that i don't like to write igual that this code:
Link
I would like to include a file .php With class; up with the list of variables, something like this:
$MSGdisplay = '';
$MSGemail = '';
$MSGnotification = '';
and use them anywhere in the script with a simple call:
$G['MSGdisplay'] = 'This is an example of code'; //more short that $_GLOBALS array
without losing the ability to assign new values.
Example:
file index.php
<?php
require_once("main.php");
global $G;
$G['test'] = 'Text Test';
$WebAPP = new Class_MAIN();
$WebAPP -> Main();
?>
file Main.php
<?php
class Class_MAIN{
function Main(){
echo $G['test'];
}
}
?>
Notice: Undefined variable: G in main.php on line 4
Remove global $G; from index.php and move it inside of the Main function in Main.php
<?php
class Class_MAIN{
function Main(){
global $G;
echo $G['test'];
}
}
?>
can solve create a file vars.php with content variable:
<?php
$G['test'] = 'text test';
?>
an create a callback file varscall.php with content variable call glabal
<?php
global $G;
?>
Use Require instance file in Index on top:
<?php
require("vars.php");
require_once("main.php");
$WebAPP = new Class_MAIN();
$WebAPP -> Main();
?>
Use CallBack Vars File igual and use variable inside the function you need:
<?php
class Class_MAIN{
function Main(){
require("varscall.php");
echo $G['test'];
}
function Other(){
require("varscall.php");
echo $G['test'];
}
}
?>
The main problem is that you need repeat per funcion the require of the file call: require("varscall.php"); and need create this as object... is not eficient

setFetchMode to type Class using namespaces in PHP

I'm trying to populate some variables in a PHP class by using setFetchMode and FETCH_CLASS.
<?php # index.php
use myproject\user\User;
use myproject\page\Page;
$q = 'SELECT * FROM t';
$r = $pdo->query($q);
// Set the fetch mode:
$r->setFetchMode(PDO::FETCH_CLASS, 'Page');
// Records will be fetched in the view:
include('views/index.html');
?>
In my view file, I have:
<?php # index.html
// Fetch the results and display them:
while ($page = $r->fetch()) {
echo "<article>
<h1><span>{$page->getDateAdded()}</span>{$page->getTitle()}</h1>
<p>{$page->getIntro()}</p>
<p>read more here...</p>
</article>
";
}
?>
These methods are from Class: Page.php:
<?php # Page.php
function getCreatorId() {
return $this->creatorId;
}
function getTitle() {
return $this->title;
}
function getContent() {
return $this->content;
}
function getDateAdded() {
return $this->dateAdded;
}
?>
It's pretty straightforward when using standard classes, that is, I've had it all working fine; name-spaces seem problematic however.
For example if I use:
<?php # index.php
require('Page.php'); // Page class
$r->setFetchMode(PDO::FETCH_CLASS, 'Page'); // works
?>
But when using namespaces,
<?php # index.php
use myproject\page\Page;
?>
// Set the fetch mode:
$r->setFetchMode(PDO::FETCH_CLASS, 'Page'); // problem
// Records will be fetched in the view:
include('views/index.html');
?>
Browse to index.php and the browser reports:
Fatal error: Call to a member function getDateAdded() on a non-object in /var/www/PHP/firstEclipse/views/index.html on line 5
My namespace paths are all set-up correctly, as I've successfully instantiated objects using the above naming conventions, for example:
<?php # index.php
use myproject\page\User; # class: /myproject/page/user/User.php
$b = new User();
print $b->foo(); // hello
?>
If you are using PHP earlier than 5.5
You need to provide the fully qualified name of the class:
use myproject\page\Page;
$r->setFetchMode(PDO::FETCH_CLASS, 'myproject\page\Page');
It's unfortunate that you have to repeat yourself like this (this code would break if you decided to switch to a different class Page from another namespace), but there is no way around the ugliness.
If you are using PHP 5.5
You are in luck! The new ::class keyword was designed to help with exactly this problem:
// PHP 5.5+ code!
use myproject\page\Page;
// Page::class evaluates to the fully qualified name of the class
// because PHP is providing a helping hand
$r->setFetchMode(PDO::FETCH_CLASS, Page::class);

Categories