-
المساهمات
1388 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
16
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Sam Ahw
-
لإرسال بريد الكتروني في لارافيل نقوم بالخطوات التالية: أولاً: نقوم بوضع معلومات البريد الالكتروني الصحيحة ضمن ملف .env وهي (عنوان البريد الالكتروني، كلمة المرور، رقم المنفذ ،وبقية التفاصيل التي تختلف بحسب نوع البريد الالكتروني مثل gmail أو غيره) كالتالي: MAIL_DRIVER = smtp MAIL_HOST = smtp.gmail.com MAIL_PORT = 587 MAIL_USERNAME = your-gmail-username عنوان البريد الالكتروني الذي سيقوم بإرسال الرسائل MAIL_PASSWORD = your-application-specific-password كلمة المرور MAIL_ENCRYPTION = tls ثم نقوم بإنشاء متحكم controller ونسميه MailController لإدارة إرسال الرسائل كالتالي: php artisan make:controller MailController وهو بدوره بقوم بالتالي: <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Mail; use App\Http\Requests; use App\Http\Controllers\Controller; class MailController extends Controller { //التابع الذي سيقوم بإرسال الرسالة public function basic_email() { //نعرف هنا اسم المرسل $data = array('name'=>"firstname lastname"); Mail::send(['text'=>'mail'], $data, function($message) { $message->to('abc@gmail.com'')->subject ('Laravel Basic Testing Mail'); //عنوان الرسالة $message->from('xyz@email.com','Sender Name'); // عنوان واسم المرسل }); //طباعة رسالة تأكيد echo "Basic Email Sent. Check your inbox."; } } يوجد أيضاً العديد من الأمثلة الممتعة في حالات مختلفة مثل إرسال بريد الكتروني وتنسيقه بهيئة HTML وإضافة مستندات مع الرسالة والعديد من الخصائص الأخرى التي يمكنك الاطلاع عليها من التوثيق الرسمي في موقع لارافيل
- 3 اجابة
-
- 2
-
إن العلاقات متعددة الأشكال هي أن يكون لديك نماذج يمكن أن تنتمي إلى أكثر من كيان واحد. يحتفظ هذا النوع من النماذج بالبنية نفسها التي لا تتغير بغض النظر عن النموذج الآخر المرتبط به. من الأمثلة الشائعة على هذا النوع من السيناريوهات هي (التعليقات). في مدونة على سبيل المثال ، يمكن أن توضع التعليقات على منشور محدد أو على صفحة مستقلة مع الحفاظ على الهيكل نفسه بغض النظر عما إذا كان منشور أو صفحة. أي بمعنى آخر ستبقى جميع الخصائص للتعليق ثابتة مثل (الاسم، تاريخ التعليق، محتوى التعليق،...). مع أخذ المثال المذكور أعلاه في الاعتبار ، لدينا كيانان: Post و Page. للحصول على تعليقات على كل منها ، يمكننا أن نقرر إنشاء قاعدة بياناتنا على النحو التالي: posts: id الرقم المعرف للمقال title عنوان المقال content محتوى المقال posts_comments: id رقم معرف فريد post_id الرقم المعرف للمقال comment التعليق date تاريخ التعليق pages: id الرقم المعرف للصفحة body محتوى الصفحة pages_comments: id رقم معرف فريد page_id الرقم المعرف للصفحة comment التعليق date تاريخ التعليق ولكن نلاحظ أنه باعتماد النهج السابق، وجب علينا إنشاء جدولين للتعليقات، جدول للتعليقات الخاص بالصفحة، وجدول آخر للتعليقات الخاصة بالمنشور أو المقال. وكليهما يقومان بنفس الدور تماماً ويحتويان نفص الخصائص، إنما الاختلاف الوحيد هو بالمكان الذي يتواجدان فيه (مرة بالمنشور ومرة أخرى بالصفحة). مع استخدام العلاقات المتعددة، يمكننا تبسيط البينة السابقة ومنع التكرار الذي حصل، فتصبح لدينا بنية الجداول كالتالي: posts: id الرقم المعرف للمنشور title عنوان المنشور content محتوى المنشور pages: id الرقم المعرف للصفحة body محتوى الصفحة comments: id الرقم المعرف للتعليق commentable_id الرقم المعرف للمكان الذي يوجد فيه التعليق (أي رقم معرف للصفحة أو رقم معرف للمنشور) commentable_type نوع المكان الهدف (صفحة أو منشور) date تاريخ التعليق body محتوى التعليق وبذلك نلاحظ لدينا عمودين جديدين مهمين يجب الانتباه إليهما: commentable_id و commentable_type. وبدورهما قاما باختصار تكرار جدول التعليق مرتين وتكرار البيانات. وهذا ببساطة هو مفهوم العلاقات المتعددة الأشكال. الآن لنأخذ المثال السابق ونقوم بتضمينه ضمن لارافيل: عند إنشاء الجداول للتهجير نقوم بالتالي: Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->text('content'); }); Schema::create('pages', function (Blueprint $table) { $table->increments('id'); $table->text('body'); }); Schema::create('comments', function (Blueprint $table) { $table->increments('id'); $table->morphs(‘comment’); //-> ستنشئ تلقائيًا عمودين باستخدام النص الذي تم تمريره إليه $table->text('body'); $table->date('date'); }); بوضع morphs سيقوم تلقائياً بإنشاء العمودين commentable_id و commentable_type. ثم عند إنشاء جدول التعليقات يمكننا تعريف دالة تساعدنا بالحصول على أي مودل آخر يملك تعليق (أي يمكننا مباشرة الحصول على تعليقات المنشور و تعليقات الصفحة) بدالة واحدة بدلاً من اللجوء لآليات أخرى أكثر تعقيداً، كالتالي: <?php namespace App; use Illuminate\Database\Eloquent\Model; class Comment extends Model { //باستخدام هذا التابع نستطيع الآن أن نحصل على أي مودل يملك تعليق أي مودل الصفحة ومودل المنشور public function commentable() { return $this->morphTo(); } } وعند إنشاء الجدول الهدف (الكيان الذي سيحوي التعليقات) على سبيل المثال جدول المنشور: namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model { //هذه الدالة ستقوم باستعادة جميع التعليقات الموجودة على منشور محدد public function comments() { return $this->morphMany('App\Comment', 'commentable'); } } نلاحظ قمنا باستخدام morphMany للدلالة بأن المنشور قد يحوي عدة تعليقات، وبذلك نستطيع الحصول على كافة التعليقات الموجودة على هذا المنشور. وكذلك الأمر طبعاً بالنسبة (للصفحة) نكرر الخطوة السابقة morphMany. يمكنك أيضاً الاطلاع على باقي أشكال العلاقات وأنواع العلاقات متعددة الأشكال الأخرى من التوثيق الرسمي في لارافيل.
- 2 اجابة
-
- 3
-
في الدورة يقوم المدربون بتزويدك بجميع الأدوات اللازمة لبناء الموقع الالكتروني وأماكن تحميلها مثل محرر الأكواد الذي ستقوم باستعماله أو أي أداة أخرى، ويتم فيها أيضاً شرح كافة التفاصيل اللازمة عن كيفية تحميل الأدوات اللازمة واستخدامها وأساسيات اللغات البرمجية المستخدمة في بناء المواقع. حيث أن عملية بناء الموقع الالكتروني هي عملية برمجية، ولا يوجد برنامج نقوم بتحميله لبناء الموقع لنا، ولكن يوجد محرر نصوص يقوم المبرمج بكتابة الشيفرة البرمجية ضمنه لبناء الموقع الالكتروني، وكذلك يوجد العديد من الأدوات الأخرى التي تساعد المبرمج في مهمته.
-
لا أعلم في حال كان الكود الذي قمت بكتابته هنا كاملاً لأنني لم ألاحظ مكان وجود رابط الاتصال مع paypal ولكن يجب عليك تغييره من api.sandbox إلى api.paypal وعادة يتم تقسيم الكود إلى 3 ملفات للسهولة، سأقوم بوضع مثال شامل لك لكي تستطيع الاستفادة منه بشكل كامل: أولاً ملف PaypalServices.dart وهو الملف المسؤول عن الاتصال مع paypal: import 'package:http/http.dart' as http; import 'dart:async'; import 'dart:convert' as convert; import 'package:http_auth/http_auth.dart'; class PaypalServices { String domain = "https://api.sandbox.paypal.com"; // for sandbox mode للتجربة فقط // String domain = "https://api.paypal.com"; // for production mode عند النشر نقوم باستخدام هذا الرابط // هنا يجب عليك استبدال المعلومات التالية بمعلومات حسابك String clientId = 'Ab4vS4vmfQFgUuQMH49F9Uy3L1FdNHtfGrASCyjNijm_EkHWCFM96ex0la-YFbwavw41R3rTKU3k_Bbm'; String secret = 'EDjvPfYgTYqdYWR2BfOiBW4dz_jeeuadqH7Z98pZMDvY33PcViiooqYFWVPFSGbfKBfNOb3LnroSI1hv'; // for getting the access token from Paypal Future<String> getAccessToken() async { try { var client = BasicAuthClient(clientId, secret); var response = await client.post('$domain/v1/oauth2/token?grant_type=client_credentials'); if (response.statusCode == 200) { final body = convert.jsonDecode(response.body); return body["access_token"]; } return null; } catch (e) { rethrow; } } // for creating the payment request with Paypal Future<Map<String, String>> createPaypalPayment( transactions, accessToken) async { try { var response = await http.post("$domain/v1/payments/payment", body: convert.jsonEncode(transactions), headers: { "content-type": "application/json", 'Authorization': 'Bearer ' + accessToken }); final body = convert.jsonDecode(response.body); if (response.statusCode == 201) { if (body["links"] != null && body["links"].length > 0) { List links = body["links"]; String executeUrl = ""; String approvalUrl = ""; final item = links.firstWhere((o) => o["rel"] == "approval_url", orElse: () => null); if (item != null) { approvalUrl = item["href"]; } final item1 = links.firstWhere((o) => o["rel"] == "execute", orElse: () => null); if (item1 != null) { executeUrl = item1["href"]; } return {"executeUrl": executeUrl, "approvalUrl": approvalUrl}; } return null; } else { throw Exception(body["message"]); } } catch (e) { rethrow; } } // for executing the payment transaction Future<String> executePayment(url, payerId, accessToken) async { try { var response = await http.post(url, body: convert.jsonEncode({"payer_id": payerId}), headers: { "content-type": "application/json", 'Authorization': 'Bearer ' + accessToken }); final body = convert.jsonDecode(response.body); if (response.statusCode == 200) { return body["id"]; } return null; } catch (e) { rethrow; } } } الملف الثاني وهو PaypalPayment.dart المسؤول عن عرض webview التي ستقوم بدورها بعرض واجهة الدفع، وفي المثال التالي تم عرض شراء منتج موبايل على سبيل المثال كالتالي: import 'dart:core'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'PaypalServices.dart'; class PaypalPayment extends StatefulWidget { final Function onFinish; PaypalPayment({this.onFinish}); @override State<StatefulWidget> createState() { return PaypalPaymentState(); } } class PaypalPaymentState extends State<PaypalPayment> { GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); String checkoutUrl; String executeUrl; String accessToken; PaypalServices services = PaypalServices(); // you can change default currency according to your need Map<dynamic,dynamic> defaultCurrency = {"symbol": "USD ", "decimalDigits": 2, "symbolBeforeTheNumber": true, "currency": "USD"}; bool isEnableShipping = false; bool isEnableAddress = false; String returnURL = 'return.example.com'; String cancelURL= 'cancel.example.com'; @override void initState() { super.initState(); Future.delayed(Duration.zero, () async { try { accessToken = await services.getAccessToken(); final transactions = getOrderParams(); final res = await services.createPaypalPayment(transactions, accessToken); if (res != null) { setState(() { checkoutUrl = res["approvalUrl"]; executeUrl = res["executeUrl"]; }); } } catch (e) { print('exception: '+e.toString()); final snackBar = SnackBar( content: Text(e.toString()), duration: Duration(seconds: 10), action: SnackBarAction( label: 'Close', onPressed: () { // Some code to undo the change. }, ), ); _scaffoldKey.currentState.showSnackBar(snackBar); } }); } // item name, price and quantity String itemName = 'iPhone X'; String itemPrice = '1.99'; int quantity = 1; Map<String, dynamic> getOrderParams() { List items = [ { "name": itemName, "quantity": quantity, "price": itemPrice, "currency": defaultCurrency["currency"] } ]; // checkout invoice details String totalAmount = '1.99'; String subTotalAmount = '1.99'; String shippingCost = '0'; int shippingDiscountCost = 0; String userFirstName = 'Gulshan'; String userLastName = 'Yadav'; String addressCity = 'Delhi'; String addressStreet = 'Mathura Road'; String addressZipCode = '110014'; String addressCountry = 'India'; String addressState = 'Delhi'; String addressPhoneNumber = '+919990119091'; Map<String, dynamic> temp = { "intent": "sale", "payer": {"payment_method": "paypal"}, "transactions": [ { "amount": { "total": totalAmount, "currency": defaultCurrency["currency"], "details": { "subtotal": subTotalAmount, "shipping": shippingCost, "shipping_discount": ((-1.0) * shippingDiscountCost).toString() } }, "description": "The payment transaction description.", "payment_options": { "allowed_payment_method": "INSTANT_FUNDING_SOURCE" }, "item_list": { "items": items, if (isEnableShipping && isEnableAddress) "shipping_address": { "recipient_name": userFirstName + " " + userLastName, "line1": addressStreet, "line2": "", "city": addressCity, "country_code": addressCountry, "postal_code": addressZipCode, "phone": addressPhoneNumber, "state": addressState }, } } ], "note_to_payer": "Contact us for any questions on your order.", "redirect_urls": { "return_url": returnURL, "cancel_url": cancelURL } }; return temp; } @override Widget build(BuildContext context) { print(checkoutUrl); if (checkoutUrl != null) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).backgroundColor, leading: GestureDetector( child: Icon(Icons.arrow_back_ios), onTap: () => Navigator.pop(context), ), ), body: WebView( initialUrl: checkoutUrl, javascriptMode: JavascriptMode.unrestricted, navigationDelegate: (NavigationRequest request) { if (request.url.contains(returnURL)) { final uri = Uri.parse(request.url); final payerID = uri.queryParameters['PayerID']; if (payerID != null) { services .executePayment(executeUrl, payerID, accessToken) .then((id) { widget.onFinish(id); Navigator.of(context).pop(); }); } else { Navigator.of(context).pop(); } Navigator.of(context).pop(); } if (request.url.contains(cancelURL)) { Navigator.of(context).pop(); } return NavigationDecision.navigate; }, ), ); } else { return Scaffold( key: _scaffoldKey, appBar: AppBar( leading: IconButton( icon: Icon(Icons.arrow_back), onPressed: () { Navigator.of(context).pop(); }), backgroundColor: Colors.black12, elevation: 0.0, ), body: Center(child: Container(child: CircularProgressIndicator())), ); } } } وأخيراً، الملف الرئيسي الذي سيحوي زر عند الضغط عليه سيقوم بتحويلك إلى واجهة paypal السابقة، makePayment.dart: import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'PaypalPayment.dart'; class makePayment extends StatefulWidget { @override _makePaymentState createState() => _makePaymentState(); } class _makePaymentState extends State<makePayment> { TextStyle style = TextStyle(fontFamily: 'Open Sans', fontSize: 15.0); final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: new Scaffold( backgroundColor: Colors.transparent, key: _scaffoldKey, appBar: PreferredSize( preferredSize: Size.fromHeight(45.0), child: new AppBar( backgroundColor: Colors.white, title: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Paypal Payment Example', style: TextStyle( fontSize: 16.0, color: Colors.red[900], fontWeight: FontWeight.bold, fontFamily: 'Open Sans'), ), ], ), ), ), body:Container( width: MediaQuery.of(context).size.width, child: Container( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ RaisedButton( onPressed: (){ // make PayPal payment Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) => PaypalPayment( onFinish: (number) async { // payment done print('order id: '+number); }, ), ), ); }, child: Text('Pay with Paypal', textAlign: TextAlign.center,), ), ], ), ) ), ) ); } } بالتوفيق،
- 5 اجابة
-
- 1
-
لجلب آخر سجل تمت إضافته في جدول ما في لارافيل يمكنك الاعتماد على قيمة حقل created_at واستخدام latest كالتالي: return DB::table('files')->latest('created_at')->first(); ويوجد أيضاً طريقة أخرى عن طريق ترتيب النتائج باستخدام orderBy واستخدام desc للترتيب من الأكبر إلى الأصغر ثم أخذ أول قيمة كالتالي: return DB::table('files')->orderBy('created_at', 'desc')->first(); أما لجلب سجلات عشوائية من الجدول يمكنك استخدام تابع مختصر تقدمه لارافيل كالتالي: User::all()->random(1); حيث تستطيع تمرير عدد السجلات التي ترغب بجلبها. وفي حال كنت تستعمل نسخة أقدم من لارافيل يمكنك تنفيذ ذلك باستخدام إحدى الطريقتين: أولاً عن طريق Eloquent: public function index() { $data = DB::table('users') ->inRandomOrder() ->limit(1) ->get(); } أو عن طريق المودل Model كالتالي: public function index() { $data = User::inRandomOrder() ->limit(1) ->get(); }
- 8 اجابة
-
- 1
-
مرحباً @hanan fahad11، إنه كغيره من المواقع الالكترونية البسيطة والتي تتألف من صفحة واحدة أو عدة صفحات ويمكن تصميمه عن طريق HTML, CSS و الجافاسكريبت، وبالطبع يمكن استعمال أطر عمل محددة أو تقنيات أخرى لتسهيل العمل ولكنها ليست إلزامية. لمساعدتك في المستقبل في حال شككت في موقع ما عن التقنيات المستخدمة في بنائه فيوجد العديد من المواقع على الانترنت التي تقدّم هذه الخدمة عن طريق عرض جميع التقنيات المستخدمة في الموقع. أما فيما يخص تطبيقات الموبايل فيمكن تنفيذها إما عن طريق Android و Swift أو باستخدام Flutter وبالتالي يتم كتابة كود التطبيق في مكان واحد ويمكن إخراجه إلى المنصتين معاً بنفس الوقت. بالتوفيق،
-
مرحباً @Marwan800، من رسالة الخطأ يبدو بأنك لم تقم بتنصيب الإضافات اللازمة وهي Flutter و Dart، ولحل هذه المشكلة نتبع الخطوات التالية: أولاً: نقوم بفتح برنامج Android Studio ثانياً: نتوجه إلى الشريط العلوي ثم SDK Manager ثالثاً: من التبويب اليساري نختار Plugins أو إضافات رابعاً: نقوم بالبحث عن Flutter و Dart ونقوم بالضغط على زر تحميل. وأخيراً، سيطلب منك بعد ذلك بإعادة تشغيل Android Studio بالتوفيق،
- 6 اجابة
-
- 1
-
مرحباً @Bahaeddine Touati، يجب عليك أيضاً إضافة الدومين الفرعي إلى حسابك ضمن Google Adsense كالتالي: أولاً: بعد تسجيل الدخول نتوجه إلى قائمة المواقع sites. ثانياً: نقوم بالضغط على السهم الموجود بجانب اسم الموقع الرئيسي ثم نختار إظهار التفاصيل (Show Details). ثالثا: نقوم بالظغط على إضافة نطاق فرعي (Add new subdomain) رابعاً: نقوم بإدخال النطاق الفرعي الجديد، ثم نضغط على الزر إضافة (Add). وبذلك سيتم ظهور الإعلانات أيضاً على الدومين الفرعي. ملاحظة، قد يتطلب بعض الوقت لتفعيل الإعلانات على الدومين الفرعي الجديد الذي قمت بإضافته. بالتوفيق،
- 2 اجابة
-
- 1
-
مرحباً @Hanan Fahad، إن كانت المشكلة بكلمة مرور Mysql بعد تنصيبه، فيمكنك مباشرةً الدخول إلى قواعد البيانات عن طريق الأمر التالي: mysql -u root وفي حال قمت بوضع كلمة مرور أثناء التحميل، وقد نسيت كلمة المرور فيمكن إعادة تعيينها باتباع الخطوات التالية: أولاً: نقوم بإيقاف mysql في حال كان يعمل عن طريق الأمر التالي: sudo systemctl stop mysql ثانياً: نقوم بإعادة إقلاع سيرفر mysql مع منعه من التحقق من الصلاحيات عن طريق الأمر التالي: sudo mysqld_safe --skip-grant-tables --skip-networking & ثالثاً: الآن يمكنك الدخول إلى سيرفر mysql من جديد عن طريق الأمر التالي: mysql -u root وسيتغير المؤشر إلى الشكل التالي: mysql> وهذا دليل على أنك قمت بالفعل بالدخول إلى mysql بنجاح. الآن يمكنك من جديد إعادة تغيير كلمة مرور الجذر root، عن طريق تنفيذ الأوامر التالية بالترتيب: FLUSH PRIVILEGES; \\ثم ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password'; \\ثم SET PASSWORD FOR 'root'@'localhost' = PASSWORD('new_password'); \\هي كلمة المرور الجديدة new_password حيث وأخيراً نعيد تشغيل Mysql كالتالي: sudo systemctl start mysql بالتوفيق،
-
مرحباً @Anoir Belkahla، من الصعب تحديد المشكلة دون الاطلاع على الكود الخاص بالانتقال بين الأنشطة لديك، ولكن لحل المشكلة يكفي أن تقوم بفهم آلية عمل المكدس (Backstack) ضمن اندرويد وكيف يتم استخدام intent. عند الانتقال بين نشاط Activity و آخر فإنه يتم تمرير النشاط السابق إلى الخلفية ويصبح النشاط القديم في أعلى المكدّس وبذلك ستتمكن من الرجوع إليه لاحقاً عن طريق الضغط على زر العودة. في حال كان يتم إغلاق التطبيق نهائياً عند الضغط على زر العودة، فسبب ذلك هو عدم وجود أي نشاط آخر ضمن المكدس وبذلك يتم إغلاق التطبيق. لحل هذه المشكلة، تأكد من عدم وجود التعليمة التالية بعد الانتقال إلى النشاط الجديد: finish(); وأيضاً يمكنك استعمال: Intent.FLAG_ACTIVITY_NEW_TASK للتأكد من عدم إنهاء النشاط السابق، مثال: Intent startMain = new Intent(Intent.ACTION_MAIN); startMain.addCategory(Intent.CATEGORY_HOME); startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(startMain); أتمنى لك التوفيق
-
مرحباً تميم، سابقاً كان يتم استعمال مكتبة تدعى vue-analytics ولكن للأسف تم التوقف عن دعمها منذ فترة قصيرة والسبب في ذلك بأن google قد انتقلت إلى إعتمادية جديدة اسمها gtag.js ولحسن الحظ تم تطوير مكتبة جديدة لمواكبة هذا التحديث. يمكنك الآن استعمال vue-gtag وهي عبارة عن إطار عمل يسمح لك بإرسال بيانات الأحداث إلى Google Analytics وإعلانات Google ومنصة Google للتسويق. يتم تضمين google analytics ضمن تطبيق Vue Js كالتالي: أولاً لتحميل المكتبة نقوم بتنفيذ الأمر التالي: npm add vue-gtag ثم يمكنك تضمنيها ضمن تطبيقك كالتالي: import Vue from "vue"; import App from "./App.vue"; import VueGtag from "vue-gtag"; Vue.use(VueGtag, { config: { id: "UA-1234567-1" } }); new Vue({ render: h => h(App) }).$mount("#app"); حيث id هو رقم المعرّف الذي ستحصل عليه من حسابك على Google Analytics. ثم يمكنك الآن إرسال (أحداث) وتتبع حركة المستخدم عن طريق التالي: export default { name: 'MyComponent', methods: { login () { this.$gtag.event('login', { method: 'Google' }) } } } وهذا مثال بسيط عن إمكانية إرسال حدث أثناء تسجيل المستخدم للدخول إلى موقعك. يمكنك أيضاً الإطلاع على كافة التفاصيل والأحداث الموجودة والتي يمكنك تطبيقها على الموقع الرسمي لهذه المكتبة. أتمنى لك التوفيق.
- 1 جواب
-
- 1
-
مرحباً @محمود رضا موسى، يتم استخدام Base64 بشكل شائع لترميز البيانات الثنائية (على سبيل المثال ، الصور أو ملفات الصوت) للتضمين في HTML و CSS والمستندات النصية الأخرى. بالإضافة إلى ذلك ، يتم استخدام Base64 لتشفير البيانات التي قد تكون غير مدعومة أو تالفة أثناء النقل أو التخزين أو الإخراج. ولكن لسوء الحظ، على الرغم من أن Base64 طريقة فعالة نسبيًا لتشفير البيانات الثنائية ، إلا أنها ستزيد في المتوسط حجم الملف لأكثر من 25٪. لا يؤدي هذا إلى زيادة النطاق Bandwidth فحسب ، بل يؤدي أيضًا إلى زيادة وقت تحميل الملفات. ولكن بما أنك تستخدمها فقط لأيقونات صغيرة الحجم نسبياً فذلك لن يسبب لك أي مشكلة، ولن تشعر بفارق كبير. كما وأن العديد من المواقع تستخدم حالياً Base64 أثناء التعامل مع Emojis أرفق لك أيضاً صورة توضيحية للمقارنة بين حجم نفس الصورة مع وبدون الترميز لتوضيح الفكرة. بالتوفيق
-
مرحباً @Heba Saeed إن سلة التسوق Shopping cart ليس لها علاقة مباشرة مع php و mysql، حيث يمكنك اعتبارها كمخزن مؤقت من طرف المستخدم وليس من طرف السيرفر، لذلك يجب عليك إضافتها في مشروعك من طرف المستخدم عن طريق الجافاسكريبت أو إطار العمل الذي تقومين باستعماله مهما يكن. بعض النقاط لمساعدتك: - يتم استخدام طريقتين لتخزين البيانات (المنتجات) من طرف المستخدم: عن طريق session storage أو local storage ، والفرق بينهما: ضمن Session storage: يتم تخزين البيانات ضمن الجلسة أي جميع البيانات التي يتم تخزينها هنا سيتم حذفها بمجرد إغلاق المستخدم للمتصفح. أما ضمن Local Storage: فسيتم تخزين البيانات بشكل دائم ضمن المتصفح. - يتم التعامل مع كلتا الحالتين عن طريق مفتاح Key و قيمة Value. أي لتخزين بيانات ضمن الجلسة عن طريق التابع sessionStorage.setItem(key,value) key: هو المفتاح أو اسم العنصر الذي سيساعدنا فيما بعد بالوصول إليه. وهو من النمط النصي String. مثال: "cart" value: هو القيم المخزنة ضمن هذا العنصر - أما لجلب البيانات من الجلسة، فيتم عن طريق التابع: sessionStorage.getItem(key)، حيث يكفي فقط أن نمرر اسم المفتاح للحصول على البيانات المخزنة ضمنه. مثال لتخزين بيانات ضمن الجلسة: var cart = { item: "Product 1", price: 35.50, qty: 2 }; var jsonStr = JSON.stringify(cart); sessionStorage.setItem( "cart", jsonStr ); ونلاحظ هنا على سبيل المثال لدينا غرض اسمه cart يحوي عدة خصائص: العنصر item - سعر العنصر price - الكمية qty. قمنا أولاً بتحويل الغرض cart إلى مصفوفة JSON ثم قمنا بتخزينها ضمن الجلسة. وأيضاً يمكنك تخزين أنواع متعددة أو إضافة عدة عناصر باعتبار كل عنصر من نمط غرض Object وبذلك تكون سلة التوسق عبارة عن مصفوفة أغراض. { “items”: [ { “product”: “Product-name #1”, “qty”: 5, “price”: 5 }, { “product”: “Test”, “qty”: 1, “price”: 2 } ] } وبعدها يمكنك استعادة البيانات عن طريق التابع getItem التالي: sessionStorage.getItem("cart"); أما بالنسبة لـ localStorage فأيضاً يتم التخزين واستعادة البيانات عن طريق نفس التوابع، ولكن نستبدل sessonStorage ب localStorage. مثال: localStorage.getItem("cart"); وبذلك يمكنك البدء بالمحاولة بإضافة سلة التسوق وجلب بياناتها وعرضها على الواجهة المخصصة لذلك ضمن موقعك. بالتوفيق،
-
في حال لم تكن موضحة ضمن صفحة pricing (الأسعار) الموجودة على الموقع، فبعض بوابات الدفع تتطلب منك إنشاء حساب على موقعهم أولاً أو التواصل معهم لمعرفة الأسعار.
-
مرحباً مروان، الأسعار غالباً تكون موضحة على الموقع الالكتروني لبوابة الدفع، لذلك قم بالبحث على Google على موقع بوابة الدفع التي تقوم باستخدامها وهناك يمكنك قراءة العروض والأسعار وباقي التفاصيل. بالتوفيق،
- 4 اجابة
-
- 1
-
مرحباً عبدالواحد، إن عملية بذر قواعد البيانات هي ليست إلزامية، فهي مقدمة من لارافيل كغيرها من الإضافات فقط لتسهل العمل على المبرمج بملء قاعدة البيانات ببيانات تجريبية. لمزيد من المعلومات يمكنك الإطلاع على الرابط بذر قواعد البيانات بالبيانات الاختبارية Seeding في Laravel بالتوفيق،
- 4 اجابة
-
- 1
-
مرحباً احمد، بالنسبة لـ Angular: يتم استخدام ngrx/store وهو امتداد لإدارة الحالة مستوحى من Redux وبالتالي يمكن عن طريقه استخدام جميع الخاصيات الموجودة ضمن Redux مثل: (Store, Actions, Reducer,...). أما في Vue: فيتم استعمال مكتبة Vuex Store وهو بمثابة متجر مركزي لجميع المكونات ضمن التطبيق، ومن أهم أدواره بأنه يقوم بحفظ الحالة وينظم عمليات تحديث البيانات ضمنها ويجعلها تشاركية مع جميع المكونات ضمن التطبيق عن طريق بناء قواعد لها. أما في Flutter: فيوجد العديد من الخيارات الممكنة لإدارة الحالة ومنها: - عن طريق استخدام Provider وهو المرجح والمعتمد من الموقع الرسمي. - عن طريق استخدام setState لإدارة الحالات المؤقتة الخاصة بكل widget - عن طريق استخدام Redux أو Fish -redux - عن طريق استخدام Bloc / Rx ويتم عبرها التعامل مع الحالة عن طريق stream وغيرها.. أما بما يخص التعامل مع API، فطبعاً يمكن استخدام axios مع Angular و Vue ولكن بالنسبة لـ Flutter فالمكتبة الأساسية هي HTTP ويمكنك تحميلها وتضمينها من الموقع الرسمي.
- 3 اجابة
-
- 1
-
منطقياً، في حالة الإضافة على الأقسام، نعم يكفي كتابة خصائص جدول department. تبقى أفضل طريقة للتجريب وتحديد المشاكل التي قد تواجهك في المستقبل هي بالتجربة مع رؤية النتيجة على المتصفح وبتتبع الكود ورسائل الخطأ والبحث عن حلولها.
-
بما أن عملية الإضافة الفعلية هي على جدول الطلبات requests، يمكنك جعل الإضافة على جدول requests بدلاً من department وإضافة مفتاح ثانوي ضمن جدول requests يعبر عن القسم (department) المقابل لهذا الطلب
-
في كود الإضافة المشكلة بأنك تقومين بإضافة Quantity إلى جدول department: $cmd = $con->runQuery("insert into department(Quantity,reqdes)values('$Quantity','$reqdes')"); وهذه الخاصية غير موجودة في الجدول كما هو موضح في صورة جداول قاعدة البيانات، إنما خاصية Quantity موجودة في جدول Requests. لذلك يظهر خطأ بعدم العثور على هذه الخاصية.
-
بالنسبة لتسجيل الدخول، يمكن إرسال البيانات عن طريق استخدام Form كالتالي: <form action="action_page.php" method="post"> <div class="container"> <label for="uname"><b>Username</b></label> <input type="text" placeholder="Enter Username" name="uname" required> <label for="psw"><b>Password</b></label> <input type="password" placeholder="Enter Password" name="psw" required> <button type="submit">Login</button> </div> </form> حيث نقوم باستبدال اسم الصفحة: action_page.php بالصفحة المراد استقبال البيانات فيها والتعامل معها.
- 17 اجابة
-
- 1
-
بالنسبة للسؤال الثاني: عند الضغط على زر التعديل يتم إرسال متغير واحد فقط وهو قيمة id <td><a class='btn btn-success btn-xs' href='editdep.php?id=$depId'>update</a></td> وفي حال أردت إرسال أيضاً باقي القيم التي سيتم تعديلها مباشرةً بقاعدة البيانات يجب عليك إرسالها كالتالي بوضع علامة & للفصل بينها: <td><a class='btn btn-success btn-xs' href="editdep.php?id=$depId&depName=$depName&depDes=$depDes">update</a></td> ويجب تعديل صفحة editdept.php كالتالي: <?php // --> الكود القديم $id = $_GET['id']; require_once("../DBConnection.php"); require_once("../settings.php"); $con = new DBConnection($localhost); $depId = $_POST['depId']; $depName = $_POST['depName']; $depDes = $_POST['depDes']; $cmd = $con->runQuery("update department set depName= '$depName' , '$depDes' where Id = $depId"); // --> الكود الجديد $id = $_GET['id']; $depName = $_GET['depName']; $depDes = $_GET['depDes']; require_once("../DBConnection.php"); require_once("../settings.php"); $con = new DBConnection($localhost); $cmd = $con->runQuery("update department set depName = $depName , depDes = $depDes where Id = $id"); ?> حيث يتم تمرير المتغيرات عن طريق الرابط وبالتالي لاستخدامها في PHP عن طريق GET بالنسبة للسؤال الرابع: يجب عليك تغيير ترتيب العمليات، بما أنك قمت بربط الجدولين sweets و products بمفتاح ثانوي، يجب أولاً التأكد من وجود الصنف الأساسي قبل إضافة الصنف الثانوي، ففي حالتك يتم إضافة صنف ثانوي لصنف أساسي غير موجود وبالتالي لا يمكن ربطه عن طريق المفتاح. ملاحظة: أيضاً يجب عليك الانتباه لاستعمال علامات التنصيص المفردة والمزدوجة في PHP أثناء التعامل مع المتغيرات، فعند استعمال علامات تنصيص مفردة لا تتم معالجة المتغير وبالتالي لا نحصل على قيمته، مثال: $x = 5; echo 'the value of x is: $x'; النتيجة: the value of x is $x أما: echo "the value of x is: $x"; النتيجة: the value of x is: 5 وفي حال أردت استعمال علامات التنصيص المفردة يجب دمجها مع المتحول كالتالي 'the value of x is: ' . $x أما بالنسبة للسؤال الثالث فلم أجد الكود الموافق لعملية الإضافة ضمن الملفات المرفقة من قبل حضرتك، ربما يجب عليك وضع جميع الملفات المتعلقة بالمشروع بملف واحد وضغطها ثم رفعها للسهولة، وفي حال أمكن إرفاق صورة لبنية الجداول في قاعدة البيانات لنتمكن من معالجة باقي المشاكل بشكل أفضل.
- 17 اجابة
-
- 1
-
أرجو منك رفع الكود كاملاً للتأكد أيضاً من بنية قاعدة البيانات
- 17 اجابة
-
- 1
-
مرحباً Nedjadi، هذه الخطوات قامت بحل المشكلة لدي سابقاً: أولاً قم بتفيذ التالي لإضافة المسار الناقص: sudo -E add-apt-repository ppa:openjdk-r/ppa ثم قم بالتحديث: sudo apt-get update وأخيراً قم بإعادة التحميل كالتالي: sudo apt-get install openjdk-8-jdk بالتوفيق،
- 2 تعليقات
-
- أبنتو 18.04
- جافا
-
(و 3 أكثر)
موسوم في: