Include file content into property? - php

I've a file called helper.php, in this file I've a list of functions (without class).
Now I need to include the content of helper file, into a property. For do this I've create a loader, this is an example:
class Loader
{
function include($helpName)
{
return include $helpName;
}
}
this Loader is used by my class like so:
class Foo
{
function __construct()
{
$this->load = new Loader();
$this->email = $this->load->include('helper.php');
$this->email->send();
}
}
unfortunately I get this error:
Fatal error: Call to a member function validate_email() on integer
if I print: var_dump($this->email); I'll get: int(1).
What am I doing wrong?

Unless you're specifically returning at the end of your class, it doesn't work that way. From the docs:
Handling Returns: include returns FALSE on failure and raises a warning. Successful includes, unless overridden by the included file, return 1.
I'd look into autoloading classes, or you can also create a class, and return that from your include.php.
public class Email
{
public function send()
{
echo 'Sending Email';
}
}
return new Email();
An example with autoloading:
//Create Email.php
public class Email
{
public function send()
{
echo 'Sending Email';
}
}
//Main file, set a register, so when it doesn't find a class, it will load from a file, and auto register it.
spl_autoload_register(function ($class_name) {
include $class_name . '.php';
});
class Foo
{
function __construct()
{
$this->load = new Loader();
//If Email class doesn't exist, it will load it from 'Email.php', and then initialize it.
$this->email = new Email();
$this->email->send();
}
}

Included code always runs in global scope. If you want your functions to be incorporated as methods of a class then you would need to create a new file wrapping the functions in
<?php
Class somename {
?>
And...
<?php
}
But writing self modifying code is inherently dangerous. And its ugly. And it will be sensitive to whether you explicitly end the included file with ?>
An alternative approach which sucks as much as that above, is to get a list of the defined functions, and invoke these from the _call() magic method:
Class somename {
public $included;
function _call($fn, $args)
{
return call_user_func_array($this->included[$fn]), $args);
}
}
$obj=new somename();
$before=get_defined_functions();
include('helper.php');
$obj->included=array_diff(get_defined_functions(), $before);
But you wil find that your included code will not run outside of a class if it references $this
Short version: do not do this

Related

add more methods to class using include_once [duplicate]

I want to make a PHP class, lets say Myclass.php. Now inside that class I want to define just the class itself and some instance variables. But all the methods must come from a Myclass_methods.php file. Can I just include that file into the class body?
I have good reasons why I want to seperate this. In short, I'll have a backend in which I can change the business logic of a class, while all other things must remain untouched. The system maintains all the ORM and other stuff for me.
But if this is a bad idea, it might be better to re-generate the whole class file after editing the business logic (so, the user-defined methods in this case).
Performance question: If during one request Myclass.php is included just once, actually that Myclass_methods.php should also be included just once. Might be wrong. Experts?
No. You cannot include files in the class body.
In a file defining a class, you may only include files in a method body or outside the class body.
From your description I take you want this:
<?php // MyClass.php
class MyClass
{
protected $_prop;
include 'myclass-methods.php';
}
<?php // myclass-methods.php
public function myMethod()
{
$this->$_prop = 1;
}
Running this code will result in
Parse error: syntax error, unexpected T_INCLUDE, expecting T_FUNCTION
What is possible though is this
<?php // MyClass.php
class MyClass
{
protected $_prop;
public function __construct() // or any other method
{
include 'some-functions.php';
foo($b); // echoes 'a';
}
}
<?php // some-functions.php
$b = 'a';
function foo($str)
{
echo $str;
}
Doing it this way, will import the contents of the include file into the method scope, not the class scope. You may include functions and variables in the include file, but not methods. You could but should not put entire scripts into it as well and change what the method does, e.g.
<?php // MyClass.php
// ...
public function __construct($someCondition)
{
// No No Code here
include ($someCondition === 'whatever') ? 'whatever.php' : 'default.php';
}
// ...
<?php // whatever.php
echo 'whatever';
<?php // default.php
echo 'foo';
However, patching the class this way to exhibit different behavior is not how you should do it in OOP. It's just plain wrong and should make your eyes bleed.
Since you want to dynamically change behavior, extending the class is also not a good option (see below why). What you really will want to do is write an interface and make your class use objects implementing this interface, thus making sure the appropriate methods are available. This is called a Strategy Pattern and works like this:
<?php // Meowing.php
interface Meowing
{
public function meow();
}
Now you got the contract that all Meowing Behaviors must obey, namely having a meow method. Next define a Meowing Behavior:
<?php // RegularMeow.php
class RegularMeow implements Meowing
{
public function meow()
{
return 'meow';
}
}
Now to use it, use:
<?php // Cat.php
class Cat
{
protected $_meowing;
public function setMeowing(Meowing $meowing)
{
$this->_meowing = $meowing;
}
public function meow()
{
$this->_meowing->meow()
}
}
By adding the Meowing TypeHint to setMeowing, you make sure that the passed param implements the Meowing interface. Let's define another Meowing Behavior:
<?php // LolkatMeow.php
class LolkatMeow implements Meowing
{
public function meow()
{
return 'lolz xD';
}
}
Now, you can easily interchange behaviors like this:
<?php
require_once 'Meowing.php';
require_once 'RegularMeow.php';
require_once 'LolkatMeow.php';
require_once 'Cat.php';
$cat = new Cat;
$cat->setMeowing(new RegularMeow);
echo $cat->meow; // outputs 'meow';
// now to change the behavior
$cat->setMeowing(new LolkatMeow);
echo $cat->meow; // outputs 'lolz xD';
While you also could have solved the above with inheritance by defining an abstract BaseCat and meow method and then deriving concrete RegularCat and Lolkat classes from that, you have to consider what you want to achieve. If your cats will never change the way they meow, go ahead and use inheritance, but if your RegularCat and Lolkat is supposed to be able to do arbitrary meows, then use the Strategy pattern.
For more design patterns in PHP, check these resources:
http://www.php.net/manual/en/language.oop5.patterns.php
http://www.ibm.com/developerworks/library/os-php-designptrns/
http://www.fluffycat.com/PHP-Design-Patterns/
http://sourcemaking.com/design_patterns
Might it not be an idea to create the core class with the relevant base functionality and then extend this with the required methods - it seems like a more logical approach.
I'll start by saying I'm not too clear why this problem is not best solved using a base class containing the methods, subclasses containing the data, and dynamic class loading. I'll assume you have a good reason.
Once your provider supports PHP 5.4 you can do what you want using traits.
Code File:
if ($pet === 'dog') include 'dog.php';
elseif ($pet === 'cat') include 'cat.php';
else die('Unknown pet');
class Pet {
use PetSounds;
}
$myPet = new Pet();
$myPet->speak();
File cat.php
trait PetSounds {
function speak() { echo 'meow'; }
}
File dog.php
trait PetSounds {
function speak() { echo 'woof'; }
}
You could make this even cleaner by naming both include files the same, putting them in different subdirectories, and using set_include_path() or defining an __autoload() function to select between them. Like I said though, this same problem could be solved better using inheritance. If you have a multiple-inheritance type problem though, if for instance you have four kinds of pets with five kinds of colors with three hair types and you need a different combination of methods for each of the 60 different classes, this is the right solution.
5.4 is currently just a Release Candidate (as of 2/24/2012) and even once released most hosts will not support it for many months - mine took 18 months after 5.3 was released before they would support it. Until then you must write entirely separate and complete class files. You can however format your classes with an eventual change to traits in mind.
Right now you can partially get what you want using magic methods and have an easy upgrade to traits when they are available.
Code File:
if ($pet === 'dog') include 'dog.php';
elseif ($pet === 'cat') include 'cat.php';
else die('Unknown pet');
class Pet {
public function __call($name, array $arguments)
{
array_unshift($arguments, $this);
return call_user_func_array("TraitFunc_$name", $arguments);
}
}
$myPet = new Pet();
$myPet->speak();
File cat.php
function TraitFunc_speak(Pet $that) { echo 'meow'; }
File dog.php
function TraitFunc_speak(Pet $that) { echo 'woof'; }
You are limited however in that your functions can not access private and protected class properties and methods and you can not use this method to provide magic methods such as __get(). Traits will solve both of those limitations.
What about using traits for this? Would that be an acceptable option? This is something I am currently experimenting with and it seems to work quite while.
A simplified version of what I am doing is basically like this. I have an application with shared core files and multiple projects. Within those projects i have modules. I want to have functions that are available for the entire project on a core level but only for that specific project.
My project controller
if(is_file(PROJECT_PATH.'/project_extensions.trait.php')){
// additional functions for this specific project
require_once(PROJECT_PATH.'/project_extensions.trait.php');
}else{
// no additional functions
trait Extensions{};
}
Class Project{
USE Extensions;
// default functions shared between all projects
function shared_stuff(){
}
}
Extensions file
trait Extensions{
// project-specific extensions
function this_project_only(){
echo 'Project Only';
}
}
Module file in the project
class MyModule extends Modules{ // modules extends projects in a different class not relevant here
function do_something(){
echo $this->project_only();
}
}
Since PHP5.4 release you can create dynamic objects like this: https://github.com/ptrofimov/jslikeobject
But this is scarcely the best practice.
Reviving an old question but this is a fairly simple solution. Do you need the common function calls to be exclusive to your class? If not, simply include your common function file(s) within the same scope as your class. You will need to create methods in your class but they will only need to call the common function. Here's a simple SOAP server example:
<?php
include 'post_function.php';
$server = new SoapServer( null, array('uri' => "http://localhost/") );
$server->setClass( 'postsoapclass' );
$server->handle();
class postsoapclass
{
public function animalNoise( $animal )
{
return get_animal_noise($animal);
}
}
?>
post_function.php
<?php
function get_animal_noise($animal)
{
if(strtolower(trim($animal)) == 'pig')
{
return 'Oink';
}
else
{
return 'This animal is mute';
}
}
?>
I have had to do what you are describing in cases where I maintain a free version and a premium version of the same software. Because, as #Gordon noted, you cannot do exactly this:
class SomeClass {
premium_file = "premium.php";
if (file_exists($premium_file)) {
require($premium_file);
}
Instead I do this:
premium_file = "premium.php";
if (file_exists($premium_file)) {
require($premium_file);
}
class SomeClass {
...
For functions you want to reference, create class methods in the main class, and call the included file's method, passing the $this pointer as a parameter. So that I can tell at a glance where functions are, I will prefix the name of the included functions as shown below:
class SomeClass {
...
// Premium functions
public function showlist() {
premium_showlist($this);
}
You can include or require before declaring your class like below:
require 'path-to-file';
class myClass{
function show($uid){
}
}
The answer is yes, for example:
Into class construct, pass to the function (that's into the included file) values as params:
$this->wpd = $this->wpdopt = 'something';
include_once('/common/functions_common.php');
$this->wpdb = wpquery($sql='', $mode='', $this->wpd);
Into the included functions_common.php file:
function wpquery($sql, $mode, $wdp)
{
if(!empty($wdp))
{ return true; } else { return false; }
}
Into class methods:
$sql = "UPDATE ..... SET ... WHERE LOWER(user_email) = . ...";
$this->wpdb = wpquery($sql,'update',$this->wpd);
OR
$retval_var = $this->wpdb = wpquery($sql,'update',$this->wpd);
OR even
$this->var = $this->wpdb = wpquery($sql,'update',$this->wpd);
Cheers to all the lovely and cool people
I came across this recently, and came up with a solution, that helped in my case. I wanted many functions in a class, but the class became bloated, so wanted to separate out the class functions into groups for readability. It took a little time to accomplish, but since the functions of the class didn't rely (much) on $this, I removed "$this" from the class functions and created several helper files to include those functions. When $this was necessary, I could nevertheless move the function into a helper file, by passing $this to the function, adding public set/get functions where necessary. It's a hack, but it's sure to help someone
class myClass
{
var x;
function myClass()
{
$this->x = 0;
}
function myFunc1Group1()
{
$x = $this->x;
$x++;
$this->x = $x;
}
function myFunc2Group1(){}
function myFunc1Group2(){}
function myFunc2Group2(){}
}
can be worked around to
class myClass
{
var x;
function myClass()
{
$this->x = 0;
}
function doSomething()
{
// not called on $this but takes $this as a parameter
myFunc1Group1($this);
}
}
and helper function set 1
function myFunc1Group1($THIS_OBJECT)
{
$x = $THIS_OBJECT->getX();
$x++;
$THIS_OBJECT->setX($x);
}
function myFunc2Group1($THIS_OBJECT){}
and helper function set 2, etc.
Probably not the best route in all cases, but helped me out a lot. Basically the class functions were only to construct and delegate, and the calculations were put into helpers.

Limit scope of require'd class definitions to a function

I have folder with many plugins. Each plugin contains same name class but different content:
plugin01.php
class Plugin{
public function get($a){
return 'Plugin01 - '.$a;
}
}
plugin02.php
class Plugin{
public function get($a){
return 'Plugin02 - '.$a;
}
}
In Plugins.php, i want to load this plugins. But not only once.
class Plugins{
public static function load($id){
require $id.'.php';
$plugin = new Plugin();
return $plugin->get('test');
}
}
echo Plugins::load('plugin01')."\n";
echo Plugins::load('plugin02')."\n";
echo Plugins::load('plugin01');
Expected result:
Plugin01 - test
Plugin02 - test
Plugin01 - test
Current Result:
Fatal error: Cannot redeclare class Plugin
This definitely does not work, because i am redefining class name and including more times same plugin.
My question is, can I include file only in Function scope (including all classes defined in external file), that if will not appear outside function?
Can I do that with PHP, or must I use different names for each class?
If you only ever could have one plugin loaded at a time, your method would work. But as you have found out, it will break with multiple classes with the same name.
I think a better solution would be to use interfaces, and then have the different plugins implement those interfaces.
So define an interface with all the methods a plugin should have:
interface Plugin
{
public function get($a);
}
then make each plugin implement it:
// Plugin1.php
class Plugin1 implements Plugin
{
public function get($a)
{
return 'Plugin 1 ' . $a;
}
}
// Plugin2.php
class Plugin2 implements Plugin
{
public function get($a)
{
return 'Plugin 2 ' . $a;
}
}
and then you can load and instantiate them almost in the same way:
class Plugins{
public static function load($pluginName){
require_once( $pluginName.'.php');
$plugin = new $pluginName();
return $plugin;
}
}
$plugin1 = Plugins::load('Plugin1');
echo $plugin1->get('Test');
$plugin2 = Plugins::load('Plugin2');
echo $plugin2->get('Test');
From the manual: include function
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.
So, you should rename your classes, since the scope is global.

How to include a php and then remove it?

Well, I don't know if this post have the correct title. Feel free to change it.
Ok, this is my scenario:
pluginA.php
function info(){
return "Plugin A";
}
pluginB.php
function info(){
return "Plugin B";
}
Finally, I have a plugin manager that is in charge of import all plugins info to pool array:
Manager.php
class Manager
{
protected $pool;
public function loadPluginsInfo()
{
$plugin_names = array("pluginA.php", "pluginB.php");
foreach ($plugin_names as $name)
{
include_once $name;
$this->pool[] = info();
}
}
}
The problem here is that when I print pool array it only show me the info on the first plugin loaded. I supposed that the file inclusing override the info because it still calling the info() method from the first include.
Is there a way to include the info of both plugins having the info() function with the same name for all plugins files?
Thank you in advance
PS: a fatal cannot redeclare error is never hurled
you can use the dynamic way to create plugin classes
plugin class
class PluginA
{
public function info()
{
return 'info'; //the plugin info
}
}
manager class
class Manager
{
protected $pool;
public function loadPluginsInfo()
{
$plugin_names = array("pluginA", "pluginB"); //Plugin names
foreach ($plugin_names as $name)
{
$file = $name . '.php';
if(file_exists($file))
{
require_once($file); //please use require_once
$class = new $name(/* parameters ... */); //create new plugin object
//now you can call the info method like: $class->info();
}
}
}
}
Are you sure the interpreter isn't choking w/ a fatal error? It should be since you're trying to define the info function twice here.
There are many ways to achieve what you want, one way as in #David's comment above would be to use classes, eg.
class PluginA
{
function info() { return 'Plugin A'; }
}
class PluginB
{
function info() { return 'Plugin B'; }
}
then the Manager class would be something like this:
class Manager
{
protected $pool;
public function loadPluginsInfo()
{
$plugin_names = array("PluginA", "PluginB");
foreach ($plugin_names as $name)
{
include_once $name . '.php';
$this->pool[] = new $name();
}
}
}
Now you have an instance of each plugin class loaded, so to get the info for a plugin you would have $this->pool[0]->info(); for the first plugin. I would recommend going w/ an associative array though so you can easily reference a given plugin. To do this, the assignment to the pool would become:
$this->pool[$name] = new name();
And then you can say:
$this->pool['PluginA']->info();
for example.
There are many other ways to do it. Now that 5.3 is mainstream you could just as easily namespace your groups of functions, but I would still recommend the associative array for the pool as you can reference a plugin in constant time, rather than linear.

How to share a dynamic variable between files in PHP(5)?

I have an object of some class that obeys the singleton pattern. I need to initialize it in one file and then use it in others. I don't know how to do this, here is what I tried :
//myClass.php
class myClass
{
private static $instance = null;
private function __construct($args)
{
//stuff
}
public function Create($args)
{
self::$instance = new myClass($args);
return self::$instance;
}
public function Get()
{
return self::$instance;
}
}
//index.php
<?php
require_once('myClass.php');
$instance = myClass::Create($args);
?>
Test Me!
//test.php
echo(is_null(myClass::Get())); //displays 1
So the problem is that from test.php, myClass::get() always returns null!
I have also tried to store the instance in the $_SESSION, which gives me the same result. Can you please point me in the right direction?
You should include file with the class difinition in each file where it used (and it should be included before it will in use).
<?php // filename: test.php
include_once("myClass.php");
$oClassInstance = myClass::Get();
var_dump($oClassInstance);
BTW
You don't need to define those two methods Create and Get. You can create only one method called getInstance:
// only one instance of the class
private static $_oInstance = null;
public static function getInstace()
{
if (!self::$_oInstance)
{
self::$_oInstance = new self();
}
return self::$_oInstance;
}
And then you can use it like:
<?php // filename: index.php
include_once("myClass.php");
// if instance does not exist yet then it will be created and returned
$oClass = myClass::getInstace();
<?php // filename: test.php
include_once("myClass.php");
// the instance already created and stored in myClass::$_oInstance variable
// so it just will be returned
$oClass = myClass::getInstance();
UPD
If you have to put some arguments into constructor just use predefined arguments:
private function __construct($aArg)
{
// this code will be launched once when instance is created
// in the any other cases you'll return already created object
}
public static function getInstance($aArgs = null)
{
if (!self::$_oInstance)
{
self::$_oInstance = new self($aArgs);
}
return self::$_oInstance;
}
ANSWER
Sorry that you have to scroll a few screens to find this =)))
The reason why you can't use myClass::Get() in you context is that you have 2 scripts that means - two different programs.
Singleton should be used within a single application (one script).
So in your case, correct usage will be module system:
- index.php
- main.php
- test.php
// file: index.php
include_once "myClass.php"
$module = $_GET["module"];
include_once $module ".php";
// file: main.php
$oClass = myClass::Create($someArgs);
var_dump($oClass); // you'll see you class body
// file: test.php
$oClass= myClass::Get();
var_dump($oClass); // you'll see the same class body as above
And your links will be:
index.php?module=main
index.php?module=test
The Create() function need to check whether $instance property already has a value before creating a new object. For example
public function Create()
{
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
In test.php you can just call myClass::Create(), no need to have the Get() function at all

php namespaces & autoload

I've read some posts about namespaces and autoload in php 5.3+, but still haven't succeeded in creating one working :x maybe some of you have an idea of what's going wrong about my code ?
Thank you previously.
Autoloader.php class
<?php
namespace my;
class AutoLoader {
private $aExt;
private $sPath;
protected static $instance;
public static function getInstance() {
if(!self::$instance instanceof self ) {
self::$instance = new self();
}
return self::$instance;
}
function __construct($sPath = __DIR__, $exts = 'php') {
// define path and extensions to include
$this->setPath($sPath);
$this->setExtensions($exts);
}
public function getPath() {
return $this->sPath;
}
public function setPath($path){
$this->sPath = $path;
}
public function removePath() {
unset ($this->sPath);
}
public function addExtension($ext) {
// prepends period to extension if none found
$this->aExt[$ext] = (substr($ext, 0, 1) !== '.') ? '.'.$ext : $ext;
}
public function removeExtension($ext) {
unset ($this->aExt[$ext]);
}
public function getExtensions() {
return $this->aExt;
}
public function setExtensions($extensions) {
// convert
if (is_string($extensions)) {
$extensions = array($extensions);
}
// add
foreach($extensions as $ext) {
$this->addExtension($ext);
}
}
public function register() {
set_include_path($this->sPath);
// comma-delimited list of valid source-file extensions
spl_autoload_extensions(implode(',',$this->aExt));
// default behavior without callback
spl_autoload_register(array($this, 'autoload'));
}
public function autoload($sClassName) {
include_once($sClassName.'.php');
return;
}
}
$autoloader = new AutoLoader();
$autoloader->register();
?>
MyClass.php the class i am trying to load dinamically
<?php
namespace my\tools;
class MyClass {
function __construct() {}
function __destruct() {}
function test() {
echo 'ok';
}
}
?>
index.php the caller
<?php
include_once('../Libraries/php/my/AutoLoader.php');
new my\tools\MyClass();
?>
and finally the class structures on my disk
Libraries
|_php
|_my
| |_Autoloader.php
|
|_MyClass.php
That's a tad bit over-engineered, my friend.
You might want to take a look at simply using PSR-0 (PRS-0 is now depreciated, PSR-4 is the new one), an autoloader specification from a large number of PHP projects, like phpBB, Joomla, CakePHP, Zend Framework and lots more. It's built with namespaces in mind, but works well with or without them.
The advantage of PSR-0 (or PSR-4) is that it leads to a clean, simple, obvious directory structure that an increasing number of projects are supporting. This means using one autoloader instead of a single autoloader for every single set of code.
spl_autoload_register() expects a valid callback. You give ... something ^^ But not a callback. A callback is
// a closure
$cb = function ($classname) { /* load class */ }
// object method
$cb = array($object, 'methodName');
// static class method
$cb = array('className', 'methodName');
// function
$cb = 'functionName';
See manual: spl_autoload_register() for further information and examples.
After searching a little on PHP.net website, the solution were really simple :/
In fact php autoload function MUST be on root namespace /, mine was on first level of my package (my/), when i moved the class to root namespace everything worked fine.

Categories