-
المساهمات
5196 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
52
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Adnane Kadri
-
يمكنك إما حذف , إخفاء , تعطيل أو حتى إزالة التفاعلية من الزر بعد إستيفاء الغرض منه ( عرض الفيديو ) لتجنب المشكل من الأساس . يمكنك ذلك عن طريق التعديل إلى أحد الأكواد : <!-- حذف الزر --> <button onclick="launchVideo();$(this).remove();">افتح الفيديو</button> <!-- إخفاء الزر --> <button onclick="launchVideo();$(this).hide();">افتح الفيديو</button> <!-- تعطيل الزر --> <button onclick="launchVideo();$(this).attr('disabled', true);">افتح الفيديو</button> <!-- إلغاء تفاعلية الزر --> <button onclick="launchVideo();$(this).attr('onclick', '');">افتح الفيديو</button>
- 6 اجابة
-
- 1
-
إن كنت تقصد تطبيق طريقة الكود الأول في طريقة وضع الفيديو من الكود الثاني (أي إظهار الفيديو بعد الضغط على الزر في كلتا الحالتين , الأولى و الثانية ) فيمكنك ذلك عن طريق : إنشاء الزر و إضافة حدث عند الضغط عليه : <button onclick="launchVideo();">افتح الفيديو</button> إنشاء عنصر الفيديو و تضمينه بالصفحة : <div class="videoyoutube"><div class="video-responsive"><div class="video-youtube loader lazyload" data-src="//player.vimeo.com/video/90429499"></div></div></div> تعريف الدالة المسؤولة عن بدء الفيديو على هذا النحو : function launchVideo() { $(".video-youtube") .each(function(){ var iframe = '<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>'; $(this).replaceWith(iframe); }); } فيكون الكود كاملا على هذا النحو : <button onclick="launchVideo();">افتح الفيديو</button> <div class="videoyoutube"> <div class="video-responsive"> <div class="video-youtube loader lazyload" data-src="//player.vimeo.com/video/90429499"> </div> </div> </div> <script> function launchVideo() { $(".video-youtube") .each(function(){ var iframe = '<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>'; $(this).replaceWith(iframe); }); } </script> هذا سيقوم بتضمين الفيديو بعد الضغط على الزر فقط . بنفس الطريقة فم بإضافة الزر المسؤول عن ملئ الشاشة أسفل عنصر الفيديو : <div id="demo-element"> <button id="go-button" style="background-position: 0% 100%, 100% 0%, 0px 0px, 0px 0px; background-repeat: no-repeat; border-radius: 8px; display: inline-block; font: 25px calibri, Tajawal, sans-serif; padding: 10px 20px; position: relative; text-decoration: none; text-shadow: rgba(255, 255, 255, 0.4) 1px 1px 0px; vertical-align: baseline; white-space: nowrap;">افتح الفيديو في كامل الشاشة</button> </div> ثم قم بإضافة التفاعلية الخاصة بالزر بعد الضغط على تشغيل الفيديو (الموصوفة في التعليق السابق) . ربما قد تحتاج بعض التنسيقات الإضافية . فيكون الكود كاملا مشابها للتالي : <style> #go-button{ background-position: 0% 100%, 100% 0%, 0px 0px, 0px 0px; background-repeat: no-repeat; border-radius: 8px; display: inline-block; font: 25px calibri, Tajawal, sans-serif; padding: 10px 20px; position: relative; text-decoration: none; text-shadow: rgba(255, 255, 255, 0.4) 1px 1px 0px; vertical-align: baseline; white-space: nowrap; } </style> <button onclick="launchVideo();">افتح الفيديو</button> <div class="videoyoutube"> <div class="video-responsive"> <div class="video-youtube loader lazyload" data-src="//player.vimeo.com/video/90429499"> </div> </div> </div> <div id="demo-element"> <button id="go-button">افتح الفيديو في كامل الشاشة</button> </div> <script> // قم ببدء الفيديو function launchVideo() { $(".video-youtube") .each(function(){ var iframe = '<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>'; $(this).replaceWith(iframe); }); // إضافة تفاعلية لزر ملئ الشاشة setEventForGoButton(); // إضافة تفاعلية لنص الزر handleFullScreen(); } function handleFullScreen() { $(document).on('fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange', function() { if(IsFullScreenCurrently()) { $("#demo-element span").text('opn'); $("#go-button").text('bak'); } else { $("#demo-element span").text('bak'); $("#go-button").text('opn'); } }); } function setEventForGoButton() { $("#go-button").on('click', function() { if(IsFullScreenCurrently()) GoOutFullscreen(); else GoInFullscreen($("#demo-element").get(0)); }); } function GoInFullscreen(element) { if(element.requestFullscreen) element.requestFullscreen(); else if(element.mozRequestFullScreen) element.mozRequestFullScreen(); else if(element.webkitRequestFullscreen) element.webkitRequestFullscreen(); else if(element.msRequestFullscreen) element.msRequestFullscreen(); } function GoOutFullscreen() { if(document.exitFullscreen) document.exitFullscreen(); else if(document.mozCancelFullScreen) document.mozCancelFullScreen(); else if(document.webkitExitFullscreen) document.webkitExitFullscreen(); else if(document.msExitFullscreen) document.msExitFullscreen(); } function IsFullScreenCurrently() { var full_screen_element = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement || null; if(full_screen_element === null) return false; else return true; } </script>
- 6 اجابة
-
- 1
-
أظن أن قصدك "وضع الكود الثاني و الثالث بداخل الأول" (و هذا تحقيقا للغرض المطلوب). لا حاجة لذلك , يمكنك فصل كل الدوال بحسب المهمة و من ثم إستدعاءهم في دالة واحدة . بداية يمكنك تبسيط العملية أكثر عن طريق التالي : قم بوضع كل الأكواد الأول و الثاني و الثالث بداخل دوال على هذا النحو (وهذا بحسب مبدأ فصل الإهتمامات) : function openVideoFile() { if(!$('#iframe').length) { $('#iframeHolder').html('<iframe id="iframe" src="//player.vimeo.com/video/90429499" width="700" height="450"></iframe>'); } } و : function putVideoInPage() { setTimeout(function(){$(".video-youtube").each(function(){$(this).replaceWith('<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>')})},5e3); } و : function GoInFullscreen(element) { if(element.requestFullscreen) element.requestFullscreen(); else if(element.mozRequestFullScreen) element.mozRequestFullScreen(); else if(element.webkitRequestFullscreen) element.webkitRequestFullscreen(); else if(element.msRequestFullscreen) element.msRequestFullscreen(); } function GoOutFullscreen() { if(document.exitFullscreen) document.exitFullscreen(); else if(document.mozCancelFullScreen) document.mozCancelFullScreen(); else if(document.webkitExitFullscreen) document.webkitExitFullscreen(); else if(document.msExitFullscreen) document.msExitFullscreen(); } function IsFullScreenCurrently() { var full_screen_element = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement || null; if(full_screen_element === null) return false; else return true; } و : function setEventForGoButton() { $("#go-button").on('click', function() { if(IsFullScreenCurrently()) GoOutFullscreen(); else GoInFullscreen($("#demo-element").get(0)); }); } و : function handleFullScreen() { $(document).on('fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange', function() { if(IsFullScreenCurrently()) { $("#demo-element span").text('opn'); $("#go-button").text('bak'); } else { $("#demo-element span").text('bak'); $("#go-button").text('opn'); } }); } ثم يمكنك دمج و إستدعاء كل الدوال بعد الضغط على زر تشغيل الفيديو على هذا النحو : $(function(){ $('#button').click(function(){ // تضمين الفيديو في الصفحة openVideoFile(); // وضع رابط فيديو بصفحة النشر بدون وضع اكواد فريم putVideoInPage(); // إضافة التفاعلية لزر ملئ الشاشة setEventForGoButton(); // تغيير النصوص بحسب وضع ملئ الشاشة // #demo-element span النصوص المعرفة بـ handleFullScreen(); }); }); ملاحظات : الكثير من الأكواد غير واضحة المهمة في الأكواد التي أرفقتها و لا يظهر بالنسبة لي أي ترابط بين الكود الثاني و الأكواد الأخرى , و رغم ذلك قد قمت بتضيمنها في الأكواد التي وصفتها لك (يمكن لأن ذلك راجع إلى غياب باقي عناصر الصفحة ) . يمكنك تتبع نفس المنطق لكتابة دالة تجمع عمل كل الدوال المعرفة (ألف دالة تقوم بألف مهمة أفضل من دالة تقوم بألف مهمة) , سيكون الكود أفضل قراءة و أكثر وضوحا.
- 6 اجابة
-
- 1
-
لا يمكنك طباعة كل المتغيرات مرة واحدة , عوضا عن ذلك يجب تمرير اسم المتغير لتتم القراءة بشكل صحيح أثناء البناء , و ببساطة هذا ﻷن متصفح الواجهة الأمامية نفسه ليس له أي وصول لملف البيئة فالعملية تخص الخادم وحده و لذلك أثناء البناء يتم إستبدال أي متغير معرف على هذا النحو : process.env.MY_VAR بقيمته الفعلية و يتم البناء بشكل عادي . في حين أن المتغير : process.env يتم تجاهله بطبيعة الحال و يتم إعادة كائن فارغ عن طريقه . فعوضا عن طباعة كل المتغيرات يمكنك فقط طباعة المتغير الذي تحتاج و إستعماله بشكل عادي .
- 2 اجابة
-
- 1
-
لما لا تقوم فقط بتحميله تزامنيا ثم تضمينه بالصفحة ؟ componentDidMount() { // script إنشاء عنصر بوسم const script = document.createElement("script"); // تعريف المسار أو الرابط script.src = "/path/to/my_scripts.js"; // تفعيل التزامن و الوصول اليه script.async = true; script.onload = () => this.scriptLoaded(); // تضمينه في البودي document.body.appendChild(script); }
- 2 اجابة
-
- 1
-
يمكنك تضمين useLocation من @reach/router و من ثم قراءة القيمة على هذا النحو : import * as React from 'react'; import { useLocation } from '@reach/router'; const Current = () => { const location = useLocation(); console.log(location); }; سيتم طباعة كائن يسهل قراءة الخواص منه على هذا النحو : { pathname: "/", href: "http://localhost:8000/", origin: "http://localhost:8000" }
-
يمكنك استبدال المسار الأخير (تأكد أنه الأخير دوما) على هذا النحو : <Route component = {NotFound} /> // هذا <Redirect to="/" /> // بهذا سيتم تتبع كل المسارات التي تختلف عن المسارات التي هي ما قبل هذا المسار و بدل عرض مكون react سيعاد توجيه المستخدم إلى الصفحة الرئيسية . و يمكنك عمل ذلك عن طريق مكتبة Gatspy على هذا النحو : ليكن في العلم أن صفحة 404 المنشئة من طرف المكتبة تكون بـ src/pages/404.jsx أو src/pages/404.js يمكنك تعديلها على هذا النحو لتقوم بنفس المهمة : import React from 'react' import { navigate } from 'gatsby' const NotFoundPage = () => { return navigate('/') } export default NotFoundPage
-
هل يمكنك ذكر نوع محرر النصوص الذي تستخدمه ؟ أو على الأقل إرفاق صورة لذلك
-
و هذا هو دور مطوري الواجهة الخلفية و قواعد البيانات . فهم المسؤولون عن جعل عملية إضافة المنتجات ( أو أي نوع اخر من المدخلات ) في قاعدة البيانات و التحكم بها عملية بسيطة من خلال واجهة إدخال يهتم مطور الواجهة الأمامية بتصميمها . يستعملون لإدارة قواعدة البيانات أشياء من مثل MySQL , MongoDB , Oracle , SQLServer , Redis .. الخ . أو ربما بعض اليات التخزين المؤقتة من مثل varnish , Memcached , redis .. الخ . و يحتاجون على الأقل للغة برمجة لهندسة الواجهة الخلفية و تولي كل الأشياء التي تحدث على مستوى الخادم . لغات من مثل Java , Python , Ruby , Php , .net .. الخ . فالمواقع من مثل مثالك لا تكتمل إلا بجزئيها و واجهتيها , الأمامية و الخلفية .
-
تقريبا هي نفس العملية و كل خطوة من الاتي تتبع نفس منطق كل خطوة من التعليق السابق . بداية يجب عليك الإتصال بقاعدة البيانات <?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; // إنشاء اتصال $conn = new mysqli($servername, $username, $password, $dbname); // تفحص الإتصال و طباعة الأخطاء ان وجدت if ($conn->connect_error) { die("فشل الإتصال بقاعدة البيانات: " . $conn->connect_error); } كتابة الإستعلام بشكل string : <?php $sql = "INSERT INTO YourTableName (column1, column2, column3) VALUES ('value 1', 'value 2', 'value 3')"; عمل Excution للإستعلام المطبوع حديثا : <?php if ($conn->query($sql) === TRUE) { echo "تم ادراج عنصر جديد بقاعدة البيانات"; } else { echo "خطأ: " . $sql . "<br>" . $conn->error; } فيكون الكود كاملا : <?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; // إنشاء اتصال $conn = new mysqli($servername, $username, $password, $dbname); // تفحص الإتصال و طباعة الأخطاء ان وجدت if ($conn->connect_error) { die("فشل الإتصال بقاعدة البيانات: " . $conn->connect_error); } // طباعة إستعلام $sql = "INSERT INTO YourTableName (column1, column2, column3) VALUES ('value 1', 'value 2', 'value 3')"; // تنفيذ الإستعلام if ($conn->query($sql) === TRUE) { echo "تم ادراج عنصر جديد بقاعدة البيانات"; } else { echo "خطأ: " . $sql . "<br>" . $conn->error; } و قد تحتاجين إغلاق الإتصال أحيانا , يمكنك ذلك عن طريق : <?php // تنفيذ إغلاق الإتصال $conn->close();
-
هل يمكنك تفعيل الDebug Mode و إرفاق الأخطاء التي ظهرت ؟ سيساعد هذا في حل المشكل أكثر يمكنك ذلك عن طريق تعديل ملف php.ini . قم بتغيير قيمتي error_reporting و display_errors , إلى : error_reporting = E_ALL display_errors = On ملاحظة : طبعا لا ينبغي وضع الأكواد حرفيا فهي وصفية و إنما يجب صياغة نفس المنطق في كتابة كود مشابه أو تنسيق الكود بما يلائم تضمينه
- 14 اجابة
-
- 2
-
هل يمكنك وصف المشاكل التي واجهتها أو أي أخطاء ظهرت ؟
- 14 اجابة
-
- 1
-
بإستخدام phpmyadmin يمكنك ذلك عن طريق : التصفح إلى http://localhost/phpmyadmin الدخول إلى قاعدة البيانات المقصودة بالقائمة الجانبية . الضغط على زر SQL في قائمة التصفح أعلى الصفحة . طباعة إستعلام الإدراج و الضغط على GO , يكون كود الإستعلام على هذا النحو : INSERT INTO blood_groups (blood_group_name) VALUES ('O+'); INSERT INTO benefactor (fk) VALUES (/* من جدول الفصائلid قم بطباعة اخر */); ملاحظات : يجب مراعاة القيم الإفتراضية للأعمدة بالجداول السابقة و التأكد من أن لها قيم إفتراضية بالفعل . لا ينصح بإدخال البيانات يدويا إلا في حالات إستثنائية , عوضا عن ذلك يمكنك فعل ذلك بالـ php .
- 3 اجابة
-
- 2
-
كل الخطوات صحيحة و سليمة , يبدوا أن المشكلة في إستعمال سرفر smtp . قم بتغيير العنوان إلى : smtp.googlemail.com أي MAIL_HOST بملف الإعداد على هذا النحو : MAIL_DRIVER=smtp MAIL_HOST=smtp.googlemail.com MAIL_PORT=465 MAIL_USERNAME=YOUR_EMAIL_ADDRESS MAIL_PASSWORD=PASSWORD MAIL_ENCRYPTION=ssl و لا تنسى محو الكاش : php artisan cache:clear php artisan config:cache
- 2 اجابة
-
- 1
-
لو أحببت أن تترك الأمر لجانب الباك اند فقط فيمكنك تطبيق العملية وفق المنطق التالي : جلب كل العناصر الغير مميزة . جلب العناصر المميزة . تكرار العناصر المميزة كذا مرة . دمج العناصر المميزة مع غير المميزة وفق ترتيب معين . مثال عملي : يمكنك جلب كل العناصر التي لا تحتوي على 1 في حقل المنتج المميز على هذا النحو : $sql = "SELECT * FROM Prodect WHERE is_special = 0 ORDER BY RAND()"; ثم جلب العناصر المميزة و تكرارها : <?php // تحضير الاستعلام $sql2 = "SELECT * FROM Prodect WHERE is_special=1 ORDER BY RAND()"; function getRepeated($query) { $repeat_times = 10; $counter = 0; $rows = []; $result = mysql_query($query); // تحضير كل الحقول while($row == mysql_fetch_row($result)) { $rows[] = $row; } // تحضير مصفوفة تحمل عناصر مميزة ومكررة $repeated = []; for($index = 0; $counter < $repeat_times; $counter++) { $repeated[] = $rows[$i]; $index++; // إعادة الدور إلى الصفر لملئ المصفوفة بعناصر مكررة if($index == count($rows)) { $index = 0; } } return $repeated; } $special = getRepeated($sql2); المزج وفق الترتيب و التكرار : <?php $non_special = [...]; // ناتج الاستعلام الاول $special = [...]; // ناتج الاستعلام الثاني مكرر $total = []; $offset = 0; for($i = 0; $i < count($non_special); $i++) { if(is_float($i / 10)) { array_push($total ,$non_special); } else { // قطعة من مصفوفة المنتجات المميزة لدمجها $pieceOfSpecial = array_slice($special,$offset,5); $offset += 5; array_merge($total ,$pieceOfSpecial); } } // =======> return $total الان ستسهل عملية عرضها مباشرة تحديث : يمكن أن لا تكون هناك أي حاجة من تكرار العناصر المميزة كذا مرة لدمجها مع الغير مميزة و يمكن تحقيق نفس الغرض في حالة جلب عدد معين من العناصر المميزة . فتكون عوض الخطوة كاملة و عوضا عن اقتطاع المصفوفة كل مرة في المرحلة الأخيرة يمكنك فقط دمج المصفوفة كلها (قد يكون هذا البديل مفيد في حالة وجود عدد محدود جدا من العناصر المميزة بقاعدة البيانات) .
- 14 اجابة
-
- 2
-
تحديث : يمكنك أيضا إضافة الevents المتعلقة بالخيارات المنشئة بعد إضافتها . مثال : function setListeners(){ document.querySelectorAll('select#products option').addEventListener('click' ,function(){ // }); } ومن ثم إنشاء الأحداث بعد إنشاء العناصر : function getProducts(target) { let getProducts = new XMLHttpRequest(); getProducts.open('GET', '/invoices/getProducts/' + target); getProducts.onload = function() { if (this.readyState === 4 && this.status === 200) { // succes let products = JSON.parse(this.responseText); products.forEach(function(item) { let option = document.createElement('option'), text = document.createTextNode(item['product_name']); option.appendChild(text); option.value = item['id']; productsSelect.appendChild(option); }); setListeners(); // إستدعاء الدالة } else { alert('لقد حدث خطأ غير متوقع'); } } getProducts.send(); }
- 5 اجابة
-
- 1
-
يبدوا أن المشكلة في تحديد العناصر فقط : و بالفعل فإن العنصر select بالمعرف products غير موجود من ضمن الDOM . عوضا عن ذلك يوجد بالمعرف product فتكون : var productsSelect = document.getElementById('product'); ثم تحتاج إستدعاء الدالة getProducts من المكان الصحيح , أي بعد أي تغير في قائمة الأقسام على هذا النحو : <select name="section" onchange="getProducts(this.value)" class="form-control @error('section') is-invalid @enderror" id="section"> <option value="NULL" disabled>إختر القسم</option> أو أيضا : document.getElementById('section').addEventListener('change' ,getProducts(this.value)); فيكون كود الجافاسكربت كاملا على هذا النحو : var productsSelect = document.getElementById('product'); document.getElementById('section').addEventListener('change' ,getProducts(this.value)); function getProducts(target) { let getProducts = new XMLHttpRequest(); getProducts.open('GET', '/invoices/getProducts/' + target); getProducts.onload = function() { if (this.readyState === 4 && this.status === 200) { // succes let products = JSON.parse(this.responseText); products.forEach(function(item) { let option = document.createElement('option'), text = document.createTextNode(item['product_name']); option.appendChild(text); option.value = item['id']; productsSelect.appendChild(option); }); } else { alert('لقد حدث خطأ غير متوقع'); } } getProducts.send(); }
-
بشكل عام . فكرة الكوبونات , قسائم الشراء و البرومو كودس هي أشياء يتم تقديمها للعملاء كحافز للشراء , وقد تكون خصم نسب مئوية معينة ,خصم مبلغ معين ثابت أو حتى الشحن و التوصيل المجاني و ربما أفكار أخرى . أما إن كنت تقصد الكوبونات كمفهوم برمجي فيمكن معاملتها كغيرها من المفاهيم و من ثم إستعمالها في عمليات حساب سعر المنتج و الدفع . مثال عملي عن الإستعمال : قم بإنشاء جدول كوبونات بقاعدة البيانات يحوي الأعمدة : coupon_code // معبرا عن كود الكوبون coupon_type // معبرا عن نوع الكوبون coupon_amount // معبرا عن مقدار الخصم بحيث ينحصر نوع الكوبون في الأنواع الثلاثة الممثلة بأرقام 1,2,3,على التوالي , بـ : 1 => fixed_card_amount // مبلغ خصم ثابت 2 => percentage_off // خصم نسبة مئوية 3 => free_shipping // شحن مجاني 2. في نموذج إدخال كود الكوبون بصفحة الدفع قم بالتحقق من وجود كوبون يحمل نفس الكود المدرج أو لا . 3. إن كان نعم يمكنك تحديد نوع و مقدار الكوبون . 4. و من ثم عمل العملية الحسابية لحساب السعر الجديد و إظهاره للمستخدم . (طبعا يجب أخذ الحيطة و إدراج إحتمال التلاعب بالسعر و التصرف وفق ذلك , مثال :تخزين السعر في الباك اند بعد إدخال كود كوبون أكثر أمانا ) . طبعا هذا هو الشكل الأبسط للعملية , و هي وصفية بحتة يمكنك تطبيقها باللغة التي تبرمج وفقها . كما يمكنك إضافة الكثير من المميزات مثل : كوبون للمسجلين حديثا فقط , كوبون بتاريخ إنتهاء صلاحية , كوبون بعدد منتهي للإستعمال .. إلخ .
- 2 اجابة
-
- 1
-
الوظيفة openssl_cipher_iv_length هي جزء من مكتبة openSSL PHP المضمنة في اعتمادات الphp بالفعل . في حالات قد يكون هذا الإمتداد مثبتا بالفعل , فيمكنك مباشرة تفعيله عن طريق تعديل ملف الإعداد php.ini مثل ما قام الأخ @يوسف احمد9بالإشارة . إن لم تحل المشكلة يستحسن تحديث إعتمادات اللارافل الخاصة بالمشروع , يمكنك ذلك عن طريق الأمرين : composer install composer update و في أحيان أخرى لن يكون الإمتداد مثبتا و هذا قد يدفعك إلى تحميل ملف الـ dll الخاص بالإضافة ( ssleay32.dll ) و من ثم إضافته إلى مجلد الphp . ملاحظات : قد تحتاج إعادة تشغيل السرفر في هذا الأمر أو الأمر الأول .
-
يمكنك إرسال طلب إلى نقطة الوصول هاته للتحويل من عملة معينة إلى أخرى : https://data.fixer.io/api/convert ? access_key = API_KEY & from = GBP & to = JPY & amount = 25 كما يمكنك جلب معدلات التحويل بالنسبة لعملة رئيسية عن طريق هاته النقطة : https://data.fixer.io/api/2013-12-24 ? access_key = API_KEY & base = USD & symbols = JPY,CAD,EUR,DZD لاحظ أنه قم تم تخصيص تاريخ معين يتم فيه جلب معدل التحويل الخاص بذاك التاريخ . يمكنك جعل العملية ديناميكية عن طريق : const date = new Date().toISOString().slice(0, 10); ثم تمرير الثابت date . لاحظ أيضا أنه يمكنك تخصيص العديد من العملات في مرة واحدة و هذا شيء جميل . مثال عن رد من التوثيق الرسمي للواجهة : { "success": true, "historical": true, "date": "2013-12-24", "timestamp": 1387929599, "base": "GBP", "rates": { "USD": 1.636492, "EUR": 1.196476, "CAD": 1.739516 } }
- 11 اجابة
-
- 1
-
أسعار العملات بالنسبة لعملة رئيسية و معدلات التحويل الخاصة بها متغيرة في الغالب و تحتاج ديناميكية لوضع الأسعار . تستطيع إما تخزين السعر بالدولار كـ base currency و من ثم جعل عملية التحويل ديناميكية عن طريق معدل تحويل . لا أظن أنه توجد حزمة جاهزة لتقوم بالعملية . لكن يمكنك إستعمال أحد هاته الـ APIS : هذا أو هذا لجلب معدلات التحويل من الدولار أو من أي base currency تستعملها . كما يمكنك مباشرة إرسال طلبات GET إلى نقطة الوصول هاته فقط و قراءة الخاصية geoplugin_currencyConverter لجلب معدل التحويل الذي يخص بالمستخدم نفسه (الذي تم إرسال الطلب عن طريقه) من الدولار من الرد مباشرة أيضا (مثلا لإظهار العملة بحسب بلد المستخدم حسب تحليل الـ IP) . أيا كانت طريقتك في جلب معدل التحويل يمكن حساب السعر الجديد بسهولة عن طريق : var new_price = base_price * exchange_rate_base_to_target /*من الرسبونس*/; و كإقتراح لتحسين تجربة المستخدم و جعل عملية تثبيت العملة المحول إليها سهلة , قم بتخزين العملة و معدل التحويل في الجلسة أو الكوكي أو التخزين المحلي بدل إرسال طلب مع كل مرة . ملاحظات : يمكنك أيضا الإستغناء عن هاته العملية ككل و إدخال أسعار لمختلف العملات في حالة كان عدد العملات محدود جدا و تريد تحكم أكبر في الأسعار بحسب البلد أو العملة (خذ إحتمال أسعار السوق السوداء مثلا , فهي لا ترسل في الردود من أي API و قد تحتاجها لوضع تسعيرة معقولة في حال كان هنالك تباعد كبير بين سعر الصرف و سعر السوق السوداء) . و بنفس منطق واجهات التطبيق البرمجية المشار إليها يمكنك تخصيص نقطة وصول لجلب معدلات التحويل بتطبيقك نفسه و ليكن من جدول تنشأه : معدلات التحويل exchange_rates , و من ثم التحكم في هاته المعدلات على نطاق أوسع و التعديل بما يلائم سعر الصرف الحالي أو السعر الذي يناسب فرع المتجر بالعملة الفلانية .
- 11 اجابة
-
- 2
-
يمكنك رفع الملفات من المشروع إلى المستودع المحلي عن طريق اﻷمرين : أولا : // إضافة كل الملفات المعدلة git add -A // إضافة ملفات محددة git add changedDirectory // أو git add changedFile ثم : git commit -m "A changes title" و أخيرا رفع الملفات إلى الـبرانش الخاص بك على الـ remote repo عن طريق : git push -u origin yourBranch ستلاحظين اخر commit قمت بعمله على المستودع الخاص بك على هذا النحو :
- 5 اجابة
-
- 1
-
لك الخيار في أن تقوم مباشرة بإستعمال المكتبة التي تقدمها و ربطها مع الـ Laravel كمكتبة خارجية أو بإستعمال أحد الحزم التي تبسط العملية . ولعل هاته الحزمة الأفضل على الإطلاق.
- 7 اجابة
-
- 1
-
لا حاجة لتشفير الـ ID لحل المشكلة فعليا , عوضا عن ذلك يمكنك إنشاء دالة أو middleware يقوم بالتحقق من ملكية العنصر item قبل عمل أي تعديلات عليه . مثال عملي : <?php class YourController extends Controller { public function editItem(Request $request ,Item $item){ if(! $this->isOwner($item)){ return 'لا يمكنك تعديل العنصر'; } // تكملة العملية } private function isOwner($item){ if(auth()->user()->id == $item->user_id){ return true; } return false; }
- 3 اجابة
-
- 1
-
في العادة إرسال رسائل sms قد تحتاج تكلفة و إشتراك لتطبيق العملية و الإستعانة بها. و يمكنك تطبيق العملية كلها وحدك مثل ما أشار الأخ @بلال زيادة. وقد تحتاج الإستعانة بأحد هاته الواجهات Twilio أو Plivo . مثال عن إرسال رسالة بإستعمال Twilio : <?php use Twilio\Rest\Client; # إرسال رسالة ... $client = new Client($account_sid, $auth_token); # تعطى مع حساب تويليو $client->messages->create($receiverNumber, [ 'from' => $twilio_number, # يعطى مع حساب تويليو 'body' => $activation_code ]); # قم تخزين الكود ... $currentUser->update([ 'activation_code' => $activation_code , ]); ثم براوت اخر يمكنك عمل المصادقة بشكل مشابه : <?php ... if($user_input == $activation_code){ $current_user->update([ 'phone_is_activated' => true, ]); return 'أنت مفعل'; } return 'كود التفعيل خاطئ'; و بالطبع فإن هذا هو الشكل الأبسط للعملية , يمكنك إضافة العديد من الأشياء كإنتهاء صلاحية الكود أو ربط كود التفعيل بمودل اخر غير مودل المستخدم و غيرها . كما يمكنك إستعمال حزم جاهزة مثل هاته الحزمة بحيث توفر عليك الكثير من الأشياء من مثل الError Reporting و كل الBack end Logic بحيث تقوم بإرسال بيانات إلى نقاط وصول معينة و القراءة من الرد . و مثل ما تقدم هذا في نفس الوقت هي تزيل عنك حرية التصرف و التطوير بما يلائم مشروعك .
- 7 اجابة
-
- 2