سؤال

وكنت أقرأ مؤخرا هذا الموضوع أو على بعض من أسوأ الممارسات PHP. في الجواب الثاني هو نقاش صغيرة على استخدام extract()، وايم فقط أتساءل ما هو كل زعل عنه.

وأنا شخصيا استخدامه لتقطيع مجموعة معينة مثل $_GET أو $_POST حيث I ثم تطهير المتغيرات في وقت لاحق، كما تم تسميتها مريح بالنسبة لي.

هل هذه الممارسة السيئة؟ ما هي مخاطر هنا؟ ما هي أفكارك حول استخدام extract()؟

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

المحلول

وأجد أنه هو ممارسة سيئة فقط لأنه يمكن أن يؤدي إلى عدد من المتغيرات التي مشرفون في المستقبل (أو نفسك في غضون بضعة أسابيع) ليس لديهم فكرة عن المكان الذي يأتون منه. النظر في هذا السيناريو:

extract($someArray); // could be $_POST or anything

/* snip a dozen or more lines */

echo $someVariable;

وأين $someVariable تأتي من؟ كيف يمكن لأحد أن يقول؟

وأنا لا أرى مشكلة في الوصول إلى المتغيرات من ضمن مجموعة بدأوا في، لذلك كنت بحاجة حقا الى تقديم حالة جيدة <م> ل باستخدام extract() بالنسبة لي أن أعتقد أنه يستحق ذلك . إذا كنت قلقا حقا حول كتابة بعض الأحرف الزائدة ثم مجرد قيام بذلك:

$a = $someLongNameOfTheVariableArrayIDidntWantToType;

$a['myVariable'];

وأعتقد التعليقات هنا على الجوانب الأمنية لأنها مبالغ فيها إلى حد ما. وظيفة يمكن أن تأخذ المعلمة الثانية التي تعطي في الواقع كنت مراقبة جيدة إلى حد ما على مدى المتغيرات التي أنشئت حديثا، بما في ذلك عدم الكتابة فوق أي المتغيرات الحالية (EXTR_SKIP)، الكتابة فقط المتغيرات الحالية (حتى تتمكن من إنشاء القائمة البيضاء) (EXTR_IF_EXISTS)، أو إضافة البادئات ل المتغيرات (EXTR_PREFIX_ALL).

نصائح أخرى

وهيا الآن. الناس اللوم الأداة بدلا من المستخدم.

وهذا مثل الحديث ضد unlink() لأنه يمكنك حذف الملفات معها. extract() هي وظيفة مثل أي دولة أخرى، واستخدامها بحكمة ومسؤولية. ولكن لا تدعي انها سيئة في حد ذاتها، وهذا مجرد جاهل.

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

<?php
    $systemCall = 'ls -lh';
    $i = 0;

    extract($_GET);

    system($systemCall);

    do {
        print_r($data[$i];
        $i++;
    } while ($i != 3);

?>

و(مثال لا معنى لها)

ولكن الآن المتطفلين الذين التخمينات أو يعرف رمز المكالمات:

yourscript.php?i=10&systemCall=rm%20-rf

وبدلا من

yourscript.php?data[]=a&data[]=b&data[]=c

والآن، $ systemCall و$ يتم الكتابة ط، مما أدى إلى السيناريو الخاص بك حذف البيانات الخاصة بك أولا والشنق ثم.

وليس هناك شيء خطأ في ذلك. وإلا فإنه لن يتم تنفيذها. العديد من (MVC) أطر استخدامها عند تمرير (تعيين) المتغيرات المشاهدات. كل ما تحتاجه لاستخدامها بعناية. تطهير تلك المصفوفات قبل تمريرها لاستخراج () والتأكد من أنها لا تجاوز المتغيرات الخاصة بك. لا ننسى أن هذه الوظيفة يقبل أيضا عدد قليل من أكثر الحجج! باستخدام الحجج الثانية والثالثة يمكنك التحكم في السلوك في حال حدوث تصادم. يمكنك تجاوز، تخطي أو إضافة البادئة. http://www.php.net/extract

إذا لم تستخدم بعناية يمكن الخلط بين هيك الآخرين كنت تعمل مع النظر فيما يلي:

<?php

    $array = array('huh' => 'var_dump', 'whatThe' => 'It\'s tricky!', 'iDontGetIt' => 'This Extract Function');
    extract($array);
    $huh($whatThe, $iDontGetIt);


?>

والعائد:

string(12) "It's tricky!"
string(21) "This Extract Function"

وسيكون من المفيد استخدام في التشويش. ولكن لا أستطيع الحصول على "أين أن فار تأتي من؟" المشكلة أنني واجهت.

والناس الحصول على كل شيء في السلاح حول استخراج لأنه لديه <م> إمكانات إلى أن يساء استخدامها. تفعل شيئا مثل استخراج ($ _ POST) ليست فكرة جيدة على أية حال، حتى لو كنت تعرف ما تقومون به. ومع ذلك، فإنه لا يكون ذلك هو يستخدم عند القيام بأشياء مثل تعريض المتغيرات إلى قالب عرض أو شيئا من هذا القبيل. في الأساس، واستخدام فقط عندما كنت متأكدا جدا أن يكون لديك سبب وجيه للقيام بذلك، وفهم كيفية استخدام المعلمة استخراج نوع اذا كان لديك فكرة تمرير شيء مجنون مثل _POST $ لذلك.

واعتقد ان السبب الكثير من الناس لا ننصح باستخدامه هو أن استخراج $_GET و$_POST (حتى $_REQUEST) superglobals المتغيرات سجلات في مساحة الاسم العالمي مع نفس اسم كل مفتاح ضمن تلك المصفوفات، وهو محاكاة أساسا REGISTER_GLOBALS = 1.

وأنني سأترك دليل PHP تفعل نتحدث عن لي.

والخلفية: extract($_REQUEST) هو نفس وضع register_globals = On في ملف php.ini

إذا استخراج في وظيفة، وسوف تكون المتغيرات المتاحة في هذا النطاق فقط. وكثيرا ما يستخدم هذا في وجهات النظر. مثال بسيط:

//View.php
class View {
    function render($filename = null) {
        if ($filename !== null) {
            $this->filename = $filename;
        }
        unset($filename);
        extract($this->variables);
        ob_start();
        $this->returned = include($this->dir . $this->filename);
        return ob_get_clean();
    }
}

//test.php
$view = new View;
$view->filename = 'test.phtml';
$view->dir = './';
$view->variables = array('test' => 'tset');
echo $view->render('test.phtml');
var_dump($view->returned);

//test.phtml
<p><?php echo $test; ?></p>

ومع بعض الدلائل بديلة، بالتحقق مما إذا كان الملف موجودا والمتغيرات وأساليب محددة - كنت قد تكرارها الى حد كبير Zend_View

ويمكنك أيضا إضافة <م> $ هذا-> outVariables = get_defined_vars ()؛. بعد التضمين لتشغيل التعليمات البرمجية مع variabels محددة والحصول على نتيجة لهذه للاستخدام مع رمز فب القديم

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

#Extract only the specified keys.
$extract=array_intersect_key(
    get_data()
    ,$keys=array_flip(['key1','key2','key3','key4','key5'])
);

#Make sure all the keys exist.
if ($missing=array_keys(array_diff_key($keys,$extract))) {
    throw new Exception('Missing variables: '.implode(', ',$missing));
}

#Everything is good to go, you may proceed.
extract($extract);

أو

#If you don't care to check that all keys exist, you could just do this.
extract(array_intersect_key(
    get_data()
    ,array_flip(['key1','key2','key3','key4','key5'])
));

والخطر هو نفسه كما هو الحال مع register_globals. تمكين المهاجم لضبط المتغيرات في السيناريو الخاص بك، ببساطة عن طريق العبث مع الطلب.

وأبدا استخراج ($ _ GET) في النطاق العالمي. بخلاف ذلك، فقد استخداماتها، مثل استدعاء دالة التي يمكن أن (يحتمل) لديك الكثير من الحجج اختياري.

وهذا يجب أن تبدو مألوفة غامضة للمطورين وورد:

function widget (Array $args = NULL)
{
    extract($args);

    if($before_widget) echo $before_widget;

    // do the widget stuff

    if($after_widget) echo $after_widget;
}

widget(array(
    'before_widget' => '<div class="widget">',
    'after_widget' => '</div>'
));

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

وهذا يخدم غرضا مزدوجا توثيق ما المتغيرات يخرجون منه حتى تتبع الظهر متغير لن يكون صعبا للغاية.

وكل استخدام أسلوب يمكن أن يؤدي إلى بعض الظروف حيث أنه يمكن أن يكون نقطة الفشل للتطبيق. وأنا شخصيا أشعر أن استخراج () لا ينبغي أن تستخدم لإدخال المستخدم (أي لا يمكن التنبؤ به) وبيانات غير مطهرة.

يستخدم

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

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

ويجب أن تدرك أن extract() ليس في مأمن إذا كنت تعمل مع بيانات المستخدم (مثل نتائج طلبات)، ولذلك فمن الأفضل لاستخدام هذه الوظيفة مع EXTR_IF_EXISTS الأعلام وEXTR_PREFIX_ALL.

إذا كنت تستخدم ذلك الحق، هو آمن للاستخدام

لمجرد شرح قليلا على الأجوبة السابقة ... لا يوجد شيء خاطئ مع استخراج () طالما تقوم بتصفية مساهمة بشكل صحيح (كما ذكر في الأخرى)؛ خلاف ذلك يمكنك في نهاية المطاف مع القضايا الأمنية ضخمة مثل هذا:

<?php

// http://foobar.doo?isLoggedIn=1

$isLoggedIn = (new AdminLogin())->isLoggedIn(); // Let's assume this returns FALSE

extract($_GET);

if ($isLoggedIn) {
    echo "Okay, Houston, we've had a problem here.";
} else {
    echo "This is Houston. Say again, please.";
}

واحد سبب وجيه إضافية دون استخراج استخدام أطول () هو أن هناك زخما في PHP لاستخدام HHVM حيث ويدعي أن يجعل PHP حول 10x اسرع. الفيسبوك (الذي جعل منه) واستخدامه، ويكيبيديا هي عليه، ويشاع ورد إلى أن تبحث في ذلك.

HHVM لا يسمح استخراج ()

وانها لا تزال نوع ألفا، حتى انها ليست أكبر قلق

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