我有一个TelegramUser
扩展了Model
的两个简单的相同功能:
public function toString() {
if ($this->telegram_first_name != null) {
return $this->telegram_first_name;
} else if ($this->telegram_username != null) {
return $this->telegram_username;
}
}
public function getDisplayName() {
if ($this->telegram_first_name != null) {
return $this->telegram_first_name;
} else if ($this->telegram_username != null) {
return $this->telegram_username;
}
}
如果我从类外部(例如$telegramUser->toString()
)调用toString方法,那么一切都会按预期工作,但是如果我从TelegramUser
模型内部调用toString,则会发生这种情况:
local.ERROR: LogicException: App\TelegramUser::toString must return a relationship instance. in webapp/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:416
Stack trace:
#0 webapp/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php(399): Illuminate\Database\Eloquent\Model->getRelationshipFromMethod('toString')
#1 webapp/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php(329): Illuminate\Database\Eloquent\Model->getRelationValue('toString')
#2 webapp/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(1519): Illuminate\Database\Eloquent\Model->getAttribute('toString')
#3 webapp/app/TelegramUser.php(79): Illuminate\Database\Eloquent\Model->__get('toString')
这是TelegramUser模型中的函数,我在其中调用toString函数:
public function giftableKarma($chatId, $karmaType, $karmaCount) {
Log::debug("$this->toString() wants to donate $karmaCount unit(s) of $karmaType->name");
...
}
试图将toString放在字符串之外,如下所示:
Log::debug($this->toString() . " wants to donate $karmaCount unit(s) of $karmaType->name");
导致相同的错误。
这就是为什么我定义了getDisplayName
的原因,只有当我将其放在字符串之外时,它们才起作用。
Log::debug($this->getDisplayName() . " wants to donate $karmaCount unit(s) of $karmaType->name");
很高兴能够工作并记录用户的名字或用户名,同时:
Log::debug("$this->getDisplayName() wants to donate $karmaCount unit(s) of $karmaType->name");
将导致相同的LogicException
错误,这一次显然是指getDisplayName“ attribute”
所以我的两个问题是:
toString
方法在类外部调用代码时起作用,而在giftableKarma
方法内部不起作用?非常感谢!
答案 0 :(得分:0)
我认为您所看到的错误与在类外部或类内部调用函数无关,而与PHP字符串解析和Laravel的魔术方法无关。
PHP's string parsing允许您插入变量名,但不能插入函数。换句话说,如果您执行以下操作:"$this->toString()"
PHP将认为您的变量名称是$this->toString
,而不是$this->toString()
。
因此,当您像这样使用它时,它将尝试访问名为toString
的类属性,而不是执行名为toString()
的方法。
在Laravel中,模型具有一种神奇的方法(__get()
),该方法可以动态解析模型属性和关系,从而可以使用$mymodel->myattribute
,而不必显式定义该属性在课堂上。因此,当您尝试调用$this->toString
(不带括号)时,Laravel首先查看该模型是否具有名为toString
的属性,如果是,则返回其值。如果不是,它将寻找一个名为toString()
的函数,并期望它定义一个关系。最后一件事是您正在发生的事情。
我不会使用toString
作为方法名称,因为它与称为__toString()
的魔术方法太接近了,该方法允许您定义类到字符串的隐式转换(Laravel实际上已经在Model类中对此进行了定义。)
对于您的特定问题,如果您想在字符串中使用该值,则可以通过用大括号将其包围来解决字符串解析限制(这是建立避免混淆的好习惯):
Log::debug("{$this->toString()} wants to...");
另外,Laravel中的一个漂亮功能是virtual accessor,您可以这样定义它:
public function getDisplayNameAttribute() {
if ($this->telegram_first_name != null) {
return $this->telegram_first_name;
} else if ($this->telegram_username != null) {
return $this->telegram_username;
}
}
您基本上定义了一个以get
开头并以Attribute
结尾的函数,Laravel神奇地将其映射到您所插入的任何单词,因此您可以像原生属性一样访问它。 / p>
然后,您可以执行以下操作:
Log::debug("$this->displayName wants to...");
它应该可以工作。