类/对象函数

目录

添加笔记

用户贡献的笔记 19 条笔记

10
gateschris at yahoo dot com
23 年前
[编辑说明:如果您试图进行覆盖,那么您只需询问(也许在方法本身中)对象属于哪个类(get_class()),或者它是否是特定根类的子类。

您始终可以引用父级覆盖方法,请参阅手册的“类和对象”页面以及其中的注释/编辑说明。]

没有函数可以确定成员是属于基类还是当前类,例如

<?php
class foo {
function
foo () { }
function
a () { }
}

class
bar extends foo {
function
bar () { }
function
a () { }
}

lala = new Bar();
?>
------------------
我们如何通过编程方式找到成员 a 现在属于类 Bar 还是 Foo。
5
covertka at muohio dot edu
19 年前
致 pillepop2003 at yahoo dot de

我遇到了同样的问题。我有一个基类,它为多个子类管理数据库任务。基类中的一个函数是一个 find() 方法,它返回子类的实例。由于 find() 通常被调用为静态方法,因此它需要知道子类的名称。正如您所发现的,这似乎无法轻松获得。

我找到的唯一获得子类名称的方法是使用 debug_traceback() 函数。这要求我在每个子类中都拥有一个 find() 方法,但它确实有效。

以下是一个示例

<?php
require_once("Application.php");

class
parentClass {
function
find() {
$className = NULL;
foreach (
debug_backtrace() as $bt) {
if (
$bt['function'] == __FUNCTION__) {
$className = $bt['class'];
}
}

// 这里应该有一些代码来查找正确的 ID,假设它是 ID 1
$id = 1;
return new
$className($id);
}
}

class
foo extends parentClass {
function
__construct($id) {
$this->id = id;
}

function
find() {
return
parent::find();
}
}

class
bar extends parentClass {
function
__construct($id) {
$this->id = id;
}

function
find() {
return
parent::find();
}
}

$a = foo::find();
printf("Type for \$a: %s<br/>\n", get_class($a));
$b = bar::find();
printf("Type for \$b: %s<br/>\n", get_class($b));
?>
3
asommer*at*as-media.com
21 年前
我刚刚发现了一些对我当前项目非常有用的东西

类可以在任何方法(包括构造函数)中覆盖自身,如下所示

class a {

..function ha ( ) {
....if ( $some_expr ) {
......$this = new b;
......return $this->ha ( );
....}
....return $something;
..}

}

在这种情况下,假设类 b 已经定义并且也具有 ha() 方法

请注意,覆盖自身语句之后的代码仍然执行,但现在适用于新类

我在任何地方都没有找到关于此行为的信息,因此我不知道这是否应该这样,以及它是否可能会改变……但它在灵活的脚本编写中打开了一些可能性!!
2
zidsu at hotmail dot com
21 年前
FYI:如果您想将您的类拆分为可管理的块,这意味着对您来说是不同的文件,您可以将您的函数放入包含文件中,并使 include() 具有返回值。就像这样

class Some_class {
var $value = 3;
function add_value ($input_param) {
return include ("path/some_file.php");
}
}

以及您的包含文件

$input_param += $this->value;
return $input_param;

然后您的函数调用将是

$instance = new Some_class ();
$instance->add_value (3);

这将返回
6
希望如此:P

请记住,包含文件中的作用域将与函数“add_value”的作用域相同。
如果您想返回结果,您也应该在您的包含中也进行 return 语句。
0
http://sc.tri-bit.com/ StoneCypher
19 年前
to covertka at muohio dot edu and pillepop2003 at yahoo dot de

有一个更简单的解决方案来获取用于与工厂函数一起工作的类的名称。假设您正在执行以下操作

<?php

function FactoryFunction($whatever, $instancedata) {

switch (
$whatever) {
case
'stuff' : return new Stuff($instancedata);
case
'otherstuff' : return new Otherstuff($instancedata);
}

}

?>

现在,考虑命名参数习惯用法,并记住 PHP 对所有内容都使用哈希;因此,进行以下更改

<?php

function FactoryFunction($whatever, $instancedata) {

switch (
$whatever) {

case
'stuff' : return array('typeis'=>'stuff', 'instance'=>new Stuff($instancedata));
case
'otherstuff' : return array('typeis'=>'otherstuff', 'instance'=>new Otherstuff($instancedata));

}

}

?>

简单易行。看来原帖作者想要的是类似于 C++ 静态数据成员的东西;不幸的是,由于 PHP4 根本没有静态变量,因此需要对语言进行重大更改以支持类似静态的行为。如果您迁移到 PHP5,静态关键字可以干净地解决您的问题。
0
ettinger at consultant dot com
20 年前
Re: 寻找未实例化的类

# 将数据从表加载到类对象中
class LFPDataFactory extends LFPObject {
var $object;
var $class;
var $table;
function LFPDataFactory($args) {
$this->unpackArgs($args); // 从 $args 中分配局部变量
if (in_array(strtolower($this->class), get_declared_classes())) {
$this->object = new $this->class;
// 组装表中的列...
// 选择它们的值并将其放入我们的新对象中...
} else { trigger_error("Class ".$this->class." not found", E_USER_ERROR); }
}
}
$r = new LFPDataFactory("class=LFPLayout,table=layout");
$new_obj = $r->object; // 这是一个 LFPLayout 对象。
print_r($new_obj);

此类会查看该类是否存在,然后实例化它 - 声明的类与实例化的类不同。只要 LFPLayout 存在于脚本中的某个位置,get_declared_classes() 就会找到它。但是,请记住对比较使用 strtolower。

为什么我要这样做?因为我的类布局与它们各自的表相同;工厂然后选择数据(确保变量匹配)并插入数据。(我已经省略了执行选择/插入的实际代码)。
-1
Dennis
14 年前
我们有一个数组,其中包含许多类似样式的对象

<?php

$step
= new StepModel(1); // 如果 StepModel 的 id 为“1”
$demand = $step->getDemand(); // 返回 DemandModel
$step2 = $demand->getCustomer(); // 返回 StepModel
$demand2 = $step2->getDemand(); // 返回 DemandModel

// [ ... ]

?>

$step 和 $step2 可以是同一个对象。所以我们有一个递归数组。现在我们需要知道 $step == $step2 还是 $step === $step2。换句话说:我们需要知道 PHP 内部资源 ID。

因为 PHP API 中没有此函数,所以我们创建了以下函数。

注意:在我们的案例中,所有对象都以 ["id":protected] 作为第一个属性。如果您的对象与之不同,则需要编辑 $pattern。

警告:函数非常慢,仅在调试原因需要时才应调用

<?php

/**
* 返回数组中所有对象的资源和对象 ID
*
* @param array $array
* @return array
*/
function getObjectInformation(Array $array)
{
// 开始输出缓冲
ob_start();

// 创建 $array 的 var_dump
var_dump($array);

// 将转储保存在变量 $dump 中
$dump = ob_get_contents();

// 清理输出缓冲
ob_end_clean();

// 删除空格
$dump = str_replace(' ', '', $dump);

// 定义正则表达式模式
// 在我们的案例中,所有对象看起来都像这样:
//
// object(ClassName)#1(1){
// ["id":protected]=>
// string(1)"1"
$pattern = '/object\(([a-zA-Z0-9]+)\)#([0-9]+)\([0-9]+\){\\n';
$pattern .= '\["id":protected\]=>\\n';
$pattern .= 'string\([0-9]+\)"([v]?[0-9]+)"/im';

// 搜索所有匹配项
preg_match_all($pattern, $dump, $regs);

// 按类名、对象 ID,然后按资源 ID 对所有匹配项进行排序
array_multisort($regs[1], SORT_ASC, SORT_STRING,
$regs[3], SORT_ASC, SORT_NUMERIC,
$regs[2], SORT_ASC, SORT_NUMERIC);

// 缓存上次匹配项
$lastMatch = array();

// 返回值
$return = array();

// 循环遍历匹配项
for ($i = 0; $i < sizeof($regs[0]); $i ++) {

// 检查当前匹配项之前是否已访问过
if (0 == sizeof($lastMatch) ||
$regs[1][$i] != $lastMatch[1] ||
$regs[2][$i] != $lastMatch[2] ||
$regs[3][$i] != $lastMatch[3]) {

// 将匹配项保存在返回值中
array_push($return, array($regs[1][$i],
$regs[2][$i],
$regs[3][$i]));
}

// 将匹配项保存在上次匹配项缓存中
$lastMatch[1] = $regs[1][$i];
$lastMatch[2] = $regs[2][$i];
$lastMatch[3] = $regs[3][$i];
}

// 返回所有匹配项
return $return;
}

?>

我知道,它并不优雅,但我希望它对一些人有用。
-1
einhverfr at not-this-host dot hotmail dot com
21 年前
您可能会发现,在复杂的项目中,为您的类使用命名空间并以分层方式安排它们会很有帮助。一种简单的方法是使用文件系统来排序您的层次结构,然后定义一个这样的函数

function use_namespace($namespace){

require_once("namespaces/$namespace.obj.php");

}

(由于此页面的 HTML UI,缩进不足)
这要求您所有对象库都以 .obj.php 结尾(我使用的是这个),但您可以根据需要修改它。要调用它,例如,您可以调用

use_namespace("example");
或者,如果 foo 是 example 的一部分,您可以调用
use_namespace("example/foo");
-3
pascal dot poncet at netconsult dot com
18 年前
主题:在 MySQL 查询中使用“sql_calc_found_rows”,同时在 PHP 数据库类对象中利用结果。

您好,

MySQL 中有一个很好的函数,它允许知道如果未设置“where”子句,将返回多少条记录:SQL_CALC_FOUND_ROWS。

如果您创建了一个数据库对象来收集返回的行,那么在尝试调用此函数的结果时,您会有点困惑。

为什么呢?
仅仅因为返回的字段名称是“found_rows()”,显然不可能调用类似于

<?php $result->found_rows() ?>

...因为它试图访问一个方法,而不是一个属性!

然后,唯一获得正确结果的方法似乎是使用类函数,例如

<?php
$db
->query("select found_rows()");
$count=current(get_object_vars(current($db->result)));
?>

当然,如果有人找到了其他解决方法,比如特殊的语法(参见在字符串中使用卷曲数组的语法),我很乐意讨论。

祝你好运!
Pascal
-4
ahigerd at timeips dot com
16 年前
要访问名称中包含非法字符的对象成员,请使用以下语法

$obj->{'illegal-property:name()'}

这与数据库对象和 SoapClient 类使用的动态生成类特别相关。
-4
Skydev
13 年前
一个小函数,允许查找所有对对象的引用。 在 3 分钟内编写,可能存在错误(例如,在某些地方将对象作为引用传递?)。

<?php
function find_ref_obj($object, $obj, $path) {
if (
in_array($obj,$GLOBALS['__REF_CHECKED'],true))
return
false;
$GLOBALS['__REF_CHECKED'][]=$obj;
$r = array();
foreach ((array)
$obj as $k => $v) {
if (
$v === $object)
$r[] = $path . "->$k";
if (
is_object($v)) {
$t = find_ref_obj($object,$v,$path . "->$k");
if (
$t!==false)
$r=array_merge($r,$t);
}
else if (
is_array($v)) {
$t = find_ref_arr($object,$v,$path . "->$k");
if (
$t!==false)
$r=array_merge($r,$t);
}
}
if (empty(
$r))
return
false;
else
return
$r;
}
function
find_ref_arr($object, $arr, $path) {
if (
in_array($arr,$GLOBALS['__REF_CHECKED'],true))
return
false;
$GLOBALS['__REF_CHECKED'][]=$arr;
$r = array();
foreach (
$arr as $k => $v) {
if (
$v === $object)
$r[] = $path . "['$k']";
if (
is_object($v)) {
$t = find_ref_obj($object,$v,$path . "['$k']");
if (
$t!==false)
$r=array_merge($r,$t);
}
else if (
is_array($v)) {
$t = find_ref_arr($object,$v,$path . "['$k']");
if (
$t!==false)
$r=array_merge($r,$t);
}
}
if (empty(
$r))
return
false;
else
return
$r;
}
function
find_references($object) {
$r = array();
$GLOBALS['__REF_CHECKED']=array();
foreach (
$GLOBALS as $n => $v)
if (
$n!='__REF_CHECKED')
if (
$n!='GLOBALS') {
if (
$v === $object)
$r[]=$n;
if (
is_object($v)) {
$t = find_ref_obj($object,$v,$n);
if (
$t!==false)
$r=array_merge($r,$t);
}
else if (
is_array($v)) {
$t = find_ref_arr($object,$v,$n);
if (
$t!==false)
$r=array_merge($r,$t);
}
}
unset(
$GLOBALS['__REF_CHECKED']);
return
$r;
}

function
find_refs($object) {
return
implode(', ',find_references($object));
}
?>
-4
HOC
20 年前
致 pillepop2003

为什么要知道一个不存在对象的类名?

我唯一能想到的解释是你想要在实例化对象之前知道类名。 嗯,这毫无用处,因为你总是实例化一个你选择的类。

当类被实例化为一个对象时,你可以通过 get_class() 方法找到对象的类。 这就够了。 在继承的情况下,你可以使用 get_class($this) 来获取实例化对象的类。 现在,你可以根据对象所属的类进行区分。

例如:

<?php
class A{
function
A(){
$class_of_this = get_class($this);
echo
'Object is an instance of class '.$class_of_this.' which is the ';
if(
strcmp($class_of_this,'A')==0)
echo
'parent-class';
else if(
strcmp($class_of_this,'B')==0)
echo
'child-class';
echo
".\n";
}
}

class
B extends A{
function
B(){
$this->A();
}
}

$object1 = new A();
$object2 = new B();
?>

当你运行这段代码时,输出将是

Object is an instance of class A which is the parent-class.
Object is an instance of class B which is the child-class.
-3
zabmilenko at hotmail dot com
19 年前
((PHP5))

我想为一个类动态选择一个扩展。 这花了我一段时间,但我找到了解决方案。 注意,我无法验证它的安全性,但它对我来说似乎有效。 也许其他人可以阐明细节。

<?php

class A { var $value = "类 A\n"; }
class
B { var $value = "类 B\n"; }

// 取消对您想要使用的扩展程序的注释。您也可以使用变量。
// define('__EXTENDER__', 'A');
define('__EXTENDER__', 'B');

// 使用 eval 创建一个包装类。
eval('class EXTENDER extends '. __EXTENDER__ . ' { }');

class
C extends EXTENDER
{
function
__construct()
{
echo
$this->value;
}
}

$t = new C;

?>

输出:类 B

实际应用:我有一个数据库抽象系统,它对 mysql、pgsql 等有单独的类。我想能够创建一个全局 db 类,该类扩展一个单独的 db 类,具体取决于应用程序配置。

我知道可能还有更好的方法来做到这一点,但我还没有达到在类方面达到那种水平。
-4
justin at quadmyre dot com
21 年前
如果您想能够从另一个类中调用一个类的实例,您只需将对外部类的引用存储为本地类的属性(可以使用构造函数将此传递给类),然后像这样调用外部方法

$this->classref->memberfunction($vars);

或者,如果双“->”对您来说太奇怪了,那么试试这个

$ref=&$this->classref;
$ref->memberfunction($vars);

这在您编写类似通用 SQL 类的东西时非常有用,您希望其他类中的成员函数能够使用它,但希望保持命名空间分离。希望对某些人有所帮助。

贾斯汀

示例

<?php

class class1 {
function
test($var) {
$result = $var + 2;
return
$result;
}
}

class
class2{
var
$ref_to_class=''; # 指向其他类的指针

function class1(&$ref){ # 构造函数
$this->ref_to_class=$ref; # 将对其他类的引用保存为该类的属性
}

function
test2($var){
$val = $this->ref_to_class->test($var); # 使用引用调用其他类
return $val;
}
}

$obj1=new class1;
# 实例化 obj1。
$obj2=new class2($obj1);
# 在实例化 obj2 时传递对 obj1 的引用

$var=5;
$result=obj2->test2($var);
# 调用 obj2 中的方法,该方法调用 obj1 中的方法
echo ($result);

?>
-7
iparanoid at gmx dot de
20 年前
致 pillepop2003 at yahoo dot de

在我看来,如果真的没有好的方法来获取未实例化类中的类名,那么在 PHP5 中可以使用静态/类变量作为一种变通方法。

示例

<?php

class myFoo
{
static
$__ClassName = __CLASS__;

static function
getClassName()
{
return
myFoo::$__ClassName;
}
};

class
myFooExtended extends myFoo
{
function
__construct()
{
myFooExtended::$__ClassName = __CLASS__;
};
};

?>

但是,您需要至少实例化一个 myFooExtended 类的对象才能调用 getClassName 或引入其他初始化(类变量需要在子类中的某个点设置为 __CLASS__)。
-4
greg at doutromundo dot com
20 年前
作为程序员,你们可能比我更有条理,但是,我确实尝试在我的类和代码中保持一定的秩序,并将它们分离到“包”中,就像在 java 中一样。
这有助于我保持条理,但在尝试使用它们时造成了混乱,所以我所做的是创建一个类来处理类的加载(我在所有页面中都实例化了它),以及我所有的错误处理类,它们都被捆绑在一起。这样,我就可以使用类似以下命令加载我的类
$baseClass->loadClass("package","className"[,"constructor"]);

负责此操作的函数有一些检查以查看它们是否已加载等等...

function loadClass($packageName,$className,$constructor=""){
// 如果您没有构造函数,请在类中声明任何函数
// 类
if ($constructor==""){
$constructor=$className;
}
if(!is_callable(array($className,$constructor))){
if (defined("CLASS_DIR")){
$pkg = CLASS_DIR.$packageName."/";
if (is_dir($pkg)){
// 我们有一个包含包名的目录
$cls = $pkg.$className.".class.php";
if(is_file($cls)){
// 我们有一个文件
include_once($cls);
}else{
die("无法在包 <b>$packageName</b> 中找到类 <b>$className</b>,请检查您的安装");
}
}else{
die("无法找到包 <b>$packageName</b>,请检查您的安装");
}
}
}
}

请记住将 CLASS_DIR 定义为包含您包的目录的物理路径...

希望这能派上用场...

以下是一个目录结构的示例...
/var/www/classes/ <- 这将是 CLASS_DIR
在那里我有
package1/
name.class.php
name2.class.php
....

loadClass 将如下所示:loadClass("package1","name");

既可爱又简单
-6
ar at 5mm de
20 年前
我错过了某种函数,用于动态覆盖或扩展对象

-----------------------------------------
function &extendObj(&$obj, $code) {
static $num = 0;

$classname = get_class($obj);
$newclass = $classname.$num;

eval('class '.$newclass.' extends '.$classname.' { '.$code.' }');

$newobj = new $newclass();

$vars = get_class_vars($classname);
foreach($vars AS $key=>$value) {
$newobj->$key = &$obj->$key;
}

return $newobj;
}
-----------------------------------------

这将创建一个新的类,该类通过给定的代码参数扩展旧类,实例化它并将所有变量从旧 obj 复制到新 obj。

-----------------------------------------
class testA {
var $prop = 'a';

function funcA($val) {
$this->prop = $val;
}

function value() {
return $this->prop;
}
}

$obj = new testA();

$newobj = &extendObj(&$obj, 'function addX() { $this->prop .= "x"; }');

$newobj->funcA('abc');
$newobj->addX();
echo $newobj->value();
-----------------------------------------

结果为“abcx”。您可以多次使用该函数,也可以与类变量一起使用。小心,即使 $newobj 只是 $obj 的副本,$obj->value() 也将返回“abcx”,因为使用了 & 运算符:$newobj->$key = &$obj->$key;
-5
cjones
19 年前
如果有人有兴趣寻找一种方法将现有的对象动态加载到类中,以下是我发现非常有用的方法。

//---------------------------------------------------------
// 将外部对象动态加载到类中

function objRef ( &$obj ) {
eval("\$this->obj_".get_class($obj)." = \$obj;");
}
//---------------------------------------------------------
// 使用以下方式引用:$this->obj_[对象名称]->[var|f{}]

示例

class date { function date ( ) { $this->date = "3 月 3 日"; } }
class time { function time ( ) { $this->time = "下午 12:30"; } }

class show {
function objRef ( &$obj ){
eval("\$this->obj_".get_class($obj)." = \$obj;");
}
function test ( $var ){
echo "$var".$this->obj_date->date." @ ".$this->obj_time->time;
}
}

$date = new date;
$time = new time;
$show = new show;
$show->objRef($date);
$show->objRef($time);
$show->test("现在的时间 => ");

// 输出:现在的时间 => 3 月 3 日 @ 下午 12:30

我发现类名前缀“obj_”非常有用,因为它有助于我在扫描脚本时自动识别外部对象引用。如果您愿意,可以省略它。希望对某些人有所帮助。
-4
ia [AT] zoznam [DOT] sk
19 年前
对于 zabmilenko 的解决方案
用这种方式创建它会更好吗?

<?php
// 所有数据库类的基类
class DB {
protected
$connectId;
}

// MySQL 类,继承自基类
class MySQL extends DB {
function
connect () {
$this->connectId = mysql_connect (...);
}
}

// PostgreSQL 类,继承自基类
class pgSQL extends DB {
function
connect () {
$this->connectId = pg_connect (...);
}
}

// 然后像这样调用构造函数:
$dbName = "MySQL";
$db = new $dbName ( ... );
// ... 这将创建一个 MySQL 类的对象
?>
To Top