سؤال

سياق الكلام

  • PHP 5.3.x.

ملخص

بعد إجراء استعراض كود مع شريك يستخدم كل من PHP و Ruby بشكل روتيني، جاء تحدي متعة على الاستيفاء السلسلة في PHP مقارنة ب Ruby.

سؤال

افترض اللون = "برتقالي"؛

روبي:

puts("My favorite color is #{color.downcase() + 'ish'} -- at least for now.");

بي أتش بي:

print("My favorite color is {strtolower( $color ) + 'ish'} -- at least for now.");

تحد: هل يمكن لأي شخص تحديد طريقة للحصول على إصدار PHP يتصرف مثل Ruby؟

مذكرة قانونية

يهدف هذا التحدي إلى ممارسة ممتعة مع ضيق استخدام PHP مستقيم فقط. هذا غير مخصص لمشاريع PHP خطيرة. بالنسبة لمشاريع PHP الخطيرة، سيرغب المطور في النظر في مكتبات Addon، مثل غصين.

هل كانت مفيدة؟

المحلول

لا يمكنك استدعاء وظائف عادية داخل سلاسل من هذا القبيل، ولكن يمكنك اقناع المحلل في القيام بأشياء غريبة:

<?php
print "{$a->b()}"; // Works

//Parse error: syntax error, unexpected '(' in Command line code on line 1
print "${time()}";

print "${$a=time()} $a"; // Also works: prints "1234380996"
?>

طالما أنه يرى متغيرا صالحا في البداية، فسوف يمضي قدما ويقبط بيانا بأكمله دون شكوى.

بالنسبة لأولئك الذين كانوا يتساءلون، نعم، هذا يعمل أيضا ...

<?php
print "${$a or print shell_exec('ls')}";
?>

نصائح أخرى

أنت قريب، يمكنك تضمين المتغيرات في السلاسل، ولكن لا تعمل المكالمات.

أنا أستعمل printf()sprintf()) لذلك، وهو مجمع رقيق حول وظيفة C نفس الاسم:

printf('My favorite color is %sish -- at least for now.', strtolower( $color ));

أنظر لهذا %s هناك؟ هذا هو العنصر النائب لنوع بيانات السلسلة التي تمر كوسيطة 2nd.

sprintf() يعمل بنفس الطريقة، لكنها ترجع السلسلة المنسقة بدلا من طباعة ذلك.

الخيارات الأخرى الوحيدة هي:

أ. إجراء مكالمات الوظيفة أولا وتعيين النتيجة النهائية إلى المتغير:

$color = strtolower( $color );
print("My favorite color is {$color}ish -- at least for now.");

ب. باستخدام سلسلة، وهو IMO القبيح قليلا:

print('My favorite color is ' . strtolower( $color ) . 'ish -- at least for now.');

ربما لاحظت استخدامي للنقلات الفردية (AKA Res)، ونقلت مزدوجة.

في PHP، يتم تحليل الحرفيين داخل اقتباسات مزدوجة للمتغيرات، كما ترون في "A" أعلاه.

لا يتم تحليل حرفي داخل اقتباسات واحدة. لهذا السبب، فهي أسرع. يجب عليك، كقاعدة عامة، استخدم فقط اقتباسات مزدوجة حول حرفي عندما يكون هناك تحليل متغير.

'My favorite color is ' . strtolower( $color ) . 'ish-- at least for now.'

لا أعتقد أن PHP يدعم التعبيرات الكاملة المحمولة في سلاسل. كان بعض الوقت منذ أن فعلت أي php على الرغم من.

إذا كان هذا هو شيء يذهب ....

class ColorIsh {
    var $color;

    function __constructor($color) { $this->color = $color; }
    function __get($prop) {
        if ($prop == 'ish') {
            // code here fixing suffix if needed
            return strtolower($this->color) . 'ish';
        }
        return '';
    }
    function __set($prop) {}
}

$color = new ColorIsh("orange");
$str = "My favorite color is $color->ish -- at least for now.";

والنسخة المتقدم فرط

class ColorIsh {
    private $color;

    function __constructor($color) {$this->color = $color; }
    function __get($prop) {
        if ($prop == 'color') 
            return $this->color;
        if ($prop == 'ish')
            return isset($this->ish) ? $this->ish : $this->color . 'ish';
        return false;
    }
    function __set($prop, $value) {
        if ($prop == 'color') { $this->color = $value; unset($this->ish); }
        if ($prop == 'ish') { $this->ish = $value; }
    }
}

$color = new ColorIsh('orange');
$color->ish = 'orangish';
print "The color is kinda $color->ish";
$color->color = 'green';
print "The color is kinda $color->ish";

output:
The color is kinda orangish.
The color is kinda greenish.

ليس ذلك جميلا، ولكن يمكنك استخدام وظيفة مجهولة.

$e = function($val) { return $val; };
$foo = 'foo';
echo "Uppercase foo = {$e(strtoupper($foo))}";

عادة ما تحتوي مشاريعي على وظيفة المساعد التي ترجع الوظيفة المجهولة أعلاه، لذلك لا يحتاج إلى إعادة إنشائها في كل مرة.

function returner() {
    static $returner;

    if (!$returner) {
        $returner = function($val) {
            return $val;
        };
    }

    return $returner;
}

$e = returner();

غير ممكن. ولكن إذا كنت تصر حقا، يمكنك دائما إنشاء فئة سلسلة مع واجهة بطلاقة ... ولكن هذا مجنون :)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top