Can functions be called without a class outside of a class?
I have some code that I found to do hashing and authentication for my passwords. The php file however doesn't have a class declaration at the top just the functions. I'm not sure how to call the functions from my other pages. Here is the hashing file I'm using
The Hashing file is set up like this :
<?php
public function MyFunction() {
}
Rather than like this:
<?php
class MyClass{
public function MyFunction() {
}
}
I have tried
include_once 'PasswordHash.php';
Then in my page calling the functions with these:
Echo PasswordHash::create_hash('$Pass');
Echo create_hash('$Pass');
Echo PasswordHash->create_hash('$Pass');
None of them work and show Fatal error:blah blah cant find class.
Thank you for reading and your help.
You will need to initiate your classes.
$password = new PasswordHash($pass);
echo $password->create_hash;
Or something along those lines.
Several issues:
create_hash('$pass') will create a hash of the string $pass, not the value of the variable, pass like this: create_hash($pass)
You must create an instance of your class, before you can call its methods.
You linked to a non-OO code example, why bother using classes, instead of using the code that is already there?
So, if you are going to continue using this class:
$hasher = new MyClass();//or whatever name you gave the class
echo 'The hash of the password is: ', $hasher->createHash($pass);//<-- change createHash with correct method name
If you are going to copy paste the example code (if it's allowed), simply call it like any old function:
echo 'The hash of the password is: ', create_hash($pass);
But make sure the functions are declared:
if (!function_exists('create_hash'))
include 'path/to/file/containing/create_hash_functions.php';
Oh, and functions outside a class don't have access modifiers:
function thisWorks(){}
//note: no public
public function thisFails(){}// <== error!
I found that you must create the object then you can work with it.
no need to make it a class just the functions.
include_once '../Resources/PasswordHash.php';
$result = validate_password("foobar", $hash);
That was all it needed.
Just to be included and then you can call it like any other function in the class.
Related
I'm coding a Wordpress plugin and I'm not sure regarding the function name conflict..
I have a file named test_handling.php which contains the following content :
function testing() { echo 'test'; }
I included this file in a class constructor (file named testcls.class.php) :
class TestCls {
function __construct() {
require_once('test_handling.php');
testing();
}
function otherfunction() {
testing();
}
// ...
}
In this case, I would like to know if the testing() function is only available in the TestCls class, or can it create conflicts if an other WP plugin has a function with the same name ?
Even with the same name, the functions will have different scope if defined as class method. To make a call to a regular function you will do the following:
testing();
and the result will be:
'test'
the class method need an instance of the class or be statically called. To call the method class you will need the following formats:
$class->test();
or
OtherPlugin::test();
To sum up, the function test will be different if defined as class method. Then, you will not have conflicts.
Other way to encapsulate your function and make sure you are using the right one is with namespaces. If you use a namespace in your test_handling.php
<?php
namespace myname;
function testing(){echo 'test';}
?>
You will access the function test like this:
<?php
require_once "test_handling.php";
use myname;
echo myname\testing();
Now you are sure about the function you are calling.
When a file is included, the code it contains inherits the variable
scope of the line on which the include occurs. Any variables available
at that line in the calling file will be available within the called
file, from that point forward. However, all functions and classes
defined in the included file have the global scope.
from include in PHP manual
Which means that yes, you can have conflicts.
update:
the code i put below will be invoked by a form on other webpage. so that's why I didn't made a instance of a obj.
More detail code:
$serverloc='serverURL';
class Aclass{
function push(){
global $serverloc;
echo $serverloc;
funNotinClass();
}
function otherFunction(){
echo $serverloc;
}
}
funNotinClass(){
echo $serverloc;
}
There is a Class contains 2 functiona "push()" and "otherFunction()" and there is independent function "funNotinClass()" and push() calls it. The class is for a web form in other page. When user click submit the form call the class and use the push() function. A weird thing I found is that the global var $serverloc is invisible to push() and funNotinClass()(they don't print out any thing), but otherFuction() which is a function just like puch() inside of the Aclass can just use the $serverloc(I dont even add global in front of it). How strange....anyone know what is the reason caused this?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
I read many information about the scope of a global var in php.
they all say a global var is defined outside of function or class and you can use it by using global this key word.
So this is my code
$serverloc='serverURL';
class Aclass{
function Afunction(){
global $serverloc;
echo $serverloc;
}
}
but when I run this class it didn't print anything out.
Is that because I did something wrong or global var just doesn't work this way. Since all the example I read before are just access a global var in functions directly not a function in a class
As per DaveRandom's comment - you haven't actually made an instance of an Aclass object.
This works and displays data as expected:
<?php
$serverloc='serverURL';
class Aclass{
global $serverloc;
function Afunction()
{
echo $serverloc;
}
}
$me = new Aclass();
$me->Afunction(); // output: serverURL
?>
Edit: DaveRandom seems to post asnwers as comments. Go Vote up some of his other answers, the rep belongs to him not me. I am his ghostwriter tonight.
If it is class globals you are after you could do like
class myClass
{
private $globVar = "myvariable";
function myClass()
{
return $this->globVar;
}
}
but when I run this class it didn't print anything out
You don't run classes, in the sense of executing them. A class is a just a data structure that holds data and functions related (called methods).
As most traditional data structures, you create instances of them (called objects), and then you execute actions on them. One way to execute actions on objects (instances of classes), is to pass a message for it to do something: that is calling a method.
So, in your case you could do:
$obj = new Aclass(); // create an object, instance of Aclass
$obj->Afunction(); // ask it to perform an action (call a method)
Having said that, sometimes you want to create a class only for grouping related functions, that never actually really share data within an object. Often they may share data through a global variable (eg.: $_SERVER, $_GET, etc). That may be the case of your design right there.
Such classes can have its methods executed without never instantiating them, like this:
Aclass::Afunction();
While relying on global variables is usually an indicator of quick'n dirty design, there are cases in which it really is the best trade-off. I'd say that a $serverlocation or $baseurl may very well be one of these cases. :)
See more:
The basics on classes and objects in the PHP manual
About the static keyword
I'm using the Markdown library for PHP by Michel Fortin. Setup is easy and it works great like this:
include_once "markdown.php";
$my_html = Markdown($my_text);
However, I have a class in which I want to pass stuff and 'Markdown' it, like so:
class Test
{
public function showMarkdown ($text)
{
return Markdown($text);
}
}
Obviously, my class is much larger than this, but this is what it boils down to. In my main script I do:
include_once "markdown.php";
$test = new Test();
echo $test->showMarkdown($text);
This returns an error, saying the function 'Markdown' is undefined. That seems obvious, because it's not within the class and I haven't used a scope operator. But when I put the include inside my class and use $this->Markdown or self::Markdown the function is still undefined. I figured that the Markdown function can't be defined inside another function.
So, how can I solve this? I need to do the include, which loads the Markdown function (and the rest of its family) but I want to be able to use it from within my classes.
Thanks for your answers/ideas.
Your example code calls a free function called Markdown (which presumably is defined in markdown.php). You simply need to put the include in the same file as your Test class.
After doing this, you will still call Markdown as a free function, and not as an instance ($this->Markdown) or static (self::Markdown) method.
write
function showMarkdown ($text)
in place of
public function showMarkdown ($text)
and
echo $test->showMarkdown("Hello World");
I've got a class I wrote to work with the front end (web browser side) of a shopping cart.
It's fairly simple in that I send the class a product ID that I bury in the URL and then query a database populating the classes variables for use in retrieving the data through some public methods.
To interface with my actual physical web page I have a file I call viewFunctions.php. Wherein I instantiate my class called ItemViewPackage():
<?php
require_once(dirname(__FILE__) . '/ItemViewPackage.php');
$viewObject = new ItemViewPackage($_GET['page']);
So, I have shoppingcartpage.php (the physical url) that requires the file viewFunctions.php that loads my class ItemViewPackage().
The output page shoppingcartpage.php calls functions like get_item_info('title') or get_item_info('price') which in the viewFunctions.php file is made like so:
function get_info($type){
echo $viewObject->get_info($type);
}
Now, right off the bat, this isn't working because, I assume, $viewObject is not global. So I make $viewObject global like so:
function get_info($type){
global $viewObject;
echo $viewObject->get_info($type);
}
But, this doesn't work either, I still get an error for "Call to a member function get_info() on a non-object"
Now, the only thing that works is:
function get_info($type){
$viewObject = new ItemViewPackage($_GET['page']);
echo $viewObject->get_info($type);
}
But, I don't want to re-instantiate my object every time I make a call to this function (which is several times for several bits of information). I'd rather instantiate once at the top of my viewFunctions.php doc and use that object every time I call this function.
Am I going about this completely wrong?
Thanks in advance.
DIAGRAM (hopefully it helps visualize)
What for do you need viewFunctions.php anyway? It's only wrapping the ItemViewPackage. Remove that and use the ItemViewPackage directly, e.g.
// shopping.php
include_once 'ItemViewPackage.php';
$viewObject = new ItemViewPackage($_GET['page']);
<div><?php echo $viewObject->get_info('title'); ?></div>
<div><?php echo $viewObject->get_info('price'); ?></div>
Then you dont have to bother with globals or Singletons. If you dont want a second instance, dont instantiate a second one. It's simple as that in PHP. If there is anything in viewFunctions.php that modifies the output of the $viewObject instance, consider making that into a class and have it aggregate the $viewObject into a property, e.g.
// viewFunctions.php
include_once 'ItemViewPackage.php';
$viewObject = new ItemViewPackage($_GET['page']);
$helper = new ViewObjectHelper($viewObject);
then you can access the $viewObject from within the Helper object with $this->propertyName.
As for reducing load to the database: this is a solved problem. Consider using a cache.
You want the singleton pattern, please see this answer:
Creating the Singleton design pattern in PHP5
This allows you to get an instance of your class in any scope, and it will also be the same instance.
What scope is the $viewObject created in?
Note: that even though it appears to be in the global scope because it is not in a function within the shown file, if the file is included from within a function it will be in that scope...
i.e.
file1.php
include 'file2.php';
function includefile($file) {
include $file;
}
includefile('file3.php');
file2.php
$global = 'this is global';
file3.php
$notglobal = 'this is not';
<?php
require_once(dirname(__FILE__) . '/ItemViewPackage.php');
$viewObject = new ItemViewPackage($_GET['page']);
function get_info($type){
global $viewObject;
echo $viewObject->get_info($type);
}
This should work from viewFunctions.php and any file that includes it such as shopping.php. So from shopping.php we can do either:
echo get_info($type);
or
echo $viewObject->get_info($type)
This alone raises some logical flags in my head. Not sure why you want to wrap the object again.
Can you declare a function like this...
function ihatefooexamples(){
return "boo-foo!";
};
And then redeclare it somewhat like this...
if ($_GET['foolevel'] == 10){
function ihatefooexamples(){
return "really boo-foo";
};
};
Is it possible to overwrite a function that way?
Any way?
Edit
To address comments that this answer doesn't directly address the
original question. If you got here from a Google Search, start here
There is a function available called override_function that actually fits the bill. However, given that this function is part of The Advanced PHP Debugger extension, it's hard to make an argument that override_function() is intended for production use. Therefore, I would say "No", it is not possible to overwrite a function with the intent that the original questioner had in mind.
Original Answer
This is where you should take advantage of OOP, specifically polymorphism.
interface Fooable
{
public function ihatefooexamples();
}
class Foo implements Fooable
{
public function ihatefooexamples()
{
return "boo-foo!";
}
}
class FooBar implements Fooable
{
public function ihatefooexamples()
{
return "really boo-foo";
}
}
$foo = new Foo();
if (10 == $_GET['foolevel']) {
$foo = new FooBar();
}
echo $foo->ihatefooexamples();
Monkey patch in namespace php >= 5.3
A less evasive method than modifying the interpreter is the monkey patch.
Monkey patching is the art of replacing the actual implementation with a similar "patch" of your own.
Ninja skills
Before you can monkey patch like a PHP Ninja we first have to understand PHPs namespaces.
Since PHP 5.3 we got introduced to namespaces which you might at first glance denote to be equivalent to something like java packages perhaps, but it's not quite the same. Namespaces, in PHP, is a way to encapsulate scope by creating a hierarchy of focus, especially for functions and constants. As this topic, fallback to global functions, aims to explain.
If you don't provide a namespace when calling a function, PHP first looks in the current namespace then moves down the hierarchy until it finds the first function declared within that prefixed namespace and executes that. For our example if you are calling print_r(); from namespace My\Awesome\Namespace; What PHP does is to first look for a function called My\Awesome\Namespace\print_r(); then My\Awesome\print_r(); then My\print_r(); until it finds the PHP built in function in the global namespace \print_r();.
You will not be able to define a function print_r($object) {} in the global namespace because this will cause a name collision since a function with that name already exists.
Expect a fatal error to the likes of:
Fatal error: Cannot redeclare print_r()
But nothing stops you, however, from doing just that within the scope of a namespace.
Patching the monkey
Say you have a script using several print_r(); calls.
Example:
<?php
print_r($some_object);
// do some stuff
print_r($another_object);
// do some other stuff
print_r($data_object);
// do more stuff
print_r($debug_object);
But you later change your mind and you want the output wrapped in <pre></pre> tags instead. Ever happened to you?
Before you go and change every call to print_r(); consider monkey patching instead.
Example:
<?php
namespace MyNamespace {
function print_r($object)
{
echo "<pre>", \print_r($object, true), "</pre>";
}
print_r($some_object);
// do some stuff
print_r($another_object);
// do some other stuff
print_r($data_object);
// do more stuff
print_r($debug_object);
}
Your script will now be using MyNamespace\print_r(); instead of the global \print_r();
Works great for mocking unit tests.
nJoy!
Have a look at override_function to override the functions.
override_function — Overrides built-in
functions
Example:
override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
short answer is no, you can't overwrite a function once its in the PHP function scope.
your best of using anonymous functions like so
$ihatefooexamples = function()
{
return "boo-foo!";
}
//...
unset($ihatefooexamples);
$ihatefooexamples = function()
{
return "really boo-foo";
}
http://php.net/manual/en/functions.anonymous.php
You cannot redeclare any functions in PHP. You can, however, override them. Check out overriding functions as well as renaming functions in order to save the function you're overriding if you want.
So, keep in mind that when you override a function, you lose it. You may want to consider keeping it, but in a different name. Just saying.
Also, if these are functions in classes that you're wanting to override, you would just need to create a subclass and redeclare the function in your class without having to do rename_function and override_function.
Example:
rename_function('mysql_connect', 'original_mysql_connect' );
override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');
I would include all functions of one case in an include file, and the others in another include.
For instance simple.inc would contain function boofoo() { simple } and really.inc would contain function boofoo() { really }
It helps the readability / maintenance of your program, having all functions of the same kind in the same inc.
Then at the top of your main module
if ($_GET['foolevel'] == 10) {
include "really.inc";
}
else {
include "simple.inc";
}
You could use the PECL extension
runkit_function_redefine — Replace a function definition with a new implementation
but that is bad practise in my opinion. You are using functions, but check out the Decorator design pattern. Can borrow the basic idea from it.
No this will be a problem.
PHP Variable Functions
Depending on situation where you need this, maybe you can use anonymous functions like this:
$greet = function($name)
{
echo('Hello ' . $name);
};
$greet('World');
...then you can set new function to the given variable any time
A solution for the related case where you have an include file A that you can edit and want to override some of its functions in an include file B (or the main file):
Main File:
<?php
$Override=true; // An argument used in A.php
include ("A.php");
include ("B.php");
F1();
?>
Include File A:
<?php
if (!#$Override) {
function F1 () {echo "This is F1() in A";}
}
?>
Include File B:
<?php
function F1 () {echo "This is F1() in B";}
?>
Browsing to the main file displays "This is F1() in B".