لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 02/20/21 في كل الموقع
-
يُمكنك حذف جميع ملفات مُجلد بإستخدام التابع cleanDirectory على الواجهة: File بهذا الشكل: File::cleanDirectory("storage/app/public/products"); و سيُعطيك true في حالة تم الحذف أما إن كان المسار غير موجود سيُعطيك false. او بإمكانك إستخدام التالي أيضاً: use Illuminate\Filesystem\Filesystem; $fs = new Filesystem; $fs->cleanDirectory("storage/app/public/products"); أما إن أردت حذف مُجلد بكافة الملفات التي بداخله يُمكنك إستخدام التابع deleteDirectory بهذا الشكل: File::deleteDirectory("storage/app/public/products"); الفرق بين الطريقتين ان الأولى تحذف الملفات التي بداخل المُجلد فقط و تُبقي على المُجلد نفسه أما الثانية فتحذف المُجلد نفسه و ما بداخله. أما الطريقة التي تستخدمها فهي لحذف ملف واحد فقط بتمرير مساره للتابع delete كما يمكنك إستخدام نفس التابع لحذف مجموعة من الملفات بتمرير مسارات هذه الملفات في مصفوفة و بالتالي يُمكن إستخدام التابع allFiles لجلب الملفات الموجودة في مجلد ما على شكل مصفوفة و نُمررها للتابع delete بالشكل التالي: $files = Storage::allFiles("public/products"); Storage::delete($files); لاحظ أننا لم نمرر المسار بداية من app لأنه توابع الصنف Storage تنظر مباشرة داخل المجلد app و بالتالي إن قمت بتمريره في مسار الملف ستفترض أن هناك مجلد app داخل مُجلد app هكذا: storage/app/app2 نقاط
-
ترشِّح هذه الإضافة البيانات إما عن طريق تدقيقها أو تعقيمها (sanitizing)، ويعدّ هذا مفيدًا خاصةً عندما يتضمن مصدر البيانات بيانات غير معروفة (أو غريبة) مثل الدخل الذي يوفره مستخدم ما، قد تأتي هذه البيانات من نموذج HTML مثلًا. المعامل تفاصيل variable القيمة التي نريد ترشيحها، لاحظ أنّ القيم العددية تُحوَّل إلى سلاسل نصية داخليًا قبل أي ترشيح filter معرِّف المرشّح الذي نريد تطبيقه، تذكر صفحة أنواع المرشِّحات في توثيق PHP جميع المرشِّحات المتاحة، إذا تجاوزت هذا المعامل ستُستخدم افتراضيًا القيمة `FILTER_DEFAULT` والتي تكافئ القيمة `FILTER_UNSAFE_RAW`، مما يؤدي إلى عدم إجراء ترشيح بشكلٍ افتراضي options مصفوفة ترابطية من الخيارات أو عملية ثنائية OR على الرايات، إذا قَبِل المرشّح هذه الخيارات يمكن توفير الرايات في الحقل "flags" من المصفوفة. يجب تمرير نوع قابل للاستدعاء من أجل مرشِّح رد النداء، ويجب أن يقبل رد النداء وسيط واحد (القيمة التي نريد ترشيحها) ويعيد القيمة بعد ترشيحها/تعقيمها table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } التحقق من القيم المنطقية var_dump(filter_var(true, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // true var_dump(filter_var(false, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // false var_dump(filter_var(1, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // true var_dump(filter_var(0, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // false var_dump(filter_var('1', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // true var_dump(filter_var('0', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // false var_dump(filter_var('', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // false var_dump(filter_var(' ', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // false var_dump(filter_var('true', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // true var_dump(filter_var('false', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // false var_dump(filter_var([], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // NULL var_dump(filter_var(null, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // false التحقق من القيم العشرية يتحقق من القيمة على أنّها قيمة عشرية ويحوّلها إلى قيمة عشرية عند النجاح. var_dump(filter_var(1, FILTER_VALIDATE_FLOAT)); var_dump(filter_var(1.0, FILTER_VALIDATE_FLOAT)); var_dump(filter_var(1.0000, FILTER_VALIDATE_FLOAT)); var_dump(filter_var(1.00001, FILTER_VALIDATE_FLOAT)); var_dump(filter_var('1', FILTER_VALIDATE_FLOAT)); var_dump(filter_var('1.0', FILTER_VALIDATE_FLOAT)); var_dump(filter_var('1.0000', FILTER_VALIDATE_FLOAT)); var_dump(filter_var('1.00001', FILTER_VALIDATE_FLOAT)); var_dump(filter_var('1,000', FILTER_VALIDATE_FLOAT)); var_dump(filter_var('1,000.0', FILTER_VALIDATE_FLOAT)); var_dump(filter_var('1,000.0000', FILTER_VALIDATE_FLOAT)); var_dump(filter_var('1,000.00001', FILTER_VALIDATE_FLOAT)); var_dump(filter_var(1, FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var(1.0, FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var(1.0000, FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var(1.00001, FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1.0', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1.0000', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1.00001', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1,000', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1,000.0', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1,000.0000', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1,000.00001', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); الخرج: float(1) float(1) float(1) float(1.00001) float(1) float(1) float(1) float(1.00001) bool(false) bool(false) bool(false) bool(false) float(1) float(1) float(1) float(1.00001) float(1) float(1) float(1) float(1.00001) float(1000) float(1000) float(1000) float(1000.00001) التحقق من العنوان الفيزيائي (MAC Address) يتحقق من قيمة أنّها عنوان فيزيائي صحيح. var_dump(filter_var('FA-F9-DD-B2-5E-0D', FILTER_VALIDATE_MAC)); var_dump(filter_var('DC-BB-17-9A-CE-81', FILTER_VALIDATE_MAC)); var_dump(filter_var('96-D5-9E-67-40-AB', FILTER_VALIDATE_MAC)); var_dump(filter_var('96-D5-9E-67-40', FILTER_VALIDATE_MAC)); var_dump(filter_var('', FILTER_VALIDATE_MAC)); الخرج: string(17) "FA-F9-DD-B2-5E-0D" string(17) "DC-BB-17-9A-CE-81" string(17) "96-D5-9E-67-40-AB" bool(false) bool(false) تعقيم عناوين البريد الإلكتروني يحذف جميع المحارف باستثناء الأحرف والأرقام والمحارف !#$%&'*+-=?^_{|}~@.[]`. var_dump(filter_var('john@example.com', FILTER_SANITIZE_EMAIL)); var_dump(filter_var("!#$%&'*+-=?^_`{|}~.[]@example.com", FILTER_SANITIZE_EMAIL)); var_dump(filter_var('john/@example.com', FILTER_SANITIZE_EMAIL)); var_dump(filter_var('john\@example.com', FILTER_SANITIZE_EMAIL)); var_dump(filter_var('joh n@example.com', FILTER_SANITIZE_EMAIL)); الخرج: string(16) "john@example.com" string(33) "!#$%&'*+-=?^_`{|}~.[]@example.com" string(16) "john@example.com" string(16) "john@example.com" string(16) "john@example.com" تعقيم الأعداد الصحيحة يحذف جميع المحارف باستثناء الأرقام وإشارة الناقص والزائد. var_dump(filter_var(1, FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var(-1, FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var(+1, FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var(1.00, FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var(+1.00, FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var(-1.00, FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var('1', FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var('-1', FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var('+1', FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var('1.00', FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var('+1.00', FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var('-1.00', FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var('1 unicorn', FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var('-1 unicorn', FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var('+1 unicorn', FILTER_SANITIZE_NUMBER_INT)); var_dump(filter_var("!#$%&'*+-=?^_`{|}~@.[]0123456789abcdefghijklmnopqrstuvwxyz", FILTER_SANITIZE_NUMBER_INT)); الخرج: string(1) "1" string(2) "-1" string(1) "1" string(1) "1" string(1) "1" string(2) "-1" string(1) "1" string(2) "-1" string(2) "+1" string(3) "100" string(4) "+100" string(4) "-100" string(1) "1" string(2) "-1" string(2) "+1" string(12) "+-0123456789" تعقيم الروابط يحذف جميع المحارف باستثناء الأحرف والأرقام والمحارف $-_.+!*'(),{}|\^~[]<>#%";/?:@&=`. var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y', FILTER_SANITIZE_URL)); var_dump(filter_var("http://www.example.com/path/to/dir/index.php?test=y!#$%&'*+-=?^_`{|}~.[]", FILTER_SANITIZE_URL)); var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=a b c', FILTER_SANITIZE_URL)); الخرج: string(51) "http://www.example.com/path/to/dir/index.php?test=y" string(72) "http://www.example.com/path/to/dir/index.php?test=y!#$%&'*+-=?^_`{|}~.[]" string(53) "http://www.example.com/path/to/dir/index.php?test=abc" التحقق من عناوين البريد الإلكتروني تعيد الدالة filter_var() عند استخدامها للتحقق من عنوان بريد إلكتروني بيانات مرشّحةً، والتي يجب أن تكون عنوان بريد إلكتروني في هذه الحالة أو false إذا لم يكن عنوان البريد إلكتروني صحيحًا: var_dump(filter_var('john@example.com', FILTER_VALIDATE_EMAIL)); var_dump(filter_var('notValidEmail', FILTER_VALIDATE_EMAIL)); الخرج: string(16) "john@example.com" bool(false) لا تتحقق هذه الدالة من المحارف غير اللاتينية، يمكن التحقق من اسم المجال المدول (Internationalized) من خلال نموذج xn-- الخاص به. لاحظ أنّه لا يمكن معرفة فيما إذا كان عنوان البريد الإلكتروني صحيحًا قبل إرسال بريد إلكتروني إليه، قد ترغب بالمزيد من عمليات التحقق مثل التحقق من سجل MX، لكن هذا ليس ضروريًا. لا تنسَ إزالة الحسابات غير المستخدمة عند إرسال بريد تأكيد إلكتروني. التحقق من القيم الصحيحة تعيد الدالة filter_var() عند استخدامها للتحقق من قيمة يجب أن تكون عددًا صحيحًا بيانات مرشّحةً والتي يجب أن تكون عددًا صحيحًا في هذه الحالة أو false إذا لم تكن القيمة عددًا صحيحًا. ولا تنسَ أنّ الأعداد العشرية ليست أعدادًا صحيحة. var_dump(filter_var('10', FILTER_VALIDATE_INT)); var_dump(filter_var('a10', FILTER_VALIDATE_INT)); var_dump(filter_var('10a', FILTER_VALIDATE_INT)); var_dump(filter_var(' ', FILTER_VALIDATE_INT)); var_dump(filter_var('10.00', FILTER_VALIDATE_INT)); var_dump(filter_var('10,000', FILTER_VALIDATE_INT)); var_dump(filter_var('-5', FILTER_VALIDATE_INT)); var_dump(filter_var('+7', FILTER_VALIDATE_INT)); الخرج: int(10) bool(false) bool(false) bool(false) bool(false) bool(false) int(-5) int(7) يمكنك استخدام تعبير نمطي إذا كنت تتوقع أرقامًا فقط: if(is_string($_GET['entry']) && preg_match('#^[0-9]+$#', $_GET['entry'])) // هذا رقم صحيح (موجب) else // الرقم المدخل غير صحيح لا تحتاج للقيام بمثل هذا التحقق إذا كنت تحوّل هذه القيمة إلى عدد صحيح لذا يمكنك استخدام filter_var(). التحقق من وجود عدد صحيح ضمن مجال نحتاج إلى تضمين الحد الأقصى والحد الأدنى للمجال للتحقق من وجود عدد صحيح ضمن هذا المجال. $options = array( 'options' => array( 'min_range' => 5, 'max_range' => 10, ) ); var_dump(filter_var('5', FILTER_VALIDATE_INT, $options)); var_dump(filter_var('10', FILTER_VALIDATE_INT, $options)); var_dump(filter_var('8', FILTER_VALIDATE_INT, $options)); var_dump(filter_var('4', FILTER_VALIDATE_INT, $options)); var_dump(filter_var('11', FILTER_VALIDATE_INT, $options)); var_dump(filter_var('-6', FILTER_VALIDATE_INT, $options)); الخرج: int(5) int(10) int(8) bool(false) bool(false) bool(false) التحقق من رابط تعيد الدالة filter_var() عند استخدامها لترشيح رابط بيانات مرشّحةً والتي يجب أن تكون رابطًا في هذه الحالة أو false إذا لم يكن الرابط صحيحًا: مثال الرابط example.com: var_dump(filter_var('example.com', FILTER_VALIDATE_URL)); var_dump(filter_var('example.com', FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)); var_dump(filter_var('example.com', FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)); var_dump(filter_var('example.com', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)); var_dump(filter_var('example.com', FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED)); الخرج: bool(false) bool(false) bool(false) bool(false) bool(false) الرابط http://example.com: var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL)); var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)); var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)); var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)); var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED)); الخرج: string(18) "http://example.com" string(18) "http://example.com" string(18) "http://example.com" bool(false) bool(false) الرابط http://www.example.com: var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL)); var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)); var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)); var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)); var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED)); الخرج: string(22) "http://www.example.com" string(22) "http://www.example.com" string(22) "http://www.example.com" bool(false) bool(false) الرابط http://www.example.com/path/to/dir/: var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL)); var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)); var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)); var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)); var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED)); الخرج: string(35) "http://www.example.com/path/to/dir/" string(35) "http://www.example.com/path/to/dir/" string(35) "http://www.example.com/path/to/dir/" string(35) "http://www.example.com/path/to/dir/" bool(false) الرابط http://www.example.com/path/to/dir/index.php: var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL)); var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)); var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)); var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)); var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED)); الخرج: string(44) "http://www.example.com/path/to/dir/index.php" string(44) "http://www.example.com/path/to/dir/index.php" string(44) "http://www.example.com/path/to/dir/index.php" string(44) "http://www.example.com/path/to/dir/index.php" bool(false) الرابط http://www.example.com/path/to/dir/index.php?test=y: var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y', FILTER_VALIDATE_URL)); var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y', FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)); var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y', FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)); var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)); var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y', FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED)); الخرج: string(51) "http://www.example.com/path/to/dir/index.php?test=y" string(51) "http://www.example.com/path/to/dir/index.php?test=y" string(51) "http://www.example.com/path/to/dir/index.php?test=y" string(51) "http://www.example.com/path/to/dir/index.php?test=y" string(51) "http://www.example.com/path/to/dir/index.php?test=y" تحذير: يجب التحقق من أنّ البروتوكول يحميك من هجوم البرمجة عبر المواقع (XSS). var_dump(filter_var('javascript://comment%0Aalert(1)', FILTER_VALIDATE_URL)); // string(31) "javascript://comment%0Aalert(1)" تعقيم الأعداد العشرية يحذف جميع المحارف باستثناء الأرقام و+- والمحارف .,eE اختياريًا. var_dump(filter_var(1, FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var(1.0, FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var(1.0000, FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var(1.00001, FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var('1', FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var('1.0', FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var('1.0000', FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var('1.00001', FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var('1,000', FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var('1,000.0', FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var('1,000.0000', FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var('1,000.00001', FILTER_SANITIZE_NUMBER_FLOAT)); var_dump(filter_var('1.8281e-009', FILTER_SANITIZE_NUMBER_FLOAT)); الخرج: string(1) "1" string(1) "1" string(1) "1" string(6) "100001" string(1) "1" string(2) "10" string(5) "10000" string(6) "100001" string(4) "1000" string(5) "10000" string(8) "10000000" string(9) "100000001" string(9) "18281-009" باستخدام خيار FILTER_FLAG_ALLOW_THOUSAND: var_dump(filter_var(1, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var(1.0, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var(1.0000, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var(1.00001, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1.0', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1.0000', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1.00001', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1,000', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1,000.0', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1,000.0000', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1,000.00001', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); var_dump(filter_var('1.8281e-009', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); يكون الخرج: string(1) "1" string(1) "1" string(6) "100001" string(1) "1" string(2) "10" string(5) "10000" string(6) "100001" string(5) "1,000" string(6) "1,0000" string(9) "1,0000000" string(10) "1,00000001" string(9) "18281-009" باستخدام الخيار FILTER_FLAG_ALLOW_SCIENTIFIC: var_dump(filter_var(1, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var(1.0, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var(1.0000, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var(1.00001, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var('1', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var('1.0', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var('1.0000', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var('1.00001', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var('1,000', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var('1,000.0', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var('1,000.0000', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var('1,000.00001', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); var_dump(filter_var('1.8281e-009', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC)); يكون الخرج: string(1) "1" string(1) "1" string(1) "1" string(6) "100001" string(1) "1" string(2) "10" string(5) "10000" string(6) "100001" string(4) "1000" string(5) "10000" string(8) "10000000" string(9) "100000001" string(10) "18281e-009" التحقق من عنوان IP يفحص قيمة فيما إذا كانت عنوان IP صحيح: var_dump(filter_var('185.158.24.24', FILTER_VALIDATE_IP)); var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP)); var_dump(filter_var('192.168.0.1', FILTER_VALIDATE_IP)); var_dump(filter_var('127.0.0.1', FILTER_VALIDATE_IP)); الخرج: string(13) "185.158.24.24" string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001" string(11) "192.168.0.1" string(9) "127.0.0.1" التحقق من عنوان IP فيما إذا كان عنوان IPv4 صحيح: var_dump(filter_var('185.158.24.24', FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)); var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)); var_dump(filter_var('192.168.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)); var_dump(filter_var('127.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)); الخرج: string(13) "185.158.24.24" bool(false) string(11) "192.168.0.1" string(9) "127.0.0.1" التحقق من عنوان IP فيما إذا كان عنوان IPv6 صحيح: var_dump(filter_var('185.158.24.24', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); var_dump(filter_var('192.168.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); var_dump(filter_var('127.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); الخرج: bool(false) string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001" bool(false) bool(false) التحقق من كون عنوان IP غير موجود ضمن مجال خاص: var_dump(filter_var('185.158.24.24', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)); var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)); var_dump(filter_var('192.168.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)); var_dump(filter_var('127.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)); الخرج: string(13) "185.158.24.24" string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001" bool(false) string(9) "127.0.0.1" التحقق من كون عنوان IP غير موجود ضمن مجال محجوز: var_dump(filter_var('185.158.24.24', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var('192.168.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var('127.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); الخرج: string(13) "185.158.24.24" bool(false) string(11) "192.168.0.1" bool(false) التعقيم بالمرشحات يمكننا استخدام المرشِّحات لتعقيم متغير ما وفقًا لاحتياجاتنا، مثال: $string = "<p>Example</p>"; $newstring = filter_var($string, FILTER_SANITIZE_STRING); var_dump($newstring); // string(7) "Example" ستحذف الشيفرة السابقة وسوم html من المتغير $string. ترجمة -وبتصرف- للفصل [Filters & Filter Functions] من كتاب PHP Notes for Professionals book اقرأ أيضًا المقال التالي: شرح المولدات وتوضيح مفهوم المغلف (closure) في PHP المقال السابق: معالجة الملفات والبيانات المرمزة بترميز UTF-8 في PHP1 نقطة
-
دخل إلى مجال الويب مؤخرًا العديد من الأفكار والتقنيات والإضافات لغاية خدمة تجربة المستخدم في تطبيقات الويب، مثل دعم الإشعارات وتوافر أيقونة على سطح المكتب وإتاحة التحكم بالـ API والعمل بشاشة كاملة وأهم عناصر وأركان هذه التقنيات والإضافات "عامل أو منجز خدمة" Service Worker وما يقدمه من عمل التطبيق بدون الاتصال في الشبكة والتخزين المؤقت وغيرها مما ساهم بإنجاح تجربة المستخدم لهذه التطبيقات. مفهوم Service Worker منجز خدمة هو سكريبت (script) ينفذ في خلفية مشروع الويب (موقع أو تطبيق)، غير مرتبط بصفحة معينة. مسؤول عن الأحداث التي تجري بالمشروع مثل طلبات الشبكة الصادرة من الصفحة المسؤول عنها والاستجابات لهذه الطلبات، له عدة غايات من أهمها اتاحة استخدام التطبيق مع الشبكة أو بانقطاعها أو ببطئها. فلو افترضنا شخصًا يستخدم موقعًا وكان متصلًا بالشبكة وأثناء تصفحه للموقع انقطع اتصاله بالشبكة ولكن أراد الرجوع للصفحة السابقة عند إذٍ لن تفتح الصفحة السابقة وستظهر له شاشة تعلمه بإنقطاعه عن الشبكة، لكن إن كان ذلك الموقع يملك Service Worker فلن يحدث هذا، بل ستظهر الصفحة السابقة أو على الأقل جزء منها. ومن اللطيف ذكره أن أي موقع ويب بإمكانه أن يمتلك Service Worker وأن يُفعله مستفيدًا من مزاياه الرائعة، لكن في حالة تطبيقات الويب التقدمية PWA يجب أن تمتلكه وأن يكون مسجلًا وفعالًا فهو من شروط عملها. أهم الميزات التي يضفيها على مشروعك سرعة كبيرة يركز ال Service Worker في فكرته بشكل كبير على السرعة والأداء المثالي في التحميل وذلك في حالة اتصال الشبكة أو بدونها أو ببطئها وتكون أطول فترة تحميل في المرة الأولى وأما في الزيارات المتكررة يتم تحميلها بشكل أسرع. انظر المثال في الصورة حيث كان وقت التحميل في المرة الأولى 2.5 ثانية وفي الزيارات الأخرى 0.8 ثانية أي انخفضت إلى أقل من الثلث وهذا مثال بسيط. (بإمكانك اختبار أداء فاعلية مشروعك من خلال هذه الأداة WEBPAGETSET). العمل بدون شبكة كانت تتميز التطبيقات (العادية) عن الويب إمكانية عملها من غير اتصال شبكة، لكن الآن مع الـ Service Worker يمكن لمواقع وتطبيقات الويب أن تعمل بدون اتصال شبكة والذي يقوم بتخزين الموارد والعناصر التي ترتبط بالأحداث والتفاعل لاستخدامها بدون اتصال شبكة أو ببطئها. التحديث المستمر للتطبيق يعتبر Service Worker المسؤول عن التحديثات في تطبيقات الويب، بل يتميز عن تحديثات أنواع البرامج والتطبيقات الأخرى بالسلاسة والاستمرارية والسهولة وذلك من خلال تخزين وتثبيت الموارد المحدثة فقط وبشكل تلقائي ويظهر شارة صغيرة للمستخدم عند فتح التطبيق بأن التطبيق تم تحديثه. سيطرة أعلى يمنح Service Worker لمطورين المواقع والتطبيقات سيطرة كاملة وأفضل على تجربة المستخدم للتطبيق. تجربة تطبيقات حقيقية يدعم Service Worker ويحسن تجربة المستخدم في التطبيقات ومحاكاتها من خلال ما يوفر من السرعة والعمل بدون اتصال الشبكة والتخزين المؤقت وهيكل التطبيق (الذي سنفصل فيه) وغيرها. وكذلك يمنح تجربة تطبيقات حقيقية ويحسنها للجوال حيث تكون منفصلة ومستقلة عن المتصفحات لا يشترط أن تكون مبنية عليها. بنية هيكل التطبيق application shell architecture عند تكرار زيارة الموقع أو عند تحميل التطبيق يتم تخزين حد معين من الشيفرات المصدرية HTML، و CSS، و JavaScript مؤقتًا ليتم استعمالها بدون اتصال الشبكة أو حتى مع اتصالها ولكن بشكل فوري وأسرع. وصلب الفكرة هنا أننا نملك هيكل يمثل جزءًا معينًا من التطبيق أو الموقع موجود على جهاز المستخدم يُحمل ويُبنى فورًا عند فتحه سواء مع اتصال شبكة أو بدون ثم يبدأ إضافة المحتوى غير المشمول فيها من الشبكة على هذا الهيكل إذ هو بمثابة الوعاء الفارغ الذي يوضع فيه شيء ما.(يعني نحافظ على واجهة المستخدم الأساسية على جهاز المستخدم ولا داعي لتحميلها كل مرة). وبهذا فإنها تخدم التجربة كثيرًا بغض النظر عن اتصال الشبكة أو سرعتها. وحتى إن كانت فكرة التطبيق/الموقع تعتمد بشكل كامل على اتصال الشبكة فإن المستخدم سيحصل على هيكل وشكل جذاب ومناسب بعدم اتصال الشبكة ويتوافق مع شكل التطبيق الأصلي ولن تظهر له شاشة عدم الاتصال، فهذا الهيكل يلعب دورًا عظيمًا في الأداء المثالي للموقع أو التطبيق من سرعة وخفة وتجربة مثالية. بعد فتح الموقع في المرة الأولى وتحميل الـ Service Worker لهذا الهيكل تظهر شارة أن البرنامج جاهز للعمل بدون اتصال شبكة. والمسؤول عن هذا الهيكل هو Service Worker وفي حال عدم دعم المتصفح لـ Service Worker لا داعي للقلق، فإن الهيكل والصفحة كاملة ستعتمد في تحميلها على استراتيجية الويب الشهيرة Progressive Enhancement بدون مشاكل. ومن الأمثلة الناجحة في استخدام فكرة هذا الهيكل: Google’s Inbox و offline Wikipedia app ومعظم مشاريع نقاية. آلية عمل الـ Service Worker وحدود إمكانياته عند الزيارة الأولى للموقع أو عند تثبيت التطبيق يتم بناء الـ Service Worker وأخذ المحتوى والهيكل وكل البيانات والموارد من الخادم، وفي المرات التالية يتم سحب بيانات وعناصر محددة من الخادم ولكن كيف يتم تنظيم هذا السحب؟ كيف يتم تحميل بعض العناصر من Service worker وأخرى من الخادم؟ يعترض Service Worker طلبات الشبكة الصادرة من الصفحة وهنا يقوم بالاستجابة لهذه الطلبات بواحدة مما يلي: جلب المطلوب من الخادم عبر الشبكة. جلب المطلوب من الذاكرة المؤقتة على جهاز المستخدم، يتم جلب من الذاكرة المؤقتة العناصر والموارد المحددة مسبقًا لتجلب منها (مثل الهيكل الذي تحدثنا عنه). بناء المطلوب برمجيًا. والرائع هنا أن هذا كله يحدث دون أن يظهر مصدر الإستجابة ولا حتى أن الـ Service Worker قد تدخل. فلو تتبعنا دورة حياة الـ Service Worker لوجدنا أنه يتم بناءه عند أول دخول ويُحمل بعض الموارد عليه، ثم يُفعل ويَستيقظ عند وجود أي حدث، ويستجيب لهذا الحدث إن لزم الأمر مؤديًا دوره، ثم يُحذف من الذاكرة بمحتواه عند مرور الزمن دون أن ينشط، وتم إنشائه هكذا محدود العمر عن قصد. ومن الجيد معرفته أن Service Worker يحتوي على API محدودة مقارنة بما تحتويه الـ JavaScript في الصفحة العادية، بإمكانك أن تعرف تفاصيل API له هنا. واعلم بأن Service worker لا يمكنه الوصول إلى الـ DOM ولكن يمكنه الوصول إلى ذاكرة التخزين. ويمكنه أيضًا ارسال طلبات الشبكة، كذلك يمكنه أن يتواصل وأن يتبادل البيانات مع الصفحة المسؤول عنها عن طريق IndexedDB API و postMessage. لا تفوت ميزاته مع مشاريعك القادمة لكن بحدود يتبين مما سبق البون الشاسع الذي يُحدِثه الـ Service Worker في أداء مشاريع الويب معه، لذا يُنصح وبشدة استخدامه في تطبيقات ومواقع الويب، لكن بشكل معقول، فليس من المنطق أن تضيفه إلى مواقع صغيرة الحجم أو لا تقدم خدمة وتفاعل وتميل للمحتوى الثابت الخفيف فلا فائدة أو معنى من إضافته لمثلها. تسهيل الحصول على Service Worker مع Workbox يعتبر Workbox مجموعة من المكتبات والأدوات المستخدمة لإنشاء Service Worker والتخزين المؤقت وغيرها وتسهيل ذلك. مراجع Instant Loading Web Apps With A Service Worker Application Shell Architecture Service Workers: an Introduction Using Web Workers Cache Fetch API IndexedDB API Client.postMessage() Application Shell Architecture workbox What Are Service Workers and How They Help Improve Performance1 نقطة
-
عذرا على اسئلتي البسيطة عندي جدول اسمه customer مثلا به 20 عميل عاوز الامر اللي يقولي العدد ده يعني اكتب مثلا عدد العملاء و جنبة الرقم المسجل بالداتابيز1 نقطة
-
شكرا لحضرتك جدا نجحت التجربة بالكود الخاص بحضرتك و نجحت ايضا بتعديله بازالة الجملة الشرطية و دالة while <?php $client_number = "SELECT COUNT(id) FROM clients "; $result = $conn -> query($client_number); $row = $result -> fetch_row() ; echo $row[0]; $conn -> close(); ?> سؤالي ، ليه حضرتك استخدمت جملة شرطية في المثال بتاعك ، عذرا فانا مبتدئ و بقول يا هادي1 نقطة
-
كلامك صحيح تماماً ولكن بالنسبة للموقع فعدد اعضاءة فقط خمسة أشخاص وفى نفس الوقت سيكون فقط كبوابة لشىء آخر أأمن بكثير لذلك سيكون فقط كـ استضافة خارجية للصور أما بالنسبة للبيانات فسيتم إرسالها مباشرةً1 نقطة
-
بمجرّد التحدث عن نسبة أمان عالية، فهذا يعني (الحاجة) لاستخدام mysql. فنسبة الأمان العالية تعني تشفير كلمات المرور وتخزينها في بيئة محمية لمنع الوصول لها. وتخزينها ضمن بيئة mysql بما يحويه من عوامل حماية وصلاحيات تجعل ذلك ممكناً بدلاً من تخزينها ضمن ملفات موجودة بين ملفات الموقع الأخرى على الخادم وبالتالي تكون عرضة للوصول إليها. كما أنه من ناحية الأداء، التعامل مع البيانات ضمن ملفات لا يقارن بالتعامل مع البيانات في قاعدة بيانات فهي أسرع بأضعاف وتوفر سهولة وديناميكية في التعامل مع البيانات.1 نقطة
-
إن إنشاء الموقع لا يعتمد على عدد المستخدمين أو عدد الصفحات، بالطبع سيشكلان معاً عاملاً مهماً لتنفيذ الموقع، ولكن الإجرائيات والخصائص التي سيتم تنفيذها أثناء عملية البرمجة هي نفسها سواء ل 5 مستخدمين أو 1000. وربما تكون بحاجة عناية أكبر في المواقع الكبيرة في حالات خاصة. لن تقوم بإضاعة الوقت في حال كنت تتعلم لغة البرمجة التي ستقوم عن طريقها بتنفيذ الموقع، على العكس تماماً إن ذلك سيساعدك لبناء الموقع بنفسك وحل المشكلات التي قد تواجهك مستقبلاً ضمن الموقع أو حتى العمل على تطويره. ففي حال قمت بنسخ ولصق نص برمجي ما، عند حدوث أي مشكلة لن تتمكن من حلّها بنفسك في حال لم يكن لديك أي معرفة فيها. أما لإنشاء الصفحات المذكورة بشكل كامل وآمن (أي كامل الموقع الذي تعنيه) بأي لغة برمجة تختارها يجب عليك أيضاً الإنتباه إلى وجود عمليات تطوير أخرى تشمل واجهات الموقع أولاً من تصميم وتنسيق HTML, CSS, Javascript وأيضاً تهيئة قاعدة البيانات بالشكل الملائم مع الأخذ بعين الاعتبار الخصائص التي ترغب بتضمينها ضمن الموقع. وكذلك الأمر بالنسبة لأمور التحقق (تسجيل الدخول) والانتقال بين الصفحات ونقل البيانات ورفع الصور وتخزينها،...إلخ. لذلك أعتقد من الصعب كتابة كافة الأمور السابقة في تعليق بسيط أو كود واحد. إن ووردبريس سيسهّل عليك بعضاً من الأمور السابقة وممكن أن يختصر عليك وقت كبير للحصول على الموقع الذي ترغب به. لذلك في حال كنت تريد بناء الموقع بنفسك أقترح عليك البدء في الخيار الأنسب لك، وفي حال واجهتك مشكلة ما أثناء عملية التطوير ستتمكن من حلها أثناء التعلم عن طريق البحث على الانترنت.1 نقطة
-
1 نقطة
-
1 نقطة
-
يظهر لي الخطأ التالي عند محاولة كتابة الملفات: java.io.IOException: Access is denied at java.base/java.io.FileOutputStream.writeBytes(Native Method) هذا الجزء من الكود هو المسؤول عن كتابة الملفات في برنامجي: private static void writeTestCaseIntoFile(String fileName, ArrayList<String> strings) { File file = new File(fileName); if (!file.exists()) { try { file.createNewFile(); } catch (IOException ex) { ex.printStackTrace(); } } FileWriter writer; try { writer = new FileWriter(file); for (String string : strings) { try { writer.write(string.trim() + "\n"); } catch (IOException ex) { ex.printStackTrace(); } } writer.close(); System.out.println("All OK! , " + fileName); } catch (IOException ex) { ex.printStackTrace(); } }1 نقطة
-
1 نقطة
-
لا مشكلة في حال كانت أسئلتك بسيطة المهم أن تتعلم منها. نريد إعادة عدد السجلات، نستخدم الدالة count (يمكنك تمرير المعرف id بدل النجمة لكن لا أعلم كيف قمت بكتابة الاسم لديك في الجدول) ستعطي نفس النتيجة و أداء أفضل قليلا في حالة سجلات كثيرة (* تقوم بعد جميع الحقول أما في حال تحديد عمود وحيد يكون أفضل - لتقليل العمليات الغير ضرورية). الاسم المستعار الذي يظهر مقابل القيمة هو customers_Number select count(*) as customers_Number from customer;1 نقطة
-
اكتب عملية خارجية تتلقى مؤشر على اول حلقة من سلسلة حلقات والتي حدودها من نمط صحيح, على العملية ان تعيد عدد العقد-الحلقات التي في السلسلة. - حل عن طريق عملية تراجعية Public static int CountNodes(Node<int> p) { int count=0; while(p != null) { Count++; p=p.GetNext(); } return count; } سؤال: اكتب عملية تتلقى مؤشر على اول حلقة من سلسلة حلقات والتي حدودها من نمط صحيح, وتتلقى أيضا عدد صحيح num, على العملية ان تعيد true اذا كان num موجود في السلسلة والّا تعيد false. وشكرا جزيلا ♥️1 نقطة
-
أن الحل بسيط، أقترح عليك الحاولة فهو يشبه إلى حد كبير نفس هذه الشيفرة التي قدمتها. سأشرح بعض الخطوات المساعدة: تابع البحث عن قيمة يجب أن نمرر له هذه القيمة كوسيط parameter ومن ثم نقوم بالتجول على قيم السلسلة بنفس الطريقة المقدمة أي حلقة while وفيها نقارن قيمة العقدة الحالية مع القيمة الممرة و نعيد true في حال التساوي. إذا انتهت الحلقة ولم نجد أي عنصر مساوٍ للوسيط نعيد false. حاول حل المشكلة إعتمادا على الشرح السابق. Public static int CountNodes(Node<int> p, int X) { while(p != null) { if (p.value == X) return true; p=p.GetNext(); } return false; } إن بنية العقدة يمكن أن تحوي قيمة العنصر الحالي حيث أن الوصول لها يكون إما عن طريق value أو قيمة أنت قمت بتعريفها حسب بنائك لنمط البينات Node. إن Node يجب أن تحوي قيمة محلية من النوع int و العنصر التالي Next. وفي حالتنا علينا المقارنة مع العنصر الحالي للعقدة. ربما تختلف التسمة value لديك لكن هذه هي الطريقة المطلوبة.1 نقطة
-
أنا اريد ان برمج اسكربت او برنامج يقوم بنسخ اسم ورقم من موقع محدد ويقوم بلصقه في خانات في جداول موجودة في الوورد او الاكسيل بحيث استطيع طباعتها ولكل اسم رقم خاص به اريده ن يقوم بنسخ الاسم والرقم الخاص به ويلصق الاسم في خانة الاسم في الوورد ويلصق الرقم في خانة الرقم في الوورد اريد ان اعرف ما هي الطريقة ولغة البرمجة والشروحات التي احتاج الاستماع اليها لاقوم بهذا ؟؟1 نقطة
-
1 نقطة
-
لدي مشروع لارافيل وقمت بإنشاء اتصال مع pusher لإرسال البيانات. نجحت العملية عند استخدام public channels ولكن عند استخدام private channels يفشل في تخطي المصادقة ويعيد الخطأ Error 403 فقط في القنوات الخاصة private channels BroadcastServiceProvider.php يحوي التحقق من المستخدم عند إنشاء الاتصال بالقناة: namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Broadcast; class BroadcastServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { Broadcast::routes(); Broadcast::channel('App.User.*', function ($user, $userId) { return true; }); } } كود ملف bootstrap.js: import Echo from "laravel-echo" window.Echo = new Echo({ broadcaster: 'pusher', key: 'My-Key-Here' }); window.Echo.private('App.User.1') .notification((notification) => { console.log(notification.type); }); يتم وصول البيانات بنجاح إلى pusher ولكنها تفشل عند الوصول إلى الروت auth1 نقطة
-
هل ممكن تزودني بلقطات شاشة من التطبيقات ؟ ايضا هذه الاعلانات من الممكن تكون من صاحب التطبيق و ليست خدمة مشترك فيها مثل ادموب.1 نقطة
-
دائما تأكد من logs عن طريق المسار التالي storage/logs تجد ملفات logs بتاريخ اليوم أو ملف كامل لجميع logs ويمكنك فتح الملفات و النظر بسبب المشكلة ممكن ان تكون قد أخطأت في كتابة اسم الcontroller في ملف المخصص للمسارات مثل Route::get('/home', 'HomeController@index')->name('home'); ممكن أن تكون قد أخطأت في كتابة اسم المسار مثل /home أو أخطأت في كتابة اسم controller مثل HomeController. أو ايضا تفقد الدالة name التي تعطي اسم المسار و في حالة الكود أعلاه تفقد اسم المسار و طريقة التوجيه المستخدمة فمثلا ممكن ان نوجه صفحة عن طريق <a href="{{ route('home') }}">الصفحة الرئيسية</a> واخيرا قم بتنفيذ php artisan cache:clear php artisan route:clear php artisan config:clear php artisan view:clear أو يمكنك عن طريق المتصفح بحذف الكاش بوضع Route::get('/cache-clear', function() { Artisan::call('cache:clear'); }); في ملف web.php ومن ثم في المتصفح قم بفتح المسار /cache-clear1 نقطة
-
قد تحدث المُشكلة بسبب أحد النقاط التالية: أنك تقوم بتصفح الرابط بشكل خاطئ أي أن المسار الذي تُحاول الوصول إليه فعلاً غير موجود. فيجب التأكد من هذه النُقطة أولاً أن المسار الذي تحاول الوصول إليه مُتضارب مع مسار آخر موجود فوقه في الترتيب فإن كان لديك مسار آخر بالشكل التالي: Route::get('/threads/{thread}', [ThreadController::class, 'show']); Route::get('/threads/create', [ThreadController::class, 'create']); و كنت تُحاول الوصول إلى الرابط threads/create/ فلن يتم أخذ المسار الثاني بعين الإعتبار بل سيتم في هذه الحالة تنفيذ المسار الأول و تمرير الكلمة create كمُعامل للتابع show. لذلك إن أردت أن يكون المسار الخاص بالتابع create له اولوية ضعه فوق المسار الذي به مُعامل بهذا الشكل: Route::get('/threads/create', [ThreadController::class, 'create']); Route::get('/threads/{thread}', [ThreadController::class, 'show']); أن التطبيق الخاص بك يعمل بالcache أي أن المسارات مُخزنة في الcache فأي مسار جديد تقوم بإضافته لا يتم الإنتباه له و في هذه الحالة يجب عليك عمل clear لل cache الخاص بالمسارات بتنفيذ أحد هذه الأوامر: php artisan route:clear // او php artisan optimize:clear حيث أن الأمر الأخير يقوم بعمل clear لعدة أشياء ليس المسارات فحسب بل صفحات العرض و الإعدادات وما إلى ذلك.1 نقطة
-
السلام عليكم اختي الكريمة معك م رضوان وزان قد قرأت ما طلبت وانا على أتم الاستعداد للبدء معك في هذا العمل بإذن الله بانتظار ردك1 نقطة
-
نواصل في هذا المقال استعراض أساسيات لغة جافا التي يحتاج كل مُطوّر أندرويد الإلمام بها. إذا لم تطّلع على الجزء الأول فأنصحك بقراءته أوّلا قبل مواصلة قراءة هذا المقال. المصفوفات في بعض الأحيان نحتاج إلى تخزين عدة بيانات من نفس النوع والتعامل معها، في هذه الحالة لا يتم استخدام عدة متغيرات للتعامل معها ولكن يتم استخدام المصفوفات Arrays. فالمصفوفات مجموعة متغيرات من نفس النوع وتربطها علاقة ببعضها فيتم تخزينها داخل متغير واحد من النوع مصفوفة، ويتم تعريف المصفوفة بالشكل التالي DataType [] arrayName = new DataType [arraySize]; فمثلا لتعريف مصفوفة من النوع int وتحتوي على 6 عناصر: int [] numArr = new int [6]; هكذا تم حجز 6 أماكن في الذاكرة للمصفوفة numArr، وللوصول لهذه الأماكن للتخزين فيها أو التعامل مع قيمها. numArr[0] = 10; numArr[1] = 5; ... numArr[5] = 3; والعنصر الأول يبدأ من صفر وتنتهي العناصر عند الرقم 5 لتصبح ست عناصر، ويتم التعامل بعد ذلك مع عناصر المصفوفة مثل المتغيرات فمثلًا لجمع رقم ما على إحدى قيمها numArr[3] = numArr[0] + 4; ويتم احتساب خطأ إذا تم الوصول إلى عنصر خارج حدود المصفوفة التي تم تعريفها مثل: numArr[7] = 2 ; //Error وتصنف النوع السابق من المصفوفات على أنه من المصفوفات الساكنة التي عند تحديد عدد عناصرها عند تعريفها فلا يمكن زيادة هذا العدد أو إزالة عناصر من المصفوفة. الدوال الدالة هي مجموعة من الأوامر التي تنفذ فقط عندما نقوم باستدعائها وتستخدم للقيام بالأوامر التي يتكرر استخدامها في مواضع مختلفة في البرنامج بسهولة دون إعادة كتابة الأسطر البرمجية مجددًا مما يجعل البرنامج أكثر وضوحًا. تتميز جافا باحتوائها على مجموعة كبيرة من الدوال الجاهزة التي يمكنك استعمالها مباشرة، كما يمكننا من إنشاء دوال خاصة تؤدي وظائف محددة. تعريف الدوال يتم على النحو التالي AccessModifier ReturnType methodName ( parameters List){ //Do some Actions here } ويحدد AccessModifier طريقة الوصول لهذه الدالة. ونوع البيانات التي سترجعه الدالة يتم تحديده في ReturnType. ثم يتم تحديد الاسم الخاص بالدالة، والـ parameters هي البيانات التي يتم تمريرها للدالة. public int add( int a , int b ) { int sum = a + b; return sum; } في المثال السابق كلمة public تعني أن هذه الدالة يمكن استدعاؤها من أي مكان في البرنامج وهي عكس private والتي تعني أن هذه الدالة لا يمكن استدعاؤها إلا من داخل الصّنف class الذي قام بتعريفها. بعد ذلك تم تحديد النوع الذي ستعيده الدالة عند استدعائها وهو int، والاسم الخاص بهذه الدالة add وتأخذ هذه الدالة قيمتين من النوع int لتعيد ناتج جمعهما. لاستدعاء هذه الدالة من أي مكان داخل البرنامج يتم كتابة اسم الدالة كما بالشكل: int result = add (10 , 15); الأصناف وهو الوحدة الأساسية المبني عليها باقي مفاهيم البرمجة كائنية التّوجّه، وهو عبارة عن وعاء كبير يحتوي على متغيرات ودوال وكائنات. وعند تعريف صنف Class جديد يصبح لديك نوع بيانات جديد يمكنك استخدامه مع باق الأنواع الموجودة بالفعل. لتعريف صنف يتم كتابة كلمة class واختيار اسم له، ثم فتح أقواس تحدد بدايته ونهايته. class ClassName { } تسمى المتغيرات التي يتم تعريفها داخل الصّنف بالخصائص attributes، وتسمى الدوال بالتّوابع methods (يعني سنستعمل "دالة" و "تابع" للدّلالة على نفس المفهوم). وتسمى المتغيرات من الأصناف بالكائنات Objects، فلا يمكن إنشاء كائن دون وجود صنف له. إذا أردنا أن نكتب برنامجًا يعبر عن مكتبة وما تحتويه من كتب فيمكن اعتبار الكتاب على أنه كائن ولإنشاء هذا الكائن ينبغي وجود Class له يحتوي على الخصائص الأساسية لجميع الكتب. class Book{ private String bookName; private String authorName; private int bookCode; public void setBookName(String name){ bookName = name; } public String getBookName(){ return bookName; } public void setAuthorName(String name){ authorName = name; } public String getAuthorName(){ return authorName; } public void setBookCode(int code){ bookCode= code } public int getBookCode(){ return bookCode; } } هكذا قمنا بصنع الصّنف الأساسي لجميع الكتب ويحتوي على خصائص مثل اسم الكتاب واسم الكاتب وهذه البيانات معرّفة private أي كما ذكرنا سابقًا لا يمكن الوصول لها أو تغييرها إلا داخل الصّنف المعرّفة بداخله فقط، وهناك عدة توابع فمنها ما يقوم بتخزين قيم في المتغيرات الخاصة بصنف ومنها ما يعيد القيم المخزنة. لاحظ أننا قمنا بتعريف التوابع كـ public وذلك حتى نستطيع الوصول لها واستدعائها من أي مكان في البرنامج. هناك بعض الدوال التي تم تعريف نوع المُخرجات returnType لها من النوع void وتعني أنها لا تعيد شيئًا. ولإنشاء كائن من هذا الصّنف نكتب: Book b1 = new Book(); Book book2 = new Book(); النصف الأيسر كما اعتدنا سابقًا عند إنشاء متغير جديد، أما النصف الأيمن فيتكون من شقين كلمة new وتعني إنشاء هذا المتغير وحجز مساحة له في الذاكرة واسم الصّنف وبعده أقواس وهو ما يسمى بالـ Constructor. ولأي من هذه الكائنات إذا أردنا وضع قيم للخصائص التي بداخلها يتم على النحو التالي: b1.setBookName(“Learn Java”); book2.setBookName(“Intro to programming Language”); book2.setBookCode(101); String name = b1.getBookName(); وهذه بعض الأمثلة لكيفية استدعاء التّوابع المختلفة من داخل class وباستخدام الكائن، لكل كائن خصائصه الخاصة لا يتشارك فيها مع باق الكائنات التي من نفس Class فلكل منها اسم كتاب يتم تخزين فيه نص معين لا يتشاركان فيه. ولاستدعاء التوابع يتم استخدام (.) بعد اسم الكائن ثم كتابة اسم التابع وتمرير المتغيرات التي تتعامل معها إن وجدت حسب تعريفنا للتّابع داخل الصّنف. لاحظ أن عند إنشاء صنف جديد نبدأ اسمه بحرف كبير دائمًا، ويمكنك إنشاء أي عدد من الكائنات من الصّنف كما ذكرنا في المثال السابق. تابع البناء Constructor تتواجد داخل كل صنف تابع خاص يُدعى Constructor يتم استدعاؤه أثناء إنشاء كائن جديد فهو تابع مهم جدًا لإنشاء الكائنات ويقوم المترجم بإنشاء هذا تابع بناء فارغ بشكل افتراضي إذا لم يتم تعريفها من قبل المطوّر. وتكتب كالتالي: public ClassName(parameter List){ //Do some Actions here } يجب أن يكون اسم تابع البناءconstructor نفس اسم الصنف ومن النوع public ويمكنك تعريف أكثر من constructor داخل نفس الصّنف ولا يوجد نوع إرجاع returnType لـلـ constructor. يمكننا من خلال constructor إدخال قيم مباشرة في الخصائص الموجودة في الكائن بدلًا من استدعاء دالة لكل خاصية. class Book{ private String bookName; private String authorName; private int bookCode; public Book(String name,String author,int code){ bookName = name; authorName = author; bookCode = code; } public String getBookName(){ return bookName; } public String getAuthorName(){ return authorName; } public int getBookCode(){ return bookCode; } } في كل مرة يتم إنشاء كائن جديد، يجب استدعاء تابع البناء constructor حتى يتم إنشاء هذا الكائن. لإنشاء كائنات بعد هذا التعديل: Book b1 = new Book (“Learn Java”,”M.K Dave”, 150); هنا تم تعريف كافة الخصائص لحظة إنشاء الكائن، ويتم التعامل مع هذا الكائن بشكل طبيعي كما تعاملنا معه مسبقًا. الوراثة يعتبر مفهوم الوراثة من أهم المفاهيم في البرمجة كائنية التّوجّه ويعني يمكننا إنشاء أصناف ترث من صنف آخر الخصائص والتّوابع المتواجدة به دون تعريفها من جديد، مما يسمح بالتركيز على الخصائص والتّوابع التي يتميز بها الصّنف الجديد. وتستخدم الكلمة extends لتطبيق مفهوم الوراثة: class Shape{ protected int width; protected int height; public void setWidth(int a){ width = a; } public void setHeight(int b){ height = b; } } إذا كان لدينا هذا الصّنف وهو يُمثل شكلًا عامًا له طول وعرض وأردنا أن ننشئ شكلًا آخر (مربع) يرث من هذا الصّنف ويضيف خصائص أكثر: class Square extends Shape{ public int getArea(){ return width * height; } } وبذلك أصبح Square يحتوي على الدالتين setWidth و setHeight بالإضافة للدالة الجديدة التي قام بتعريفها getArea، وبذلك استطعنا أن نعطي المزيد من الخصائص للشكل الجديد. وإذا أردنا أن نصنع شكلًا آخر (مثلث): class Triangle extends Shape{ public int getArea(){ return 0.5*width * height; } } لا يمكن للصّنف أن يرث من أكثر من أب. وبتطبيق هذا المفهوم على الدرس السابق نجد أن أندرويد يحتوي على صنف اسمه View وهو الأب لكل العناصر الخاصة بواجهة المستخدم ويحدد الخصائص الأساسية والمشتركة بينهم جميعًا ويرث منه العناصر الخاصة مثل TextView وهو View ولكن يعرض نصًا فقط أو Button وأيًضا View قابل للضغط ويقوم بمهمة محددة عند الضغط عليه. وإذا قمنا بالتعديل على المثال السابق واستخدمنا في Shape تابع البناء لتعريف الطول والعرض: class Shape{ protected int width; protected int height; public Shape(int a ,int b){ width = a; height = b; } } ينبغي علينا أن نعرف دالة بناء للصّنف التي ترث منه: class Square extends Shape{ public Shape(int w ,int h){ super(w,h); } public int getArea(){ return width * height; } } وتستخدم super لاستدعاء Constructor الخاص بالأب وتمرير له القيم التي يحتاجها، وذلك لأن عند إنشاء كائن من Square والذي يرث من Shape: Sqaure s = new Square(10,10); يتم بناء الأب أولًا Shape ثم الابن Square حتى يكتمل بناء الكائن s بشكل صحيح. لذا يتم تمرير في دالة البناء الخاصة بالابن ما تحتاجه دالة البناء الخاصة بالأب، ولم نقوم بذلك قبل التعديل لأننا كنا نستعمل دالة بناء فارغة في الأب. التحويل من نوع بيانات إلى آخر تمكننا لغات البرمجة من التحويل من نوع بيانات إلى آخر باستخدام مفهوم Casting، فمثلًا إذا كان لدينا متغير من النوع double: double d = 12.5478; ونريد تحويله إلى رقم صحيح: int x = (int) d; نفعل ذلك عن طريق كتابة نوع المتغير بين القوسين وبعدها اسم المتغير الذي نريد تحويله كما في المثال. وهناك بعض الشروط على التحويل بين الأنواع بهذه الطريقة فلا يمكن تحويل String إلى int مثلًا لاختلاف النوعين عن بعضهما. ويمكن تحويل من صنف إلى آخر شريطة أن يكون بينهما علاقة الوراثة. Shape sh = new Shape(15,15); Square s = (Square) sh; بهذا نكون قد وصلنا إلى نهاية هذا الدّرس، في انتظار تجربتكم وآرائكم. إن كانت لديك أيّة أسئلة فلا تتردّد في طرحها.1 نقطة
-
مرحبا، لايمكن الحكم على أي شخص فقط عن طريق شهاداته حتى لو كانت جامعية، في مجال البرمجة تبقى الخبرة و المهارات هي العامل الأساسي في التوظيف. بالنسبة لشهادة الأكاديمية، لن تحصل عليها إلا باجتياز الامتحان وهذا يعطيها أفضلية عن دورات أخرى. طبيعة الامتحان بعد اتمامك للدورة، سيكون عليك التواصل معنا من خلال مركز مساعدة حسوب لتحديد موعد امتحان وسيكون على الشكل التالي: اجراء محادثة صوتيّة لمدة 30 دقيقة يطرح المدرّب عليك أسئلة متعلّقة بالدورة والأمور التي نفّذتها خلالها. يحدد لك المدرّب مشروعًا مرتبطًا بما قمت به أثناء الدورة لتنفيذه خلال فترة محددة تتراوح بين أسبوع الى أسبوعين. اجراء محادثة صوتيّة أخرى لمدّة 30 دقيقة يناقش بها مشروعك وما نفذته وتطرح أسئلة خلالها. ان سارت على جميع الخطوات السابقة بشكل صحيح، تحصل على الشهادة أو يرشدك المدرّب لأماكن القصور ويطلب منك تداركها ثم التواصل معنا من جديد. بعد الانتهاء من الدورة، يمكنك البدء بتقديم عروض العمل على منصات العمل الحر مثل مستقل للفترة الأولى لتكتسب بعض الخبرة، ثم بعد فترة تقوم بالتقديم على الشركات في حال أحببت ذلك مع تقديم جميع الأعمال التي قمت بها خلال الدورة و المشاريع الخاصة. بعد اجتيازك الامتحان ستتم المتابعة معك خطوة بخطوة وتوضيح جميع الطرق التي ستسلكها للحصول على عمل. حيث أحد البنود التي توفرها لك الأكاديمية عند شرائك دورة هو: إرشاد وتوجيه أثناء فترة بحثك عن عمل: هذا هو الهدف الأساسي لجميع دورات أكاديميّة حسوب. بعد إتمامك للدورة سيتم الإطّلاع على سيرتك الذاتية من قبل المختصّين لدينا وتقديم ارشادات مخصّصة لك لتحسينها وكذلك على ملفّك الشخصي في مواقع العمل الحر. بالتوفيق1 نقطة
-
بعد أن أنشأنا أول مشروع في Android Studio وقمنا بتجربة التطبيق على المحاكي سنتعلم الآن أساسيات التعامل مع واجهة المستخدم وكيفية إنشاء العناصر المختلفة بداخلها. طرق إنشاء واجهة المستخدم لتطبيق أندرويد في نظام تشغيل أندرويد هناك طريقتان لإنشاء واجهة المستخدم الخاصة بالتطبيق: التعريف في الملف الخاص بها layout باستخدام لغة XML: وتتميز هذه الطريقة بأنها تقوم بفصل عناصر الواجهة عن الشيفرات البرمجية بلغة الجافا والتي تحدد وظيفة التطبيق الأصلية مما يُسهل عملية تطوير التطبيقات واكتشاف الأخطاء وتصحيحها وتجعل التطبيق أكثر مرونة لدعم أحجام الشاشات المختلفة واللغات المختلفة. تعريف عناصر واجهة المستخدم باستخدام الشيفرات البرمجية بلغة الجافا حيث تتكون الواجهة وقت تشغيل التطبيق وعمله لدى المستخدم. كما يمكنك استخدام هاتين الطريقتين معًا عن طريق تعريف العناصر في ملف layout وباستخدام الشيفرة البرمجية تقوم بتغيير خصائصها بناءً على تفاعل المستخدم مع هذه العناصر، وتلك هي الطريقة التي سنقوم باستخدامها. عناصر واجهة المستخدم تنقسم عناصر واجهة المستخدم إلى نوعين View و ViewGroup: View هو عنصر يقوم برسم شيء ما على الشاشة حيث يستطيع المستخدم التفاعل مع هذا الشيء. ViewGroup هو حاوية غير مرئية تستطيع أن تحمل بداخلها العناصر المكوَنة للواجهة. ويتميز كل نوع من ViewGroup بطريقة فريدة ومختلفة لعرض العناصر الأخرى بداخله وتُسمى العناصر المتواجدة داخل ViewGroup بالأبناء. يمكن أن يحتوي عنصر ViewGroup على عناصر من النوع ViewGroup أيضًا أو من النوع View وذلك للوصول إلى التصميم المنشود لواجهة المستخدم كما توضح الصورة التالية: يوفر أندرويد للمطورين مجموعة من Views و ViewGroup الجاهزة والتي تقوم بالوظائف الشائعة في التطبيقات. أمثلة على ViewGroup Linear Layout: ويتم ترتيب العناصر بداخله في اتجاه واحد إما بشكل أفقي أو رأسي. Relative Layout: ويتم ترتيب العناصر بداخله نسبة إلى عنصر أخر ويتم استخدامه عند صنع واجهة أكثر تعقيدا يصعُب معها استخدام Linear Layout. أمثلة على View Button TextView ImageView أساسيات تصميم الواجهات باستخدام XML توفر لغة XML طريقة سهلة وسريعة لصنع واجهة المستخدم وتتشابه مع طريقة صناعة صفحات الويب باستخدام HTML. كما ذكرنا سابقًا تتواجد الملفات الخاصة بالواجهة في مجلد res/layout بامتداد XML. يجب أن تحتوي ملفات XML على عنصر يسمى root ويعتبر هذا العنصر الحاوية الرئيسية لباقي العناصر ويكون هذا العنصر إما ViewGroup أوView، كما يجب أن يحتوي على XML namespace وهو من المعايير القياسية الخاصة بـ XML. تعريف الـ namespace بسيط وثابت لكل الـ root elements ويكون على النحو التالي xmlns:android="http://schemas.android.com/apk/res/android" وبعد تعريف الـ root element يمكنك بعدها إضافة عناصر أخرى لاستكمال واجهة المستخدم. وفي أغلب التطبيقات يكون الـ root من النوع ViewGroup لقدرته على إضافة أبناء له، على عكس View والذي لا يمكن أن يحتوي على أبناء. يتكون كل عنصر من عناصر XML من وسم الفتح <ElementName>، ووسم الغلق <ElementName/>. وبين وسم الفتح والغلق يتم وضع العناصر الأخرى والتي تعتبر أبناء ViewGroup، وبما أنه لا يوجد للعنصر View لأبناء فيمكن الاستغناء فيه عن وسم الغلق واستخدام وسم الغلق الذاتي </ElementName>. لتوضيح الأمر أكثر سنقوم بصنع واجهة مستخدم مشابهة لتطبيق أهلًا بالعالم Hello World. قم بفتح الملف content_main.xml المتواجد بداخل المجلد res/layout، ثم قم بمسح كافة الشيفرة المكتوبة. بعد عنصر root الخاص بالواجهة أضف عنصر ViewGroup من نوع LinearLayout كالتالي: <LinearLayout> قم بتحديد XML namespace الخاص بالعنصر LinearLayout: <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android > لكل عنصر من عناصر واجهة المستخدم سواء كان View أو ViewGroup العديد من الخصائص والتي يمكن التحكم بها وتخصيصها عن طريق XML أو عن طريق شيفرة الجافا وقد تكون هذه الخصائص خاصة بهذا العنصر فقط أو خصائص مشتركة لدى أكثر من عنصر. ومن الخصائص الهامة تحديد العرض والارتفاع الخاصين بالعنصر، ولتحديد العرض للعنصر نستخدم الخاصية layout_width: android:layout_width="Value" ونستبدل Value بقيمة العرض، وهناك عدة طرق لتحديد قيمة العرض، فيمكن تحديدها عن طريق قيم معرَفة مسبقًا للنظام مثل "match_parent" وتعني أن يكون عرض العنصر نفس عرض العنصر الأب، وإذا كان العنصر الأب هو root فالأب هنا المقصود به شاشة الهاتف. وباستخدام نفس الطريقة يتم تحديد الارتفاع الخاص بالعنصر عن طريق خاصية layout_height: android:layout_height ="Value" ليصبح الشكل النهائي للعنصر: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> </LinearLayout> لاحظ أنه يتم تحديد كافة الخصائص الخاصة بالعنصر داخل وسم الفتح ويتم أيضًا وضع XML namespace معهم. سنقوم بإضافة عنصر أخر للواجهة من نوع View وهو TextView والذي يستطيع أن يحمل بداخله نصًا ويمكن للمستخدم قراءته ولا يمكنه تغييره: <TextView /> سنقوم بتحديد الخصائص الخاصة بهذا العنصر وكما ذكرنا أن خاصتيَ العرض والارتفاع من الخصائص الهامة التي ينبغي تحديدها لكافة العناصر. <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" /> كان من الممكن استخدام قيمة "match_parent" ولكننا قمنا باستخدام "wrap_content" والتي تعني أن يكون العرض أو الارتفاع يشغل القدر المطلوب للنص فقط، أما إذا استخدمنا "match_parent" فسيشغل العنصر كل المساحة الخاصة بالأب والذي هو LinearLayout والذي يشغل مساحة الشاشة كلها كما حددنا ذلك سابقًا. لتحديد النص المطلوب كتابته داخل العنصر، نقوم بإضافة السطر التالي: android:text="Hello World!" هذا هو الشكل الكلي لملف XML: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </LinearLayout> الآن قم بتشغيل التطبيق على المحاكي وستجده يعمل بالشكل المطلوب. ملاحظات العنصر TextView متواجد بين وسميَ الفتح والغلق الخاصين بـ LinearLayout ويُعتبر TextView ابنًا لـ LinearLayout. يستخدم العنصر TextView وسم الغلق الذاتي. يتم تحديد الخصائص للعنصر داخل وسم الفتح الخاص به فقط. التطبيق الثاني سنقوم بتطوير المثال السابق واستخدام عناصر أخرى في التطبيق لصنع واجهة مثل الصورة التالية: الاختلاف هنا في إضافة عنصر جديد للواجهة وهو Button. لإضافة هذا العنصر يتم استخدام العنصر </ Button> وإضافته داخل LinearLayout. نقوم بتحديد الطول، الارتفاع والنص الخاص بالزر كالتالي: <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click me"/> سيظهر الزر بجانب النص السابق: ولتغيير موضع الزر يجب تغيير اتجاه العناصر داخل عنصر LinearLayout، ولتغيير الاتجاه للرأسي بدلًا من الأفقي نستخدم الخاصية orientation: android:orientation="vertical" حيث أن الاتجاه يكون أفقيًا بشكل افتراضي. ليصبح ملف XML على النحو التالي: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click me"/> </LinearLayout> ملاحظات أي عنصر من النوع View يستخدم وسم الغلق الذاتي لأنه لا يستطيع أن يحتوي على أبناء أو عناصر أخرى بداخله. إذا قمت بكتابة العنصر Button أولًا بداخل LinearLayout ثم العنصر TextView سيتم تغيير الترتيب في الواجهة أيضًا. التطبيق الثالث يحتوي هذا التطبيق على نص "Android Image" وصورة للأندرويد وزر يتم ترتيبها بشكل رأسي. لصنع واجهة المستخدم سنختار LinearLayout كعنصر root وتغيير الاتجاه الخاص به للرأسي. نقوم بعدها بإضافة عنصر TextView وكتابة النص الخاص به، ولكن يمكن ملاحظة أن حجم الخط الخاص بالنص أكبر من الأمثلة السابقة لذا يجب تغيير حجم الخط عن طريق الخاصية textSize: android:textSize="40sp" ويتم تحديد الخط بوحدة "sp" وهي وحدة خاصة في نظام أندرويد لتحديد حجم الخط دون الاعتماد على كثافة البكسل المكوَنة للشاشة ليظهر النص دائمًا بنفس الحجم باختلاف أحجام شاشات الهواتف. لتغيير موضع النص ليكون في منتصف الواجهة نقوم باستخدام خاصية الجاذبية layout_gravity: android:layout_gravity="center" نقوم بإضافة العنصر ImageView لعرض الصور وتحديد الطول والارتفاع كالسابق، ولتحديد الصورة المعروضة بداخله نقوم بوضع الصورة في الملف res/drawable وعرضها داخل العنصر باستخدام الخاصية src: android:src="@drawable/andimg" تستخدم @ للإشارة إلى عنصر داخل الملف وبعدها يتم كتابة اسم الملف وهو drawable ثم تحديد اسم الصورة المتواجدة بداخله. نضيف بعدها العنصر Button ونقوم بتحديد النص الخاص به مع ملاحظة أن العرض الخاص به يستغل كافة مساحة الشاشة وليس على قدر المحتوى فقط. ليصبح ملف XML على النحو التالي: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Android Image" android:textSize="40sp" android:layout_gravity="center" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/andimg"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Say Hi"/> </LinearLayout> التطبيق الرابع نريد في هذا التطبيق صُنع واجهة مركبة كما في الصورة التالية: سيكون الـ root مثل الأمثلة السابقة من النوع LinearLayout ولكن هل اتجاه العناصر بداخله أفقي أم رأسي؟ ستجد العناصر متواجدة في الاتجاهين. لصنع هذه الواجهة سنستخدم أكثر من ViewGroup من النوع LinearLayout ونغير اتجاهاتها لصنع الشكل المطلوب كما في الصورة التالية: سيكون العنصر root من النوع LinearLayout والاتجاه بداخله رأسي، ويحتوي على LinearLayout آخر الاتجاه بداخله أفقي ونضع بداخله العنصرين المتجاورين كما في الصورة السابقة. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> </LinearLayout> </LinearLayout> نضع العنصرين ImageView و EditText داخل العنصر LinearLayout الثاني. نقوم بتحديد العرض والارتفاع واختيار الصورة من ملف drawable للعنصر ImageView مثل ما فعلنا في التطبيق السابق، وبالنسبة للعنصر الآخر EditText والذي يٌستخدم لإدخال نص من المستخدم، نقوم بتحديد عرضه وارتفاعه، بالإضافة إلى عرض نص يعبر عن المحتوى الذي يجب على المستخدم إدخاله باستخدام الخاصية hint: android:hint="Write your name here" نُضيف العنصر الأخير من النوع Button داخل LinearLayout الأول ولوضعه جهة اليمين نستخدم الخاصية layout_gravity: android:layout_gravity="right" ليُصبح ملف XML على الشكل التالي: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher"/> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Write your name here"/> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="70dp" android:text="Done" android:layout_gravity="right"/> </LinearLayout> ملاحظات تم تحديد الارتفاع الخاص بـ LinearLayout الثاني بـ "wrap_content" حتى يشغل الارتفاع الخاص بالعناصر فقط ولا يشغل مساحة الشاشة كلها. تم استخدام طريقة مختلفة لتحديد الارتفاع الخاص بـالعنصر Button، وتستخدم هذه الطريقة في حالة لم نرد استخدام القيم المعرَفة داخل النظام مثل "match_parent" أو "wrap_content" واستخدام قيم مختلفة. وتُستخدم الوحدة "dp" كوحدة لتحديد الأبعاد دون الاعتماد على كثافة البكسل المكوَنة للشاشة ليظهر العنصر بنفس الأبعاد دائمًا باختلاف أحجام شاشات الهواتف. التطبيق الخامس هناك طريقة أخرى لإنشاء واجهة المستخدم كما في التطبيق السابق، حيث نقوم باختيار root من النوع RelativeLayout للوصول لنفس الشكل أيضًا كما في الصورة السابقة. في RelativeLayout يتم وضع العناصر نسبة إلى عناصر أخرى متواجدة لذلك ينبغي تحديد لكل عنصر ID مميز له لأن عند وضع عنصرين من نفس النوع (Button مثلا) سيكون اسم كل منهما Button ولا نستطيع عندها التفريق بين الزر الأول أو الثاني وللتفرقة بينهم يتم استخدام خاصية id: android:id="@+id/btn1" ويتم كتابة ID الخاص بالعنصر بعد كلمة /id+@ ويكون هذا ID مميز لهذا العنصر فقط ولا يتشابه معه عنصر آخر. وهناك استخدام آخر لـ ID عند التحكم في العناصر باستخدام شيفرة الجافا. وبهذا يصبح ملف XML على الشكل التالي: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" android:id="@+id/img" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Write your name here" android:id="@+id/edttxt" android:layout_toRightOf="@+id/img" /> <Button android:layout_width="wrap_content" android:layout_height="70dp" android:text="Done" android:id="@+id/btn1" android:layout_below="@+id/edttxt" android:layout_alignParentRight="true"/> </RelativeLayout> عند تشغيل التطبيق على المحاكي سيقوم برسم نفس الشكل السابق. ملاحظات تم تحديد ID خاص لكل العناصر. هناك بعض الخصائص التي تحدد موضع كل عنصر بالنسبة لعنصر آخر. مثل الخاصية layout_toRightOf المستخدمة للعنصر EditText وذلك لوضعه بجانب العنصر ImageView جهة اليمين: android:layout_toRightOf="@+id/img" والخاصيتين layout_below و layout_alignParentRight المستخدمتين مع العنصر Button وذلك لوضعه أسفل العنصر EditText و بمحاذاة الشاشة من جهة اليمين: android:layout_below="@+id/edttxt" android:layout_alignParentRight="true" بهذا نكون قد وصلنا إلى نهاية ثاني دروسنا من سلسلة أندرويد للمبتدئين، في انتظار تجربتكم وآرائكم.1 نقطة
-
السلام عليكم بارك الله فيكم على الشرح الأكثر من وافي هل يمكنني متابعة العمل بنسخة 1.51 نقطة