-
المساهمات
5256 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
52
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Adnane Kadri
-
يمكنك تضمين 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
-
-
يبدوا أن المشكلة فقط في تعريفك للـ Routes فلو كانت المشكلة في إظهار الview فسيتم رمي exception عن طريق ViewException من داخل المتحكم . فهذا يعني أن الطلب لا يصل أصلا إلى المتحكم و المشكلة فقط هي في سطر واحد . Route::get('user/profile', [UserConroller::class, 'edit']); وبالفعل فأنت تستخدم تعريفا من النسخة 8 من لارافل في حين أنك تستخدم لارافل 5 و تقوم بإستعمال سياق غير مدعم بعد (PHP callable syntax) على هذا النحو : <?php use App\Http\Controllers\UserController; .. Route::get('user/profile', [UserController::class, 'edit']); // غير مدعوم بعد في حين أنه في النسخ ما قبل 8.x يجب عليك تعريف الراوت على هذا النحو (string syntax) : <?php Route::get('user/profile', 'UserController@edit'); و ستحل المشكلة بهذا . ملاحظات : مثل ما شرح الزملاء فإنه يوجد لديك بعض الأخطاء يجب إصلاحها و ذلك في UserConroller تصبح UserController و في oute تصبح Route و هذا : <?php public function edit() { # $user = User::find(auth()->user()->id); عوضا عن هذا $user = auth()->user(); # هذا /* * ولا داعي لتمرير المتغير يوزر أصلا * بحيث يمكنك استعمال هذا المساعد * auth() * بداخل ملفات الblade */ return view('auth.profile',compact('user')); } بعد ذلك , وكخطوات إضافية , تأكد أن تقوم بمحو الكاش عن طريق : php artisan route:clear ثم تأكد أن الراوت موجود عن طريق : php artisan route:list و أخير يمكنك التصفح إلى http://127.0.0.1:8000/user/profile كعضو مسجل و استعراض الصفحة .
-
إن كنت تعتمد على تخزين محلي فقط يمكنك تخزين الملفات إما في الـ public_path أو الـ storage_path . في الحالة الأولى ستكون جميع الملفات و الصور المخزنة ظاهرة للعامة و يمكن الوصول إليها ببساطة . تخزن الملفات في : public > your-folder و يكون التخزين على هذا النحو : <?php .. $request->file('image')->move(public_path('your-folder'), $name); في الحالة الثانية لن يمكن إستدعاء الصور و الملفات إلا عن طريق إنشاء رابط symlink و هاته الطريقة أكثر أمانا و حفظا للخصوصية في حالة ما كانت الملفات و الصور المخزنة حساسة أو خاصة . افتراضيا يتم تخزين هاته الصور و الملفات في : storage > app > public > your-folder و التخزين على هذا النحو : <?php .. $request->file('image')->move(storage_path('your-folder'), $name); علما أنه يمكنك إدارة و إنشاء ديسكات التخزين بملف config/filesystems.php : <?php ... 'disks' => [ ... 'storage-path' => [ 'driver' => 'local', 'root' => storage_path('app').'/uploads', ], 'public-path' => [ 'driver' => 'local', 'root' => public_path().'/uploads', 'url' => env('APP_URL').'/public_files', 'visibility' => 'public', ] ... ], ملاحظة : يمكنك إنشاء الsymlink عن طريق طباعة الأمر : php artisan storage:link
- 4 اجابة
-
- 1
-
-
بداية , لا يمكنك تخزين أي ملفات بقاعدة البيانات Sql , عوضا عن ذلك يمكنك إستخدام الfile systems لتخزين الصورة أو الملف و تخزين باث الصورة أو الملف في قاعدة البيانات . يتم إستقبال الطلب من قبل اللارافل و معالجته على هذا النحو : <?php public function uploadImg(Request $request) { // التحقق إن كان الطلب يحمل ملف باسم image if($request->hasFile('image')) { // انشاء اسم بلاحقة للملف $name = time()."_".$request->file('image')->getClientOriginalName(); // تخزين الملف بالpublic path $request->file('image')->move(public_path('images'), $name); } // return response()->json([ asset("images/$name"), // باث الصورة 201, // كود الحالة 'message' => asset("images/$name") ? 'تم حفظ الصورة' : 'failed' ]); }
- 4 اجابة
-
- 2
-
-
يمكنك الإستعانة بهاته الحزمة لتحقيق الغرض. بداية قم بتثبيت الحزمة عن طريق مدير الحزم : npm install react-ga --save 2. تضمين الموديلات اللازمة بملف App.js : import ReactGA from "react-ga"; 3. مصادقة غوغل انالتكس مع الحزمة , أيضا قم بتعريف ثابت بشكل globally (سنأتي لإستعماله في الخطوة التالية): ReactGA.initialize("TRACKING-ID"); const history= createHistory(window); 4. بداخل وسم LocationProvider بالراوتر قم بتعريف الخاصية history و قم بإرفاقها بالثابت الذي تم تعريفه على هذا النحو : <LocationProvider history={history}> <Router> .. </Router> </LocationProvider> الان يتم رصد أي تغيير يخص الكائن window . ينبغي الان فقط الإستماع لهاته التغيرات و التصرف بناءا عليها . مثال : history.listen( window => { ReactGA.pageview(window.location.pathname + window.location.search); }); و هذا جواب سؤالك :
