اذهب إلى المحتوى

Mustafa Suleiman

الأعضاء
  • المساهمات

    10060
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    303

أجوبة بواسطة Mustafa Suleiman

  1. في في العرض (views) في Django تستطيع كتابة عبارة if statement بواسطة الشروط والتحقق منها في العرض نفسه، ومن ثم تمرير النتيجة إلى القالب (template) لعرض المحتوى المناسب بناءً على الشرط، وإليك مثالًا بسيطًا:

    في views.py:

    from django.shortcuts import render
    
    def my_view(request):
        is_authenticated = request.user.is_authenticated
        return render(request, 'my_template.html', {'is_authenticated': is_authenticated})

    في القالب (my_template.html):

    {% if is_authenticated %}
        <p>مرحبًا بك، {{ request.user.username }}!</p>
    {% else %}
        <p>قم بتسجيل الدخول من فضلك.</p>
    {% endif %}

    قمت  باستخدام request.user.is_authenticated للتحقق مما إذا كان المستخدم قد سجل الدخول أم لا في العرض.

    ثم تمرير قيمة is_authenticated إلى القالب عن طريق الدمج مع السياق (context) عند استدعاء دالة render. في القالب، واستخدام البنية if...else لعرض المحتوى المناسب بناءً على قيمة is_authenticated.

    ولاحظ أنه يجب عليك تعريف المسار المناسب في urls.py وربطه بالعرض (view) الخاص بك في Django.

  2. المشكلة تتعلق بنوع البيانات المتوقع في السطر الذي يحتوي على الخطأ، ويتعذر تحويل القيمة من نوع "int" إلى نوع "String" في سلسلة الحروف (String).

    وربما السبب هو محاولة استخدام القيمة المسترجعة من SharedPreferences على أنها سلسلة حروف (String) في السطر 27  في ملف "paniercontroller.dart"، ولكن القيمة المسترجعة عبارة عن رقم صحيح (int) وليس سلسلة حروف (String).

    حاول تجربة تحويل القيمة المسترجعة إلى سلسلة حروف (String) باستخدام دالة toString()، وذلك باستخدام الدالة toString() على القيمة المسترجعة من SharedPreferences قبل استخدامها في عملية التحويل.

    مثال:

    String? userId = sharedPreferences.getString('user_id').toString();

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

    وذلك مجرد إقتراح ولم أقم بتجربة الكود، وأخبرني بالنتيجة.

  3. 1- لنبدأ بحل كل رسالة تحذير وخطأ على حدى، ورسالة التحذير الأولى هي:

    wrning: You are importing createRoot from "react-dom" which is not supported. You should instead import it from "react-dom/client".
    p

    وهي تعني أنك تستخدم createRoot من react-dom وهو غير مدعوم في الإصدار الحالي من React وهو الإصدار 18و بدلاً من ذلك، يجب عليك استيراده من react-dom/client.

    2-  والتحذير الثاني لديك هو:

    warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot
    p

    ويعني أن استخدام ReactDOM.render لم يعد مدعومًا في React 18 ويجب استخدام createRoot بدلاً من ذلك، ويوضح أنه حتى تقوم بالتبديل إلى الواجهة البرمجية الجديدة، سيتصرف تطبيقك كما لو كان يعمل بناءً على React 17.

    حيث في React 18، تم إدخال تغييرات في طريقة تجهيز وتقديم التطبيق، وبدلاً من استخدام ReactDOM.render لتقديم التطبيق في نقطة الدخول الرئيسية، يجب استخدام createRoot لإنشاء نقطة جذرية وتقديم التطبيق من خلالها.

    3- وأيضًا لديك مشكلة أخرى وهي تستخدم الكود التالي في ملفي App.jsx وindex.jsx:

    App.jsx
    
    createRoot(document.getElementById('root')).render(<App />);
                                                       
    في ملف index.jsx
    
    ReactDOM.render(
      <BrowserRouter>
        <App />
      </BrowserRouter>,
      document.getElementById('root')
    );
    
                                                       
                                                      

    وهو يقوم بإنشاء نقطة جذرية باستخدام createRoot من react-dom ويقوم بتقديم مكون التطبيق <App /> من خلالها.

    أي يجب وضعه في مكان واحد فقط وهو index.jsx فهو نقطة الدخول لتطبيقك في webpack.

    4- المشكلة الأخيرة هي أنك تقوم بتضمين المكون App داخل أكثر من Router حيث أنك في الملف App.jsx تضعه داخل Router والتي هي BrowserRouter وفي index.jsx تضعه داخل BrowserRouter أخرى.

    وذلك غير مسموح بالطبع وسيسبب لديك مشكلة في التطبيق.

    5- لماذا قمت بإنشاء ملفي App.jsx وindex.jsx فكل ما تحتاجه هو index.jsx كملف رئيسي للمشروع.

    6- كمعلومة جانبية أنت لست بحاجة إلى استيراد React في بداية أي مكون في إصدار React 18.

    وبناءًا على ما سبق عليك تعديل الكود في ملف index.jsx كما يلي:

    //  react-dom/client الاستيراد من
    import { createRoot } from 'react-dom/client';
    
    import './App.css';
    import './index.css';
    import reportWebVitals from './reportWebVitals';
    import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
    import Home from './pages/home';
    
    import 'bootstrap/dist/css/bootstrap.css';
    import 'bootstrap/dist/js/bootstrap.min.js';
    import '@fortawesome/fontawesome-free/css/all.css';
    
    createRoot(document.getElementById('root')).render(
      // استخدم createRoot بدلاً من ReactDOM.render
      <Router>
        <Routes>
          <Route path='/' element={<Home />} />
        </Routes>
      </Router>
    );
    
    reportWebVitals();

    أي قم بحذف ملف App.jsx واستخدم الكود السابق فقط في index.jsx

    • شكرًا 1
  4.  سأوضح لك المصطلحات بالتفصيل وأمثلة لتوضيح الأفكار.

     الفرق بين الـ Parameters والـ Arguments

    • Parameters: المتغيرات التي يتم تعريفها في تعريف الدالة وتستخدم لتمرير القيم إلى الدالة، وشير إلى المتغيرات التي يتعامل معها الدالة في داخلها.
    • Arguments: القيم الفعلية التي يتم تمريرها إلى الدالة عند استدعائها، وتشير إلى القيم التي تمررها عند استخدام الدالة.

    مثال:

    لنفترض أن لدينا دالة بسيطة تسمى "add" تقوم بإجراء عملية جمع بين اثنين من الأرقام، حيث a و b هما parameters، أما الأرقام المحددة مثل 3 و 5 فهي arguments.

    function add(a, b) {  // a و b هما parameters
        return a + b;
    }
    
    const result = add(3, 5);  // 3 و 5 هما arguments
    console.log(result);  // الناتج سيكون 8

    الفرق بين الـ Declaration والـ Initialization

    • Declaration: يتعلق بتعريف متغير أو دالة أو كائن بشكل عام، حيث يتم إعلان وجوده وتحديد نوعه واسمه، ولكن لا يتم تعيين قيمة محددة له في هذه المرحلة.
    • Initialization: يتعلق بتعيين قيمة محددة لمتغير بعد تعريفه، أي تخصيص قيمة بداية للمتغير.

    مثال:

    في JavaScript، تستطيع إعلان المتغير باستخدام الكلمة الرئيسية var أو let أو const، ويمكنك تعيين القيمة باستخدام عامل التعيين =.

    let x;  // هنا نقوم بالإعلان عن المتغير x
    x = 5;  // هنا نقوم بتعيين قيمة 5 للمتغير x

    الـ Execution Context

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

    مثال:

    عند استدعاء الدالة، يتم إنشاء Execution Context جديد يحتوي على المتغيرات المحلية والمعلومات اللازمة لتنفيذ الدالة.

    وعند انتهاء التنفيذ، يتم إزالة Execution Context ويعود التنفيذ إلى السياق السابق.

    function outer() {
        const x = 5;
    
        function inner() {
            console.log(x);
        }
    
        inner();
    }
    
    outer();  // سيتم طباعة قيمة 5

    في المثال السابق، الدالة الداخلية inner يمكنها الوصول إلى المتغير x المعرف في البيئة الخارجية (outer)، لأن Execution Context يحتفظ بالارتباط بين الدوال والقيم المرتبطة بها في نطاق الكود.

    الـ Lexical Environment

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

    مثال:

    في JavaScript، يتم تشكيل الـ Lexical Environment عند تحديد النطاقات اللغوية.

    أي عند البحث عن قيمة متغير، يتم البحث في Lexical Environment الحالي وفي البيئات الأبوية حتى يتم العثور على القيمة.

    function outer() {
        const  x = 5;
    
        function inner() {
            console.log(x);
        }
    
        inner();
    }
    
    outer();  // سيتم طباعة قيمة 5

    هنا الدالة الداخلية inner يمكنها الوصول إلى المتغير x المعرف في البيئة اللغوية الخارجية (outer)، لأن Lexical Environment يحتفظ بالارتباط بين الدوال والقيم المرتبطة بها في نطاق الكود.

    • أعجبني 1
  5. بتاريخ 25 دقائق مضت قال محمد الحربي:

    أخي مازال يطبع auth فارغ في الضغطة لأولى على login وعندما أضغط مرة أخرى ينجح الأمر كما كان في السابق

    ولكن تأخرت الاستجابة قليلا بسبب await

    أنا أريد أن يتم طباعة بيانات الـ auth من الضغطة الأولى 

    والتي هي عبارة عن بيانات المستخدم و الرمز المميز token

    حاول تغيير ترتيب الدوال  في ملف login.jsx:

    import { login } from "../../redux/actions/authActions.js";
    
    const handleChange = (e) => {
      const { name, value } = e.target;
      setUserData({ ...userData, [name]: value });
    };
    
    const handlevalid = async (res) => {
      if (res.token) {
        setIsCorrect(true);
      } else {
        setIsCorrect(false);
      }
    };
    
    const handleLogin = async (e) => {
      e.preventDefault();
      setUserData({ email, password });
    
      try {
        const res = await dispatch(login(userData)); // انتظر حتى انتهاء العملية
        console.log(res); // استخدم الاستجابة المتاحة هنا
    
        handlevalid(res); // قم بتمرير الاستجابة كمعامل للدالة
        console.log(auth);
      } catch (error) {
        // إدارة الأخطاء هنا
      }
    };

    قمت بنقل الاستدعاء للدالة handlevalid() بعد استلام الاستجابة من login()، وتمرير الاستجابة كمعامل للدالة handlevalid() لكي تتمكن من استخدامها فيها.

    وبالتالي، يجب أن تحصل على طباعة صحيحة لـ auth من الضغطة الأولى على زر login.

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

  6. في CSS، تعتبر ":before" عنصر زائف وتستخدم لإضافة محتوى قبل عنصر محدد، بينما ":after" تستخدم لإضافة محتوى بعد عنصر محدد، وغالبًا تستخدم هاتين الخاصيتين لإضافة عناصر مرئية إلى عناصر HTML الموجودة.

    لكن في حالة عنصر الإدخال "input"، يعتبر استخدام ":before" غير صحيح ولا يعمل على نحو صحيح.، ذلك لأنه عنصر الإدخال "input" يعتبر عنصراً فارغاً لا يحتوي على محتوى داخلي.

    مما يعني أنه لا يمكنك استخدام ":before" لإضافة محتوى قبل عنصر "input" نفسه.

    وإذا كنت ترغب في إنشاء رمز البحث داخل عنصر الإدخال "input"، تستطيع استخدام العديد من الطرق لتحقيق ذلك.

    واحدة من هذه الطرق هي وضع عنصر فرعي مستقل للعنصر "input" واستخدام الخاصية "position: absolute" لتحديد موقع الرمز بالنسبة لعنصر الإدخال، كتعيين أيقونة لرمز البحث كخلفية للعنصر الفرعي وتنسيقه بواسطة CSS ليتناسب مع المظهر المطلوب.

    وسأوضح لك الكود اللازم لإنشاء رمز البحث داخل عنصر الإدخال "input" باستخدام خاصية "position: absolute":

    HTML:

    <div class="search-container">
      <input type="text" class="search-input">
      <span class="search-icon"></span>
    </div>

    CSS:

    .search-container {
      position: relative;
    }
    
    .search-icon {
      position: absolute;
      top: 50%;
      right: 10px;
      transform: translateY(-50%);
      width: 20px;
      height: 20px;
      background-image: url('path/to/search-icon.png');
      background-size: cover;
    }
    
    .search-input {
      padding-right: 30px;
    }

    حيث قمت بإنشاء عنصر <div> لتكون حاوية لعنصر الإدخال "input" وعنصر الرمز "span".

    ثم بتعيين الخاصية "position: relative" للعنصر الحاوي .search-container ليمكن تحديد موقع العناصر الفرعية بالنسبة له.

    وتحديد الخاصية "position: absolute" للعنصر الفرعي .search-icon ليمكن تحديد موقعه بالنسبة للحاوية.

    ثم استخدمت الخاصيات top, right, transform لتحديد موقع الرمز في الزاوية العلوية اليمنى ووسط العنصر، قمت أيضًا بتعيين خلفية للرمز باستخدام خاصية "background-image" وتحديد حجمها باستخدام "background-size".

    أخيرًا، تعديل حجم عنصر الإدخال "input" بإضافة الحشو على الجانب الأيمن ليسمح بوجود مساحة كافية لعرض الرمز داخل العنصر.

    ولا تنسى استبدال 'path/to/search-icon.png' بمسار الصورة الخاصة بأيقونة البحث، أو تستطيع استخدام أيقونة من Font Awesome.

    وإليك مثال إذا أردت استخدام Font Awesome:

    HTML:

    <!DOCTYPE html>
    <html>
    <head>
      <!-- استيراد Font Awesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    </head>
    <body>
      <div class="search-container">
        <input type="text" class="search-input">
        <span class="search-icon"><i class="fas fa-search"></i></span>
      </div>
    </body>
    </html>

    قمت بتحديد الأيقونة المستخدمة لرمز البحث باستخدام العنصر <i> ومنحها الفئات المناسبة .fas و .fa-search، حيث .fas تعني استخدام الأيقونات الخطية (Solid) و.fa-search تعني استخدام أيقونة البحث.

    CSS:

    .search-container {
      position: relative;
    }
    
    .search-icon {
      position: absolute;
      top: 50%;
      right: 10px;
      transform: translateY(-50%);
      width: 20px;
      height: 20px;
      color: #999; /* لتغيير لون الأيقونة */
    }
    
    .search-input {
      padding-right: 30px;
    }

     

    • أعجبني 1
  7. بتاريخ 50 دقائق مضت قال محمد الحربي:

    أخي هذه الدالة في ملف authAction.js 

    import {postDataApi} from "../../utils/fetchDataApi";
    
    export const login = (data) => async (dispatch) => {
        try {
            const res = await postDataApi(`login`, data)
            localStorage.setItem('login', true);
            dispatch({
                type: "AUTH" ,
                payload: {
                    token: res.data.access_token,
                    user: res.data.user
                }
            });
            localStorage.setItem('login', true);
            console.log(res)
        }

     

    وهذه الدالة في ملف login.jsx

    import {login} from "../../redux/actions/authActions.js";
    
    const handleChange = (e) => {
        const {name, value} = e.target;
        setUserData({...userData, [name]:value })
      }
      
      const handlevalid = async () => {
        if (auth.token) {setIsCorrect(true)}
        else {setIsCorrect(false)};
      };
    
      const handleLogin = async (e) => {
        e.preventDefault();
        setUserData({email, password })
        dispatch(login(userData))
        handlevalid()
        console.log(auth)
      }

    ولا أريد أن تبدأ دالة ()handlevalid أو console.log عملها إلا بعد انتهاء login التي في ملف authActions من عملها لأن أمر طباعة auth في ملف login يحدث قبل انتهاء عملية جلب البيانات فتتم طباعة أوبجكت فارغ بلا بيانات وبعدها مباشرة

    تتم طباعة الداتا في المتصفح بنجاح عملية جلب البيانات

    وعندما أضغط مرة أخرة على زر login تتم طباعة auth بأوبجكت يحتوي على بيانات 

    كما في الصورة المرفقة

    لكي تتأكد من أن الدالة handlevalid() وطباعة console.log(auth) تعملان بعد انتهاء عملية login()، عليك باستخدام مفهوم Promises في JavaScript.

    أي عدل الكود كما يلي في ملف authAction.js:

    import { postDataApi } from "../../utils/fetchDataApi";
    
    export const login = (data) => async (dispatch) => {
      try {
        const res = await postDataApi(`login`, data);
        localStorage.setItem('login', true);
        dispatch({
          type: "AUTH",
          payload: {
            token: res.data.access_token,
            user: res.data.user
          }
        });
        localStorage.setItem('login', true);
        console.log(res);
    
        return res; // يتم إرجاع الاستجابة لتصبح متاحة للدالة المستدعاة
      } catch (error) {
        // إدارة الأخطاء هنا
      }
    };

    في ملف login.jsx:

    import { login } from "../../redux/actions/authActions.js";
    
    const handleChange = (e) => {
      const { name, value } = e.target;
      setUserData({ ...userData, [name]: value });
    };
    
    const handlevalid = async () => {
      if (auth.token) {
        setIsCorrect(true);
      } else {
        setIsCorrect(false);
      }
    };
    
    const handleLogin = async (e) => {
      e.preventDefault();
      setUserData({ email, password });
    
      try {
        const res = await dispatch(login(userData)); // انتظر حتى انتهاء العملية
        console.log(res); // استخدم الاستجابة المتاحة هنا
    
        handlevalid();
        console.log(auth);
      } catch (error) {
        // إدارة الأخطاء هنا
      }
    };

    مع هذه التغييرات، الآن الدالة handleLogin() ستنتظر انتهاء العملية في login() باستخدام الكلمة المفتاحية await وستحتفظ بالاستجابة في المتغير res.

    بعد ذلك، تستطيع استخدام الاستجابة في console.log(res) أو أي عملية أخرى قبل استدعاء handlevalid() وconsole.log(auth).

     

  8. حاول تجربة استخدام المتغير العالمي $_SERVER['HTTP_REFERER'] في صفحة page.php للتحقق من الموقع الذي يحاول الوصول إلى الصفحة عبر iframe.

    وتستطيع التحقق من قيمة المتغير ومقارنتها بعنوان الموقع المسموح به (domain2.com)، وإذا كانت مختلفة، يمكنك عرض رسالة "غير مسموح".

    وإليك مثال لكود PHP بإمكانك استخدامه في صفحة page.php:

    <?php
    $allowedDomain = 'http://domain2.com';
    
    // التحقق من وجود قيمة referer ومقارنتها بالموقع المسموح به
    if (isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], $allowedDomain) !== 0) {
        echo "غير مسموح";
        exit;
    }
    
    // استمرار في عرض محتوى الصفحة
    ?>
    <!DOCTYPE html>
    <html>
    <head>
        <title>صفحة</title>
    </head>
    <body>
        <!-- محتوى الصفحة هنا -->
    </body>
    </html>

    ولاحظ أنه على الرغم من أن هذا الحل يعمل في معظم الحالات، إلا أنه يعتمد على قيمة $_SERVER['HTTP_REFERER'] التي يتم إرسالها من المستعرض، والتي قد تكون غير موثوقة في بعض الحالات.

    وربما من الأفضل استخدام حلول قائمة على الجانب الخادم، مثل .htaccess، إذا كنت ترغب في تعزيز الأمان.

  9. من الأفضل قراءة المستندات الخاصة بمكتبة Three.js وهي متوفرة بالعربية أيضًا من خلال الرابط التالي:

    حيث أنها ستوفر لك الطريقة السليمة لاستخدام المكتبة.

    Screenshot2023-05-24020030.thumb.png.5933a11468a546193da579773ac2afd8.png

    وبخصوص الكود الخاص بك لاحظي أنه في السكريبت لم يتم استدعاء GLTFLoader و DRACOLoader بشكل صحيح في الكود الخاص بك.

    فأنت قمت باستدعاء المكتبة باسم THREE وبالتالي يجب استيراد الدوال المرادة منها.

    والصحيح هو تعريف المتغيرات GLTFLoader و DRACOLoader واستخدامها فيما بعد، على النحو التالي:

    const loader = new THREE.GLTFLoader();
    const draco = new THREE.DRACOLoader();
    draco.setDecoderPath('/examples/jsm/libs/draco/');
    loader.setDRACOLoader(draco);

    حاولي استخدام الكود التالي حيث قمت باستيراد المكتبات عن طريق CDN وكتابة HTML والسكريبت في صفحة واحدة لمعرفة أين يقع الخطأ بالضبط:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="https://cdn.jsdelivr.net/npm/three@0.131.2/build/three.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/three@0.131.2/examples/js/loaders/GLTFLoader.js"></script>
        <title>3D</title>
        <style>
            body { margin: 0; overflow: hidden; }
        </style>
    </head>
    <body>
        <script>
            const scene = new THREE.Scene();
            const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.z = 5;
    
            const renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            const loader = new THREE.GLTFLoader();
            loader.load(
                'path/to/your/home.glb',
                function (gltf) {
                    scene.add(gltf.scene);
                },
                undefined,
                function (error) {
                    console.error('An error occurred while loading the model:', error);
                }
            );
    
            function animate() {
                requestAnimationFrame(animate);
                renderer.render(scene, camera);
            }
    
            animate();
        </script>
    </body>
    </html>

     

  10. حاول استخدام التعديل التالي على ملف .htaccess:

    RewriteEngine On
    RewriteBase /
    
    RewriteRule ^egypt/([^/]+)/?$ egypt.php?id=$1 [QSA,L]
    RewriteRule ^egypt/([^/]+)/([^/]+)/?$ egypt.php?id=$1&id1=$2 [QSA,L]
    RewriteRule ^egypt/([^/]+)/([^/]+)/([^/]+)/?$ egypt.php?id=$1&id1=$2&id3=$3 [QSA,L]

    وذلك التعديل يتيح لك استخدام الروابط التي تحددها بصورة صحيحة.

    الـRewriteRule الأولى تتعامل مع الرابط الأساسي، وتحوّل www.example.com/egypt/cairo/ إلى www.example.com/egypt.php?id=cairo. الـRewriteRule الثانية تتعامل مع رابط يحتوي على متغيرين، وتحوّل www.example.com/egypt/cairo/almaadi/ إلى www.example.com/egypt.php?id=cairo&id1=almaadi.

    أما الـRewriteRule الثالثة، فتتعامل مع رابط يحتوي على ثلاثة متغيرات، وتحوّل www.example.com/egypt/cairo/almaadi/rent/ إلى www.example.com/egypt.php?id=cairo&id1=almaadi&id3=rent.

    ويرجى التأكد من أنك قمت بتمكين مود Rewrite في خادم الويب الذي تستخدمه وأن ملف .htaccess موجود في المسار الصحيح. كما يجب أن يكون لديك صلاحيات القراءة والكتابة على ملف .htaccess.

  11. في البداية يجب تجنب الدخول لمشاهدة الدورات من أكثر من 3 أجهزة فذلك قد يعرض حسابك للإيقاف المؤقت لتفقد السبب.

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

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

    وأيضًا لا تنسى رفع المشروع الخاص بك على GitHub.

     

  12. السبب وراء وضع الـ abstract class في بداية قائمة الـ states في فلاتر BLOC هو لتوفير واجهة مشتركة لجميع حالات الحالة (states) المحتملة التي يمكن أن يتبعها Cubit أو Bloc.

    وباستخدام الـ abstract class ، تستطيع تعريف مجموعة محددة من الحالات الأساسية التي قد يعتمدها Cubit أو Bloc دون الحاجة إلى إعادة تعريف الأساليب الأساسية في كل مرة.

    والكود في الصورة، تم به تعريف NewestBooksState كـ abstract class وتنفيذها من قبل عدة حالات محددة، مثل NewestBooksInitial و NewestBooksLoading و NewestBooksFailure و NewestBooksSuccess.

    ومن خلال استخدام abstract class، تستطيع توحيد النهج وتطبيق المنطق المشترك بين حالات الحالة المختلفة، مثل توفير قائمة الممتلكات (props) المشتركة وأي أساليب أخرى ترغب في تعريفها لجميع حالات الحالة.

    أيضًا بوجود abstract class، بإمكانك استخدام المتغيرات من نوع NewestBooksState للإشارة إلى أي حالة من حالات الحالة، مما يسهل تحديد الحالة الحالية واتخاذ الإجراءات المناسبة في الـ Cubit أو Bloc الخاص بك.

    وسأقدم لك مثالًا يوضح كيفية استخدام الفئة المجردة (abstract class) في فلاتر BLOC، ولنفترض أن لدينا Cubit لإدارة حالة قائمة أحدث الكتب في تطبيق مكتبة.

    فتستطيع كتابة الفئات المختلفة على النحو التالي:

    import 'package:equatable/equatable.dart';
    
    abstract class NewestBooksState extends Equatable {
      const NewestBooksState();
    
      @override
      List<Object> get props => [];
    }
    
    class NewestBooksInitial extends NewestBooksState {}
    
    class NewestBooksLoading extends NewestBooksState {}
    
    class NewestBooksFailure extends NewestBooksState {
      final String error;
    
      const NewestBooksFailure(this.error);
    
      @override
      List<Object> get props => [error];
    }
    
    class NewestBooksSuccess extends NewestBooksState {
      final List<Book> books;
    
      const NewestBooksSuccess(this.books);
    
      @override
      List<Object> get props => [books];
    }

    هنا لدينا الفئة المجردة NewestBooksState التي تم تنفيذها من قبل عدة حالات محددة.

    وNewestBooksState يحتوي على المنطق المشترك لجميع حالات الحالة، والذي يشمل تنفيذ props لإعطاء معرف فريد لكل حالة، وذلك لتمكين المقارنة والتعامل مع التغييرات في الحالة بشكل فعال.

    • NewestBooksInitial: حالة البداية، ويمثل الحالة الأولية للقائمة.
    • NewestBooksLoading: حالة التحميل، ويشير إلى أن القائمة تحمل البيانات حاليًا.
    • NewestBooksFailure: حالة الفشل، ويشير إلى حدوث خطأ أثناء جلب البيانات، ويحتوي على رسالة الخطأ المحددة.
    • NewestBooksSuccess: حالة النجاح، ويشير إلى أن البيانات تم جلبها بنجاح، ويحتوي على قائمة الكتب الأحدث.

    وباستخدام الفئة المجردة NewestBooksState وحالاتها المحددة، يمكنك توحيد المنطق وإدارة حالة قائمة الكتب في Cubit الخاص بك، وإصدار حالة معينة باستخدام emit داخل Cubit بناءً على المنطق والأحداث التي تحدث في التطبيق.

  13. بتاريخ 6 دقائق مضت قال علي العبدالله:

    لقد اطلعت على المسارات ولم ارى React 

    بل ارى تقنيات مختلفة في المسارات الاخرى

     

    في دورة تطوير التطبيقات باستخدام لغة JavaScript  ستتعلم التالي:

    • الأسس البرمجية السليمة للغة JavaScript
    • الإضافات الحديثة في نسخة ES6 من اللغة
    • تطوير تطبيقات الخادم باستخدام بيئة Node.js
    • أساسيات مكتبة React.js وبناء تطبيق ملاحظات باستخدامها
    • أساسيات مكتبة React Native و Expo
    • تطوير تطبيق جوال للوصل بين الأطباء والمرضى بالاعتماد على React Native
    • التعرف على التطبيقات التي تتطلب اتصالًا مستمرًا بين المتصفح والخادم
    • بناء تطبيق محادثة يشبه تطبيق WhatsApp
    • إنشاء تطبيق أسئلة وأجوبة ونقاشات مع تصيير من جهة الخادم Server-side Rendering عبر إطار العمل Next.js
    • بناء واجهات أمامية باستخدام React.js مع مكتبة Material-UI
    • إنشاء تطبيقات سطح مكتب باستخدام JavaScript باستخدام إطار العمل Electron.js
    • بناء تطبيق جوال لشبكة تواصل اجتماعي باستخدام إطار العمل Ionic ومكتبة React.js

    وبخصوص React فستقوم بتعلم الأساسيات عن طريق بناء تطبيق ملاحظات Todo list، وبعد ذلك ستقوم ببناء مشروع كبير عبارة عن تطبيق محادثة يشبه تطبيق WhatsApp فالواجهة الأمامية ستكون عن طريق React والواجهة الخلفية بواسطة node.js.

    وأيضًا ستقوم ببناء نسخة لتطبيق الهاتف عن طريق React Native.

    وفي المشروع ستتعلم كيف يمكن إدارة عملية تسجيل الدخول وإنشاء الحسابات والتواصل عن طريق WebSockets والحماية والتحقق وقواعد البيانات و API.

    وأيضًا ستقوم ببناء  تطبيق أسئلة وأجوبة باستخدام Next.js وهو إطار مطلوب بشكل أساسي في سوق العمل بالنسبة لوظيفة React developer وأيضًا بتعلمك node.js ستصبح مطور Full stack مما يحسن فرصتك في البداية وستحصل على معرض أعمال قوي من خلال تلك المشاريع ولكن يجب التطبيق بمفردك بعد مشاهدة المدرب.

    • أعجبني 1
  14. لا يوجد دورة متخصصة في الأمن السيبراني ضمن أكاديمية حسوب، ولكن ستحتاج إلى دورة علوم الحاسوب حيث أنها أساسية إذا اردت التخصص في ذلك المجال.

    وإليك نقاش حول تلك الدورة:

    وبخصوص المسار الخاص بالأمن السيبراني فأنصحك بقراءة النقاش التالي حيث تم الإجابة بالتفصيل:

     

    • أعجبني 1
  15. قبل الدخول في مجال يجب إجراء بحث وافي، وتفقد المنافسين وحجم الزيارات وإمكانية المنافسة، وهل هناك مساحة لتوفير شيء جديد أو أفضل مما هو موجود؟

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

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

    وأيضًا لا تقم بحشو الكلمات في أسفل الموقع بل قم بكتابة نص يوضح طبيعة عمل الموقع وبه كلمة مفتاحية تستهدفها.

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

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

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

  16. ببساطة إذا كانت مواصفات حاسوبك غير كافية بالنسبة للمشروع الذي تعمل عليه، فتستطيع استخدام Google Colab،  حيث  المستخدمين المجانيين على Google Colab يحصلون على وصول مجاني إلى وحدات المعالجة الرسومية (GPU) ووحدات المعالجة الرسومية المتخصصة (TPU) لمدة تصل إلى 12 ساعة.

    ويتم توفير GPU runtime في Colab مع المواصفات التالية: وحدة المعالجة المركزية Intel Xeon @2.20 جيجاهرتز، 13 جيجابايت من ذاكرة الوصول العشوائي (RAM)، وحدة Tesla K80 للتسريع، و 12 جيجابايت من ذاكرة الوصول العشوائي GDDR5 VRAM.

    أما TPU runtime في Colab، فهو يتألف من وحدة المعالجة المركزية Intel Xeon @2.30 جيجاهرتز، 13 جيجابايت من ذاكرة الوصول العشوائي (RAM)، وحدة TPU سحابية بقوة حوسبة تصل إلى 180 تيرافلوبس.

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

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

    بعد انتهاء الـ 12 ساعة على Google Colab، يتم إلغاء جلسة العمل الحالية ويتعين عليك إعادة تشغيلها، ويعني ذلك أن أي عمل غير محفوظ سيتم فقده، بما في ذلك البيانات والنماذج والتعديلات التي تم إجراؤها خلال الجلسة.

    وتستطيع يمكنك حفظ النتائج والملفات الضرورية قبل انتهاء الجلسة الحالية، عن طريق حفظ البيانات في حساب Google Drive الخاص بك أو تنزيلها إلى جهاز الكمبيوتر الشخصي الخاص بك.

     أيضًا استخدام الوظيفة "Save a copy in Drive" في Google Colab لحفظ الدفتر الحالي في Google Drive قبل انتهاء الوقت المحدد.

    بتاريخ 1 ساعة قال Ali Ahmed39:

    شكرا جدا 

     

    بس بيئات العمل علي الحاسوب ممتع اكثر 

    وهل الماك بوك الجديد معالجه m2 في المجال

    افضل في مجال تعلم الاله

     

    معالجات m مصممة بواسطة Apple ومبنية على تقنية ARM، تتميز بأداء مذهل وكفاءة عالية في استخدام الطاقة.

    فمع معالج M2،  ستستفيد من أداء محسّن وتسارع لعمليات التعلم الآلي، ويحتوي المعالج M2 على مجموعة متنوعة من وحدات المعالجة المركزية ووحدات المعالجة الرسومية المتكاملة، مما يسمح بتنفيذ عمليات التعلم العميق بسرعة وكفاءة. بالإضافة إلى ذلك، يشتمل على وحدة Neural Engine التي توفر قدرات تسريع متقدمة لعمليات التعلم الآلي.

    ومن المهم أيضًا أن تنظر إلى الذاكرة والتخزين في الجهاز، حيث توفر MacBook الجديدة غالبًا ذواكر وتخزين فائقة السرعة، مما يساعد على تسريع عمليات التعلم الآلي وتحليل البيانات.

    ولكن إذا كان لديك كرت شاشة قوي على نظام الويندوز فستحصل على أداء مشابه حيث أن العامل الأساسي هو كرت الشاشة، يأتي بعده المعالج ثم الرامات.

     

    • أعجبني 1
  17.   

    بتاريخ منذ ساعة مضت قال Taieb Ahmed:

    شكرا على الرد ...

    انا لا افهم في البرمجة كثيرا لكن اظن ان هناك ملف PHP اسمه CurrencyController.php

    اظن انه يحتاج الى كود تخصيص ... مثلا نضع له شرط انه اذا كانت اللغة غير ar يكون الرمز symbol = dz 

    في هذا الملف يوجد كود changeCurrency أظن انه يمكن الاضافة او التعديل عليه بوضع شرط او دالة 

    الكود في الملف 

    public function changeCurrency(Request $request)
        {
            $currency = Currency::where('code', $request->currency_code)->first();
            $request->session()->put('currency_code', $request->currency_code);
            $request->session()->put('currency_symbol', $currency->symbol);
            $request->session()->put('currency_exchange_rate', $currency->exchange_rate);
        	flash(translate('Currency changed to ').$currency->name)->success();
        }
     

    كود خاص ب WordPress لاعطاء امر تحويل الرمز حسب تغير اللغة 

    add_filter('woocommerce_currency_symbol', 'change_existing_currency_symbol', 10, 2);
        
    function change_existing_currency_symbol( $currency_symbol, $currency ) {
         switch( $currency ) {
               case 'DA':           
                  if(ICL_LANGUAGE_CODE=='en'){
                      $currency_symbol = 'DA'; 
                  }else{
                     $currency_symbol = 'دج';  
                  }
               break;            
         }
         return $currency_symbol;
    }
     

    و انا احتاج الى كود خاص ب Laravel

    و لاصحاب الخبرة اليكم كود الملف كاملا ... ان كان هذا هو الملف الذي يجب عليه التخصيص ؟

    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use App\Models\Currency;
    
    class CurrencyController extends Controller
    {
        public function __construct() {
            // Staff Permission Check
            $this->middleware(['permission:currency_setup'])->only('currency','create','edit');
        }
    
        public function changeCurrency(Request $request)
        {
            $currency = Currency::where('code', $request->currency_code)->first();
            $request->session()->put('currency_code', $request->currency_code);
            $request->session()->put('currency_symbol', $currency->symbol);
            $request->session()->put('currency_exchange_rate', $currency->exchange_rate);
        	flash(translate('Currency changed to ').$currency->name)->success();
        }
    
        public function currency(Request $request)
        {
            $sort_search =null;
            $currencies = Currency::orderBy('created_at', 'desc');
            if ($request->has('search')){
                $sort_search = $request->search;
                $currencies = $currencies->where('name', 'like', '%'.$sort_search.'%');
            }
            $currencies = $currencies->paginate(10);
    
            $active_currencies = Currency::where('status', 1)->get();
            return view('backend.setup_configurations.currencies.index', compact('currencies', 'active_currencies','sort_search'));
        }
    
        public function updateYourCurrency(Request $request)
        {
            $currency = Currency::findOrFail($request->id);
            $currency->name = $request->name;
            $currency->symbol = $request->symbol;
            $currency->code = $request->code;
            $currency->exchange_rate = $request->exchange_rate;
            $currency->status = $currency->status;
            if($currency->save()){
                flash(translate('Currency updated successfully'))->success();
                return redirect()->route('currency.index');
            }
            else {
                flash(translate('Something went wrong'))->error();
                return redirect()->route('currency.index');
            }
        }
    
        public function create()
        {
            return view('backend.setup_configurations.currencies.create');
        }
    
        public function edit(Request $request)
        {
            $currency = Currency::findOrFail($request->id);
            return view('backend.setup_configurations.currencies.edit', compact('currency'));
        }
    
        public function store(Request $request)
        {
            $currency = new Currency;
            $currency->name = $request->name;
            $currency->symbol = $request->symbol;
            $currency->code = $request->code;
            $currency->exchange_rate = $request->exchange_rate;
            $currency->status = '0';
            if($currency->save()){
                flash(translate('Currency updated successfully'))->success();
                return redirect()->route('currency.index');
            }
            else {
                flash(translate('Something went wrong'))->error();
                return redirect()->route('currency.index');
            }
        }
    
        public function update_status(Request $request)
        {
            $currency = Currency::findOrFail($request->id);
            if($request->status == 0){
                if (get_setting('system_default_currency') == $currency->id) {
                    return 0;
                }
            }
            $currency->status = $request->status;
            $currency->save();
            return 1;
        }
    }
     

     

    حاول  إضافة شرط داخل دالة changeCurrency لتغيير رمز العملة بناءً على اللغة المحددة، وتستطيع استخدام دالة app()->getLocale() للحصول على اللغة المحددة في Laravel.

    public function changeCurrency(Request $request)
    {
        $currencyCode = $request->currency_code;
        $language = app()->getLocale();
        
        // تحديد رمز العملة بناءً على اللغة
        $currencySymbol = ($language == 'ar') ? 'دج' : 'DA';
        
        $currency = Currency::where('code', $currencyCode)->first();
        $request->session()->put('currency_code', $currencyCode);
        $request->session()->put('currency_symbol', $currencySymbol);
        $request->session()->put('currency_exchange_rate', $currency->exchange_rate);
        
        flash(translate('Currency changed to ') . $currency->name)->success();
    }

    قمت بإضافة شرط للتحقق من اللغة المحددة. إذا كانت اللغة 'ar' (عربي)، وسيتم تعيين رمز العملة إلى 'دج'، وإلا سيتم تعيينه إلى 'DA'.

    احفظ التعديلات واختبر الموقع عند تغيير لغة الموقع للتحقق من تغيير رمز العملة بناءً على اللغة المحددة، ويرجى ملاحظة أنه قد تحتاج إلى إعادة تشغيل الخادم أو مسح ذاكرة التخزين المؤقت لتطبيق السكريبت (مثل مسح مجلد bootstrap/cache في Laravel) لتطبيق التغييرات يدويًا أو من خلال الأمر:

    php artisan optimize:clear

     

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

    بخصوص التمرين الأول سأجيب عليه لتوضيح طريقة الحل، وسأترك باقي الأسئلة لك لحلها:

    1. عليك بإنشاء متغيرين لتتبع الأعداد التي ستتم طباعتها، واحد للترتيب التصاعدي والآخر للترتيب التنازلي.
    2. تهيئة المتغيرين بقيمة صفر.
    3. استخدمي حلقة التكرار (حلقة for أو حلقة while) للتكرار من 1 إلى 100.
    4. داخل الحلقة، قم بإجراء الخطوات التالية:
    5. افحصي إذا كان المتغير الخاص بالترتيب التصاعدي أقل من 100، فإذا كان الشرط صحيحًا، قومي بطباعة القيمة وزيادة المتغير بواحد.
    6. افحصي إذا كان المتغير الخاص بالترتيب التنازلي أقل من 100، وإذا كان الشرط صحيحًا، قومي بزيادة المتغير بواحد.
    7. بعد انتهاء الحلقة، ستكون قد تم طباعة الأعداد المطلوبة.

    ومخطط التدفق سأتركه لك لحله، وهنا شرح ومصادر ستفيدك:

    وبخصوص خريطة التدفق فقومي بقراءة التالي:

    وأيضًا بعض المصادر المفيدة.

     

  19. أرجو منك إرفاق الكود في سؤالك من خلال الضغط على الكود <> عند كتابة السؤال.

    ومن الصعب تحديد بالضبط ما هي المشكلة التي تواجهها في رمز React الذي قدمته، حيث يجب تحديد ما الذي تريد فعله وشرحه بالضبط، وأيضًا توفير مجلد المشروع إن أمكن.

    ومع ذلك، هناك بعض الأخطاء الواضحة في الرمز التي يمكن تصحيحها:

    في البداية، يجب أن تتأكد من تشغيل كود React داخل وحدة الإرسال الصحيحة. يجب أن يتم وضع الكود داخل مكون React مثل class App extends React.Component ويتم استدعائه في ReactDOM.render().

    وأيضًا عليك باستخدام className بحرف c صغير وليس كبير C

    والدالة map التي تستخدمها لتكرار this.state.users غير صحيحة، حيث يجب أن تكون هناك قوسين مستديرين بعد map لتحديد الدالة المراد تنفيذها على كل عنصر.، مثلاً:

    this.state.users.map((ele) => { // code }).

    أيضًا يجب أن يكون لديك عناصر users صحيحة داخل المصفوفة.

    حالياً، لديك قوسين مفتوحين بدون أي شيء داخلهما قبل العنصر الأول وبعد العنصر الثاني في المصفوفة يجب أن تتأكد من تنسيق البيانات بشكل صحيح.

     

  20. 1- ستجد خيار باسم setup & configurations اضغط عليه ومنه اختر Languages.

    2- قم بإختيار اللغة الإفتراضية للموقع من الأعلى ثم اضغط save.

    3- ستجد خيار باسم add new language قم بالضغط عليه واكتب ar وسيظهر لك العربية اخترها ثم احفظ من خلال save

    4- بجانب اللغة العربية قم بتفعيل الزر الخاص بتحويل تنسيق الموقع من اليمين إلى اليسار RTL.

    5- ستجد بجانب اللغة العربية زر الترجمة بجانب علامة القلم اضغط عليه ثم بترجمة العملة كما تريد.

    Screenshot(18).thumb.png.e0ad614dcdde9dbe9ad7873d1bcad225.png

     

  21. تجاهلي الرسالة التالية:

     packages are looking for funding run `npm fund` for details

    حيث أنه يخبرك بتنفيذ الأمر npm fund، وسيتم عرض قائمة بجميع الوحدات والحزم التي قمت بتثبيتها والتي تم إنشاؤها بواسطة شركات أو منظمات تحتاج إلى دعم مالي لمشاريعها في مجال تقنية المعلومات.

    وستظهر لك قائمة بصفحات الويب التي يمكنك من خلالها إرسال الأموال لهذه الشركات أو المنظمات.

    وتستطيعي تعطيل ظهور تلك الرسالة عن طريق الأمر التالي:

    npm config set fund false --global

    وبخصوص parcel

    من الأفضل استخدام parcel بشكل محلي داخل المشروع وليس global، لذلك عليك بحذف النسخة التي قمتي بتحميلها بشكل global بالأمر التالي:

    npm un parcel -g

    بعد ذلك تثبيت الحزمة بالشكل التالي:

    npm install --save-dev parcel

    وتستطيعي تشغيل المشروع من خلال الأمر التالي مباشرًة:

    npx parcel src/index.html

    ولاحظي أنه يتم تشغيل الملف index.html في مجلد src.

    والأفضل استخدام السكريبت  في ملف package.json بالشكل التالي:

    {
      "name": "my-project",
      "source": "src/index.html",
      "scripts": {
        "start": "parcel",
        "build": "parcel build"
      },
      "devDependencies": {
        "parcel": "latest"
      }
    }

    ولاحظي أنه في source تم تحديد الملف الرئيسي للمشروع، وتستطيعي تشغيل المشروع الآن عن طريق الأمر npm start.

    وتستطيعي قراءة الشرح الخاص بـ Parcel من المستند الرسمي:

     

    • شكرًا 1
  22. عندما يتعلق الأمر بتخزين البيانات في قاعدة البيانات، هناك عدة طرق يمكن اتباعها، وسأقدم لك بعض الأفكار العامة حول كيفية تخزين البيانات التي تم توضيحها في استفسارك.

    بالنسبة للخانات الثابتة، بإمكانك اتخاذ قرار بين تخزين القيم المباشرة أو استخدام المعرفات والربط ببيانات أخرى.

    ولنستخدم مثالك "اسم الكتاب: أبيض وأسود".

    تستطيع أن تقرر تخزين النص "أبيض وأسود" مباشرة كقيمة في قاعدة البيانات وجعلها حقلًا في الجدول الخاص بالمواضيع، أو باستطاعتك إنشاء جدول منفصل للكتب وتخزين تفاصيل الكتب فيه، مع إضافة حقل يحمل معرف الكتاب في جدول المواضيع للإشارة إلى الكتاب المحدد.

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

    مثلاً، إضافة حقول مثل "اسم الكتاب بالعربية" و "اسم الكتاب بالإنجليزية"، وبمثل هذا النهج، يمكن للتطبيق استخدام النص المناسب بناءً على لغة تفضيل المستخدم أو اختياراته.

    وتذكر أن الطريقة الأفضل والصحيحة لتخزين البيانات تعتمد على احتياجات تطبيقك.

    ,إذا كنت تستخدم قاعدة بيانات Firebase، فإنها توفر لك بنية لتخزين البيانات تعتمد على مفهوم الوثائق والمجموعات في قاعدة البيانات.

    حيث أن في Firebase، يتم تخزين البيانات في وثائق (Documents)، وهي هيكل تخزين قابل للتنفيذ يتكون من مجموعة من الحقول وقيمها. يمكنك أن تنظر إلى الوثيقة كإدخال مستقل في قاعدة البيانات.

    وبناءً على ما تم شرحه، تستطيع تخزين الخانات الثابتة (مثل نوع المشاركة ونوع الكتاب ورقم الإصدار) كحقول في وثيقة الموضوع، وتخزين القيم المباشرة لهذه الخانات مباشرة في حقولها بقاعدة البيانات.

    مثلاً، إنشاء وثيقة لكل موضوع وتتضمن حقولًا مثل "عنوان الموضوع" و "نوع المشاركة" و "نوع الكتاب" و "رقم الإصدار"، وتخزين القيم المدخلة من المستخدمين في هذه الحقول.

    في Firebase، بإمكانك أيضًا تخزين قيم متعددة لنفس الحقل باستخدام مفهوم المصفوفات. وبالتالي، تستطيع تخزين أسماء الكتب بالعربية والإنجليزية في نفس الحقل، مثل ["أبيض وأسود", "Black and White"].

     

    • شكرًا 1
  23. الدالة الأولى:

    function increase(num) {
        num++;
        console.log(num);
    }

    تستقبل معامل واحد يُسمى num، وداخل الدالة، يتم استخدام المعامل المؤقت ++ لزيادة قيمة num بمقدار واحد.

    ثم طباعة القيمة المحدثة لـ num، في هذه الحالة، سيتم زيادة قيمة num من 1 إلى 2، وبعد ذلك ستُطبع القيمة 2.

    الدالة الثانية:

    function increase(number) {
        return number++;
    }

    الدالة أيضًا تستقبل معامل واحد يُسمى number، داخل الدالة، يستخدم المعامل المؤقت ++ لزيادة قيمة number بمقدار واحد.

    ومع ذلك، يتم إرجاع القيمة الأصلية لـ number (قبل زيادتها)، حيث ستُرجع الدالة قيمة 1 (القيمة الأصلية لـ number) وليس القيمة المحدثة (2).

    ولكن ما السبب؟

    السبب يكمن في المعامل ++، فهو معامل يُستخدم لزيادة قيمة متغير بمقدار واحد.

    وهناك فرق بين استخدام ++ قبل اسم المتغير وبعده.

    فإذا استخدمته قبل اسم المتغير ويعرف باسم pre-increment:

    ++num

    ستتم زيادة قيمة المتغير ومن ثم يتم استخدام القيمة المحدثة. أما إذا استخدمته بعد اسم المتغير، ويعرف باسم post-increment:

    num++،

    فسيتم استخدام القيمة الأصلية للمتغير ومن ثم يتم زيادة قيمته.

    مثال لتوضيح الاستخدام:

    let num = 1;
    console.log(++num); // ستُطبع القيمة 2 (تم زيادة القيمة قبل الاستخدام)
    console.log(num++); // ستُطبع القيمة 2 (ت

    بمعنى أنك لو أردت أن يتم إرجاع قيمة 2 من الدالة الثانية وليس 1 عليك تعديل المعامل ليصبح قبل المتغير بالشكل التالي:

    function increase(number) {
        return ++number;
    }

     

    • شكرًا 1
×
×
  • أضف...