Using a custom class in a Wordpress theme - php

I have a PHP class with methods that I would like to use anywhere I choose on my theme.For instance this class:
<?php
class MyClass
{
const constant = 'constant value';
function showConstant() {
echo self::constant . "\n";
}
}
$class = new MyClass();
$class->showConstant();
?>
How would I include such a class in my theme?

You have a couple of ways to go about this; you can write a plugin, which might be a bit overkill, but you can also:
1
In your functions.php-file, just add your functions there, and then you can call them in your theme
function myClassFunction() {
class MyClass {
const constant = 'constant value';
function showConstant() {
echo self::constant . "\n";
}
}
$class = new MyClass();
$class->showConstant();
}
2
Create a new directory in your themes folder, something like /includes. Put your class in there. Then wherever in your theme where you need your class and it's functions, just include it in your template:
<?php
require_once('includes/MyClass.php');
$class = new MyClass();
$class->showConstant();
?>
It all depends on what kind of class it is, what it does and how often you use it. There are a whole lot of ways to do it.

Related

Get class namespace and name from class reference, without changing my classes

In php you often check if the object you get is of the correct type. If not you throw an exception with a message like this:
use My\Class\MyClass
...
if (!$object instanceof MyClass) {
throw new Exception(
sprintf(
"object must be of type '%s'",
'My\Class\MyClass'
)
);
}
Right now I pass the full namespace and the name of the class in a string to sprintf.
How can I get this from the class reference so that i can do something like this
sprintf("object must be of type '%s'", MyClass::getName())
EDIT:
I would like to achieve this for all classes without adding new methods. So it should be a solution using some existing method or one of the php __ MAGIC__ methods.
As of php 5.5 there's a magic constant that gives you the FQCN of any class. You can use it like this:
namespace My\Long\Namespace\Foo\Bar;
MyClass::class;
// will return "My\Long\Namespace\Foo\Bar\MyClass"
It's documented on the new features page.
namespace test;
class a {
public function getname()
{
return __CLASS__;
}
}
And:
$a = new a();
echo $a->getname(); //
Outputs
test\a
Static method works same way:
public static function getname()
{
return __CLASS__;
}
...
a::getname(); // test\a
You can also get only namespace with __NAMESPACE__
Update:
you can you ReflectionClass for same thing:
$a = new a();
$r = new \ReflectionClass($a);
echo $r->getName(); // test\a
you can create ClassHelper class to have it for using anywhere you need it easily:
class ClassHelper
{
public static function getFullQualifiedName($object)
{
$rc = new \ReflectionClass($object);
return $rc->getName();
}
}
And use it:
echo ClassHelper::getFullQualifiedName($a); // test\a
Finnaly: if you use php 5.6 and above (for future), you can work with class constant
echo a::class; // test\a

define class globally in withut require include

I want to define a class globally, so if I create a page this , it works
<?php
$cl = new MyOwnClass();
?>
How can I do that ?
You shoulod look into Autoloading Classes: http://www.php.net/manual/en/language.oop5.autoload.php
class classname
{
public function publicfuntioname($testvar) {
$this->testvar = $testvar;
}
}
Now include this file any where
$obj= new classname();
$obj->publicfuntioname("another value");

Lazy load class in PHP

I want to lazy load class but with no success
<?php
class Employee{
function __autoload($class){
require_once($class);
}
function display(){
$obj = new employeeModel();
$obj->printSomthing();
}
}
Now when I make this
function display(){
require_once('emplpyeeModel.php');
$obj = new employeeModel();
$obj->printSomthing();
}
It works but I want to lazy load the class.
__autoload is a standalone function not a method of a class. Your code should look like this:
<?php
class Employee{
function display(){
$obj = new employeeModel();
$obj->printSomthing();
}
}
function __autoload($class) {
require_once($class.'.php');
}
function display(){
$obj = new Employee();
$obj->printSomthing();
}
UPDATE
Example taken from the php manual:
<?php
function __autoload($class_name) {
include $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
Change Employee a bit:
class Employee {
public static function __autoload($class) {
//_once is not needed because this is only called once per class anyway,
//unless it fails.
require $class;
}
/* Other methods Omitted */
}
spl_autoload_register('Employee::__autoload');
First if all it's better to use spl_autoload_register() (check the note in php's manual for autoloading).
Then back to your problem; only if the display() function is in the same directory as the employeeModel this will work. Otherwise, use absolute paths (see also include() and include_path setting

Forget late static binding, I need late static __FILE__

I'm looking for the get_called_class() equivalent for __FILE__ ... Maybe something like get_included_file()?
I have a set of classes which would like to know what directory they exist in. Something like this:
<?php
class A {
protected $baseDir;
public function __construct() {
$this->baseDir = dirname(__FILE__);
}
public function getBaseDir() {
return $this->baseDir;
}
}
?>
And in some other file, in some other folder...
<?php
class B extends A {
// ...
}
class C extends B {
// ...
}
$a = new A;
echo $a->getBaseDir();
$b = new B;
echo $b->getBaseDir();
$c = new C;
echo $c->getBaseDir();
// Annnd... all three return the same base directory.
?>
Now, I could do something ghetto, like adding $this->baseDir = dirname(__FILE__) to each and every extending class, but that seems a bit... ghetto. After all, we're talking about PHP 5.3, right? Isn't this supposed to be the future?
Is there another way to get the path to the file where a class was declared?
ReflectionClass::getFileName
Have you tried assigning it as a static member of the class?
<?php
class Blah extends A {
protected static $filename = __FILE__;
}
(Untested, and statics plus class inheritance becomes very fun...)
what if you don't use __FILE__ but a separate variable and set the variable to __FILE__ in each class
class A {
protected static $baseDir;
protected $filename = __FILE__; // put this in every file
public function __construct() {
}
public function getBaseDir() {
return dirname($this->filename) . '<br>'; // use $filename instead of __FILE__
}
}
require('bdir/b.php');
require('cdir/c.php');
class B extends A {
protected $filename = __FILE__; // put this in every file
}
$a = new A;
echo $a->getBaseDir();
$b = new B;
echo $b->getBaseDir();
$c = new C;
echo $c->getBaseDir();
you still have to redeclare the property in each class, but not the method
You could use debug_backtrace(). You probably don't want to, though.
Tested:
protected static $filename = __FILE__;
static::$filename
Doesn't work.
It looks like the constant is registered when the class is loaded which is not "late".
Not sure it was possible before, but what was best for me today is using reflection :
$basePath = new \ReflectionObject($this);
$dir = dirname($basePath->getFileName());

How can I call a static method on a variable class?

I'm trying to make some kind of function that loads and instantiates a class from a given variable. Something like this:
<?php
function loadClass($class) {
$sClassPath = SYSPATH."/classes/{$class}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$class = $class::getInstance();
}
}
?>
If I use it like this:
<?php
loadClass('session');
?>
It should include and instantiate the session class.
BTW: the static getInstance function comes from this code:
<?php
function getCallingClass() {
$backtrace = debug_backtrace();
$method = $backtrace[1]['function'];
$file = file($backtrace[1]['file']);
$line = $file[($backtrace[1]['line'] - 1)];
$class = trim(preg_replace("/^.+?([A-Za-z0-9_]*)::{$method}\(.*$/s", "\\1\\2", $line));
if(! class_exists($class)) {
return false;
} return $class;
}
class Core {
protected static $instances = array();
public static function getInstance() {
$class = getCallingClass();
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new $class();
} return self::$instances[$class];
}
}
?>
The thing is that right now the way to use the functions in a class is this:
<?php
$session = session::getInstance();
?>
But now I want to build that into a function so that I never again have to use that line of code.
I just say loadClass('session');
and than I can use $session->blablablafunction();
Calling static functions on a variable class name is apparently available in PHP 5.3:
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
http://php.net/manual/en/language.oop5.static.php
Could definitely use that right now myself.
Until then you can't really assume that every class you are loading is designed to be a singleton. So long as you are using < 5.3 you'll have to just load the class and instantiate via the constructor:
function loadClass($class) {
$sClassPath = SYSPATH."/classes/{$class}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$class = new $class;
}
}
OR
Just load the class without creating an object from it. Then call "::getInstance()" on those meant to be singletons, and "new" on those that are not, from outside of the loadClass() function.
Although, as others have pointed out earlier, an __autoload() would probably work well for you.
You can use call_user_func():
$class = call_user_func(array($class, 'getInstance'));
The first argument is a callback type containing the classname and method name in this case.
Why not use __autoload() function?
http://www.php.net/autoload
then you just instantiate object when needed.
It looks like you are fighting PHP's current implementation static binding, which is why you are jumping through hoops with getCallingClass. I can tell you from experience, you should probably abandon trying to put instantiation in a parent class through a static method. It will cause you more problems in the end. PHP 5.3 will implement "late static binding" and should solve your problem, but that obviously doesn't help now.
You are probably better off using the autoload functionality mentioned by kodisha combined with a solid Singleton implementation. I'm not sure if your goal is syntactic sugar or not, but it think you will do better in the long run to steer clear of trying to save a few characters.
Off the top of my head, needs testing, validation etc:
<?php
function loadClass($className) {
if (is_object($GLOBALS[$className]))
return;
$sClassPath = SYSPATH."/classes/{$className}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$reflect = new ReflectionClass($className);
$classObj = $reflect->newInstanceArgs();
$GLOBALS[$className] = $classObj;
}
}
?>
Late static bindings will work for you I think. In the construct of each class do:
class ClassName
{
public static $instances = array();
public function __construct()
{
self::$instances[] = $this;
}
}
Then...
Here is an autoloader I created. See if this solves your dilemma.
// Shorten constants for convenience
define ('DS', DIRECTORY_SEPARATOR);
define ('PS', PATH_SEPARATOR);
$template = "default";
// Define an application path constants
define ('APP_ROOT', realpath('.').DS);
define ('VIEW', APP_ROOT . 'Views' . DS);
define ('MODEL', APP_ROOT . 'Models' . DS);
define ('CONTROLLER', APP_ROOT . 'Controllers' . DS);
define ('TEMPLATE', VIEW."templates".DS.$template.DS);
define ('CONTENT', VIEW."content".DS);
define ('HELPERS', MODEL."helpers".DS);
// Check if application is in development stage and set error reporting and
// logging accordingly
error_reporting(E_ALL);
if (defined('DEVELOPMENT')) {
ini_set('display_errors', 1);
} else {
ini_set('display_errors', 0);
ini_set('log_errors', 'On');
ini_set('error_log', APP_ROOT.'error.log');
}
$paths = array(APP_ROOT, VIEW, MODEL, CONTROLLER, TEMPLATE, CONTENT, HELPERS);
// Set the include path from Config Object
set_include_path(implode(PS, $paths));
// Autoloader
function __autoload($class)
{
require_once $class.'.php';
return;
}
Then all you have to do is
$var = new ClassName();
but you have to have a php file in the path with the name
ClassName.php
where ClassName is the same as the name of the class you want to instantiate.

Categories