I'm trying to encapsulate an included file within a function. Nothing from the included file should be accessible outside the encapsulation function.
What I've found is that variables from the included file will be limited to the scope of the encapsulation function, but functions from the included file will be globally accessible.
index.php:
function encapsulate_this() {
include 'some_file.php';
}
encapsulate_this();
echo say_hello();
echo $test_variable;
some_file.php:
$test_variable = "Hi!";
function say_hello() {
return "Hello!";
}
Output:
Hello!
In the above example echoing say_hello() will work, but $test_variable will not.
How can I successfully encapsulate functions from the included file so they are not globally accessible?
All functions (and classes) are global in PHP, there's no such concept as "scope" for those things. I only see two options:
Name your functions and/or classes in a way so they won't conflict with other global things, namespaces can help a lot here. E.g. if you rigorously apply the PSR-4 naming standards to all files and all functions, it doesn't really matter whether functions are exposed globally or not, since their names cannot conflict.
Use anonymous functions, which is the only way functions can be scoped:
$say_hello = function () {
return 'Hello';
};
Obviously, both depend on the included file to cooperate; if you're including a third party file which does not adhere to either standard, you're SOL.
You should consider anonymous classes (php7+). In a class you can have public, protected and private members.
public members are accessible from outside the class.
protected members are accessible from inside the class and classes which inherit the class.
private members are only accessible from inside the class.
A little example:
some_file.php
$helloClass = new class('HelloWorld') {
public function say_hello_public(){
return "Hello!";
}
private function say_hello_private(){
return "Hello!";
}
};
index.php
function encapsulate_this() {
include 'some_file.php';
echo $helloClass->say_hello_public(); //Works because it's a public method.
echo $helloClass->say_hello_private(); //Won't work because it's a private method.
}
encapsulate_this();
echo $helloClass->say_hello_public(); //Won't work outside scope
Related
Following non OOP file (incOverview.php) :
<?php
echo show_value();
classView.php
<?php
class myView
{
public function loadView()
{
include("incOverview.php");
}
public function show_value()
{
return 42;
}
}
$objView = new myView();
$objView->loadView();
This will not work, it's only a sample to explain my problem.
I expect "12"
When i include this file in an PHP class, the global function show_value does not exists, as expected.
But it exists inside the class. Normally the included file must be changed to $this->show_value(); but in this scenario it is not possible.
Is there a solution, to include this non OOP file into my class and the class handles all requested functions ?
You can wrap functions in your non-oop file as a trait and include trait inside your classes. Or include your file outside the classes. And functions will be available in global namespace.
Let's say I have a class:
class test {
public static function sayHi() {
echo 'hi';
}
}
Call it by test::sayHi();
Can I define sayHi() outside of the class or perhaps get rid of the class altogether?
public static function sayHi() {
echo 'hi';
}
I only need this function to encapsulate code for a script.
Maybe the answer is not a static method but a plain function def?
A static method without a class does not make any sense at all. The static keywords signals that this method is identical for all instances of the class. This enables you to call it.. well.. statically on the class itself instead of on one of its instances.
If the content of the method is self-contained, meaning it does not need any other static variables or methods of the class, you can simply omit the class and put the code in a global method. Using global methods is considered a bad practice.
So my advice is to just keep the class, even if it has only that one method within. This way you can still autoload the file instead of having to require it yourself.
Functions in OOP are public by default, you can modify them to private like:
private function test(){
//do something
}
Or like you said, to static, in public or private like:
private static function test(){
//do something
}
But if you're not using OOP, functions by default are global and public, you can't change their access to private. That's not the way they are supposed to works because if you change their type to private, you will NEVER be able to access to that function. Also, static doesn't works because is another property of OOP...
Then, you can simply create that function and access it from everywhere you want (obviously where is available :P because you need to include the file where is stored)
Inside the definition of a class' method I include an external file. I would like this external file unable to access $this, but only the "public" instance, i.e. only the public methods and properties.
So far I have tried to use anonymous functions, call_user_func with a method returning $this.
I have seen I can unset $this in my anonymous function without altering the rest of the execution, but I haven't found a way to get the instance as I want it. I think I could try to unset all non-public properties and methods in the anonymous function but I wonder if there is not a simpler way.
Class Foo{
private $test = 23;
public function getFoo(){
return $this;
}
public function inclFile($file){
$foo = call_user_func([$this, 'getFoo']);
$r = function()use($foo){
unset($this);
var_dump($foo->test); // i am getting it!
require($file);
};
$r();
// Here $this is still set
}
}
I would turn the design around a bit, and create this function (and place it anywhere):
function access_object_in_file($file_to_require, $object) {
require $file_to_require;
}
This will limit the scope of the file to only have access to $object. Since PHP is PHP, your file will be allowed to create reflection classes, parse back trace etc but the variable scope is limited to $object.
If you do not want any type of objects passed to the function, I would add an interface and type hint for it, such as this:
// let's pretend we're in a view layer
function render($view_file, Properties $object) {
require $file_to_require;
}
in C , i can define a function to be static so it can only be used in it's own file.
in python , i can define a function with it's name starts with _ so this function can't be used outside this finle.
could i do it in php ?
If you really mean "functions": No, both arent possible.
First: Functions are always static.
Second: In PHP namespaces are not bound to a file. So a file can declare non, one or more namespaces. On the other side a namespace can be declared in different files. Its difficult to define a consistent way on how non-public functions can get resolved. You can use static classes instead.
A class can be used to for data hiding and implementing encapsulation.
You can use private keyword to declare functions in php to hide them outside of code but the all are bounded with class.
Only class can use these type of functions.
class A
{
/* This method will only be accessible in this
class only by the other methods of this class
and will be hide from rest of program code*/
private function setValues()
{
//some stuff
}
public function getVal()
{
$this->setValues();
}
}
The method above can only be accessible by this class.
How to create a PHP function only visible within a file? Not visible to external file. In other word, something equivalent to static function in C
There is no way to actually make a function only visible within a file. But, you can do similar things.
For instance, create a lambda function, assign it to a variable, and unset it when your done:
$func = function(){ return "yay" };
$value = $func();
unset($func);
This is provided that your script is procedural.
You can also play around with namespaces.
Your best bet is to create a class, and make the method private
Create a class and make the method private.
<?php
class Foo
{
private $bar = 'baz';
public function doSomething()
{
return $this->bar = $this->doSomethingPrivate();
}
private function doSomethingPrivate()
{
return 'blah';
}
}
?>
Use namespace, for apply your own visibility.
In the PHP world, namespaces are designed to solve two problems that
authors of libraries and applications encounter when creating
re-usable code elements such as classes or functions:
Name collisions between code you create, and internal PHP classes/functions/constants or third-party classes/functions/constants.
Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code.