我有兩個子類,我想從另一個子類中呼叫一個方法。是開始按依賴順序鏈接我的類的唯一解決方案嗎?很抱歉這個菜鳥 PHP 問題。基本上,擁有多個“基”類(例如電子郵件類)是一個常見的場景,其他子類需要訪問其中的其他子類。所以你才開始鏈接它們嗎?
// BaseClass.php
require_once("./services/checkout.php");
require_once("./services/email.php");
class Base {
// ...
}
// checkout.php
class checkout extends Base {
public function onCheckout() {
// Call send email
$this->sendEmail($email); // <- How to do this?
}
}
// email.php
class email extends Base {
public function sendEmail($email) {
// Send email
}
}
uj5u.com熱心網友回復:
我認為擁有BaseAction或BaseController沒有像BaseClass. 有類似的東西感覺更直觀:
class Checkout
{
public function onCheckout(Mailer $mailer)
{
$mailer->sendEmail($email);
}
}
class Mailer
{
public function sendEmail($email)
{
// Send email
}
}
這還是很粗糙的。您很可能想要一個介面,注入到checkout建構式中,也許是使用一些實作自動裝配的依賴注入庫自動注入:
interface MessengerInterface
{
public function send(string $text): bool;
}
class Checkout
{
public function __construct(
private MessengerInterface $messenger
) {
}
public function onCheckout()
{
$this->messenger->send('Your order blah blah');
}
}
class Mailer implements MessengerInterface
{
public function send(string $body): bool
{
// Send email
}
}
uj5u.com熱心網友回復:
這里的關鍵詞是“組合與繼承”。
繼承表示“is-a”關系。您可能會說 anHTMLEMail 是一個 Email- 它是同一類事物,但具有額外或不同的行為。Checkout 但是說是一個是 沒有意義的Emailer——它們是兩個不同的東西,也不是另一個的型別。
組合代表一種“有”的關系。ACheckout可能有一個 Emailer,它用于發送電子郵件。所以它們是你“組合”在一起的不同類。這基本上意味著,而不是$this->sendEmail(),你會寫$emailer->sendEmail(),$emailer另一個來自某個地方的物件在哪里。
實作“組合”最簡潔的方法是通過“依賴注入”,這主要是一種“將物件傳遞給其他物件”的奇特方式。
這可能會將其傳遞給單個方法:
class Checkout extends Base {
public function doCheckout($emailer) {
// Call send email
$emailer->sendEmail('[email protected]', 'Hello');
}
}
更靈活,因為您可能希望在多個方法中使用,將其傳遞給建構式并將其存盤在屬性中:
class Checkout extends Base {
private Emailer $emailer;
public function __construct(Emailer $emailer) {
$this->emailer = $emailer;
}
public function doCheckout() {
// Call send email
$this->emailer->sendEmail('[email protected]', 'Hello');
}
}
建構式中的這種屬性設定非常普遍,以至于 PHP 8 有一個特殊的簡稱,稱為“建構式屬性提升”:
class Checkout extends Base {
// note the "private" keyword next to the argument
public function __construct(private Emailer $emailer) {
}
public function doCheckout() {
// Call send email
$this->emailer->sendEmail('[email protected]', 'Hello');
}
}
更靈活的是,你可以依賴一個interface,這意味著“任何具有正確行為的東西都可以在這里傳遞,我稍后會決定確切的實作”。
The idea is that you can write the Checkout class without knowing what the inside of the Emailer class is going to look like. You just need to know that sendEmail requires certain arguments, and returns certain things when it's done. Then you can have one implementation that uses a username and password to talk to an SMTP server, one implementation that uses an API key to use a web service, and a third that just logs to a local file for test purposes. The Checkout class doesn't need to know how to create each one, or when to use them, it just waits for one to be provided.
Somewhere else, you have some co-ordinating code that actually knows how to create all these objects. The fancy way to do this in a larger project is with a library like PHP-DI that uses configuration and "auto-wiring" to work out what's needed when, but a simple version just looks like this:
$config = parse_config_file('config.ini');
if ( $config['mode'] === 'debug' ) {
$emailer = new DebugEmailer($config['logfiles']['email_debug']);
}
else {
$emailer = new SMTPEmailer($config['smtp']['username'], $config['smtp']['password']);
}
$checkout = new Checkout($emailer);
$checkout->doCheckout();
uj5u.com熱心網友回復:
請閱讀 PHP 中的特征。看來這對您的目標來說是正確的:
PHP 特征 (php.org)
PHP-Traits(W3Schools - 更容易理解)
我建議重新考慮您的繼承,無論 E-Mail 類和 Checkout-Class 從同一個基類繼承是否有意義。他們應該自己做完全不同和獨立的事情。如果您想從結帳類發送電子郵件,請嘗試實作一個電子郵件類并將其實體注入結帳物件。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/441389.html
上一篇:具有用戶名和密碼的關聯陣列
