معلمات PHP حسب المرجع والقيمة الافتراضية الخالية

StackOverflow https://stackoverflow.com/questions/280385

  •  07-07-2019
  •  | 
  •  

سؤال

لنفترض أن لدينا توقيع طريقة مثل

public static function explodeDn($dn, array &$keys = null, array &$vals = null,
    $caseFold = self::ATTR_CASEFOLD_NONE)

يمكننا بسهولة استدعاء الطريقة عن طريق حذف جميع المعلمات بعد ذلك $dn:

$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com');

يمكننا أيضًا استدعاء الطريقة بثلاثة معلمات:

$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, $v);

ومع 4 معلمات:

$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, $v, 
    Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER);

ولكن لماذا من المستحيل استدعاء الطريقة باستخدام مجموعة المعلمات التالية على سبيل المثال:

$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, null, 
    Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER);
$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', null, $v);

ما الفرق بين المرور null إلى الأسلوب والاعتماد على القيمة الافتراضية؟هل هذا القيد مكتوب في الدليل؟هل يمكن التحايل عليه؟

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

المحلول

وانها لأنك لا يمكن أن يكون إشارة إلى قيمة خالية.

هل يمكن أن يكون إشارة إلى متغير يحتوي على قيمة خالية - وهذا هو بالضبط ما تفعله القيمة الافتراضية. أو يمكنك تمرير في اغيا باعتباره قيمة حرفية - ولكن منذ كنت تريد المعلمة خارج هذا غير ممكن هنا

نصائح أخرى

وبينما يجب عليك إنشاء متغير وهمية لكل الحجج المرجع إذا كنت تريد تمرير NULL صراحة، لم يكن لديك لإنشاء هذا المتغير في سطر منفصل. يمكنك استخدام تعبير مهمة مثل $ دمية = NULL مباشرة كحجة وظيفة:

function foo (&$ref = NULL) {

    if (is_null($ref)) $ref="bar";
    echo "$ref\n";        
}

foo($dummy = NULL); //this works!

ولقد اكتشفت ذلك بنفسي، وأنا تماما في حالة صدمة O_O!

وهذا هو ما PHP الوثائق يقول:

function makecoffee($type = "cappuccino")
{
    return "Making a cup of $type.\n";
}
echo makecoffee(); // returns "Making a cup of cappuccino."
echo makecoffee(null); // returns "Making a cup of ."
echo makecoffee("espresso"); // returns "Making a cup of espresso."

وكنت أتوقع makecoffee(null) العودة "صنع فنجان من الكابوتشينو". عمل حول واحدة ولقد استخدمت للتحقق داخل وظيفة إذا كانت الوسيطة فارغة:

function makecoffee($type = null)
{
    if (is_null($type)){ 
       $type = "capuccino";
    }
    return "Making a cup of $type.\n";
}

والآن makecoffee(null) عوائد "صنع فنجان من الكابوتشينو".

(وأنا أدرك هذا لا يحل في الواقع مسألة تتعلق زند، ولكن قد يكون من المفيد لبعض ...)

و @Tomalak

والواقع، القيمة الافتراضية يخلق متغير دون أي إشارة المعنية. وهو أمر كنت ببساطة لا يمكن أن تنطلق عند تمرير شيء ما.

ما أجد لتوضيح الأسباب هو المثال التالي (التي لم أكن اختبار):

function foo (&$ref = NULL) {
  $args = func_get_args();
  echo var_export($ref, TRUE).' - '.var_export($args, TRUE);
}
$bar = NULL;
foo();     // NULL - array()
foo($bar); // NULL - array(0 => NULL)

في رأيي، يجب PHP توفر وسيلة لعدم تمرير معايير معينة، مثل مع
foo($p1, , , $p4); أو بناء جملة مماثل بدلا من تمرير NULL.
ولكن لم يحدث ذلك، ولذلك عليك أن تستخدم متغيرات وهمية.

وفقط لتأكيد ما Tomalak قال <وأ href = "https://stackoverflow.com/questions/280385/ فب-ب-المرجع معلمات والافتراضية لاغية # 280397 "> هنا :

والأعمال التالية:

$k=array();
$v=null;
$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, $v, 
    Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER);

وليس لطيفا - ولكن التفسير واضحا ومفهوما

كما أشار @aschmecher في تعليق علىإجابة @ Szczepan هنا, ، عمل func($var = null) يولد إشعار معايير صارمة.

حل واحد

إليك طريقة لا تولد أي تحذيرات من هذا القبيل:

<?php
error_reporting(E_ALL | E_STRICT);

function doIt(&$x = null) {
    if($x !== null) echo "x not null: $x\n";
    $x = 2;
}

function &dummyRef() {
    $dummyRef = null;
    return $dummyRef;
}

doIt(dummyRef());

doIt(dummyRef());

توضيح

بدلًا من تمرير متغير، نقوم بتمرير نتيجة دالة تُرجع مرجعًا.النداء الثاني ل doIt(dummy()) هو التحقق من أن المرجع $dummy القيمة لا تستمر بين المكالمات.يتناقض هذا مع إنشاء متغير بشكل صريح، حيث يحتاج المرء إلى تذكر مسح أي قيمة متراكمة:

$dummyRef = null;
doIt($dummyRef);
doIt($dummyRef); // second call would print 'x not null: 2'

طلب

لذلك في مثال OP، سيكون:

$dn = Zend_Ldap_Dn::explodeDn(
    'CN=Alice Baker,CN=Users,DC=example,DC=com',
    $k,
    dummyRef(),
    Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER
);

اعتبارات إضافية

الشيء الوحيد الذي قد يثير قلقي هو ما إذا كانت هذه الطريقة تؤدي إلى حدوث تسرب للذاكرة.ويبين الاختبار التالي أنه لا:

<?php
function doItObj(&$x = null) {
    if(gettype($x) !== "object") echo "x not null: $x\n";
    $x = 2;
}

function &dummyObjRef() {
    $dummyObjRef = new StdClass();
    return $dummyObjRef;
}

echo "memory before: " . memory_get_usage(true) .  "\n";

for($i = 0; $i < 1000000; $i++) {
    doItObj(dummyObjRef());
}

echo "memory after: " . memory_get_usage(true) . "\n";

echo "\n$i\n";

على نظامي (باستخدام PHP 5.6.4)، أظهر كلا الاستدعاءين إلى Memory_get_usage حوالي 262 كيلو بايت.

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