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

Sam Ahw

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

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

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

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

    16

كل منشورات العضو Sam Ahw

  1. إن الإضافات المفعّلة للويب والإضافات الموجودة التابعة لموجّه الأوامر قد تختلف في نظام التشغيل. لذلك وللتأكد من تفعيل هذه الإضافة قم بتنفيذ الأمر التالي في موجه الأوامر: php -m أيضاً، في نظام تشغيل ubuntu مثلاً، عند تنفيذ أمر التحميل التالي: sudo apt-get install php5-mcrypt فلا يتم تحميل الإضافة ضمن mods-available، فتحتاج بعدها إلى إجراء الأمر التالي لنقلها: sudo ln -s /etc/php5/conf.d/mcrypt.ini /etc/php5/mods-available/mcrypt.ini ثم تحتاج إلى تفعيل mod وإعادة التشغيل في حال كان خادم الويب apache كالتالي: sudo php5enmod mcrypt sudo service apache2 restart وبدءً من الإصدار الخامس في لارافيل لم تعتد تعتمد على الإضافة mcrypt وأيضاً في النسخ الحديثة من php لم تعد موجودة.
  2. المذكور في غوغل أنه الوقت الطبيعي لمراجعة التطبيقات هو حوالي 3 أيام من تاريخ التقديم، ولكن قد يستغرق في بعض الأحيان وقت أطول قليلاً. لا يمكنك تسريع العملية، ولكن في حال وجود أي مشكلة سيقومون بإرسال بريد الكتروني لك يحوي التفاصيل، لذلك قم بمراجعة بريدك الالكتروني باستمرار.
  3. يوجد عدة طرق لتنفيذ ذلك، فيمكنك على سبيل المثال استخدام المصفوفات كالتالي: $query->where([ ['column_1', '=', 'value_1'], ['column_2', '<>', 'value_2'], [COLUMN, OPERATOR, VALUE], ... ]) بحيث يكون الترتيب بدءً من اليسار: اسم العمود، عملية المقارنة، القيمة. وكذلك يمكنك وضع الجمل الشرطية ضمن متحولات وإعادة استخدامها في الاستعلام بالشكل التالي: $matchThese = ['field' => 'value', 'another_field' => 'another_value', ...]; $orThose = ['yet_another_field' => 'yet_another_value', ...]; ثم: $results = User::where($matchThese)->get(); // مع مجموعة أخرى من الاستعلامات $results = User::where($matchThese) ->orWhere($orThose) ->get(); وبالتالي سيكون مماثل للاستعلام الأساسي بالشكل المكافئ للتالي: SELECT * FROM users WHERE (field = value AND another_field = another_value AND ...) OR (yet_another_field = yet_another_value AND ...) وأخيراً: يمكن ببساطة وضع سلسلة الشروط بشكل متتالي: User::where('this', '=', 1) ->where('that', '=', 1) ->get();
  4. سبب الخطأ هو أن لارافيل في النسخة 5.4 أحدثت تغييراً في الترميز الافتراضي المستخدم في قواعد البيانات وأصبح utf8mb4 والذي يدعم تخزين الemojis. وهذا الخطأ أصبح يظهر فقط مع المشاريع المبنية على النسخ الأحدث من 5.4 والتي مازالت تستخدم نسخ أقدم من mysql5.7.7 ولذلك في حال كنت تستخدم mariadb أو نسخ أقم سيظهر هذا الخطأ لديك والحل هو بالطبع بتحديث النسختين في كل من لارافيل و قاعدة البيانات. ولكن يوجد حل مؤقت يمكنك تنفيذه في كل مشروع، بالتوجه إلى AppServiceProvider.php ثم بداخل التابع boot نقوم بتعديل defaultStringLength في لارافيل كالتالي: public function boot() { Schema::defaultStringLength(191); } وبالطبع لا ننسى إضافة تضمين الschema في نفس الملف: use Illuminate\Support\Facades\Schema;
  5. إن السبب في ذلك هو بعض التغييرات التي طرأت على النسخة الثامنة في لارافيل. ففي النسخ السابقة من لارافيل، مزود خدمة المسارات RouteServiceProvider موضوع ضمن $namespace بشكل افتراضي، أما في نسخة لارافيل 8 فقيمتها الافتراضية هي null لكي تتيح للمبرمج من تعريف الاسماء الخاصة به. لذلك يجب عليك استخدام المسار الكامل ضمن التعريف عند عدم استخدام namespace محدد، كالتالي: use App\Http\Controllers\UserController; Route::get('/users', [UserController::class, 'index']); // أو Route::get('/users', 'App\Http\Controllers\UserController@index'); أما في حال كنت ترغب باعتماد الطريقة القديمة (الموجودة في الإصدارات السابقة من لارافيل) يجب عليك تعديل الملف App\Providers\RouteServiceProvider وإضافة namespace ضمن التابع boot كالتالي: public function boot() { Route::prefix('api') ->middleware('api') ->namespace('App\Http\Controllers') // <--------- نضيفها هنا ->group(base_path('routes/api.php')); } ولكن في حال كنت تستخدم نسخة أحدث من لارافيل 8.0.2 فأتاحت لك سهولة تنفيذ السابق عن طريق تعليق السطر التالي فقط: // protected $namespace = 'App\\Http\\Controllers'; وبذلك تعود لنفس الاستخدام كما هو في الإصدارات الأقدم من الإصدار رقم 8.
  6. يمكن تغيير اسم الملف server.php والموجود في جذر المشروع إلى الاسم index.php ثم نسخ الملف htaccess من داخل مجلد public أيضاً إلى المجلد الرئيسي (الجذر) للمشروع. ولكن هذه الطريقة ليست الأفضل كونها تسمح ببعض الخروقات الأمنية، لأنها تسمح للمخترقين بالوصول إلى معلومات حساسة مثل المعلومات الموجودة ضمن الملف .env ولها أيضاً بعض العيوب الأمنية الأخرى. بدلاً من ذلك، يمكن إنشاء ملف جديد htaccess ضمن المجلد الرئيسي للمشروع أي بجانب الملف server.php ووضع بداخله التالي: RewriteEngine On RewriteCond %{REQUEST_URI} !^/public/ RewriteRule ^(.*)$ /public/$1 [L,QSA] والذي بدوره سيقوم بإعادة كتابة جميع URIs إلى المجلّد public حتى الترويسات التي يتم استقبالها على سبيل المثال authorization headers والمتغيرات الأخرى.
  7. يختلف حل هذه المشكلة تبعاً لاختلاف نظام التشغيل أو البيئة التي يتم الاتصال عبرها وتنفيذ الأوامر، ولكن من الحلول المقترحة. فقد تظهر نتيجة عدم التمكن من تحديد الاتصال ضمن ملف .env وذلك بسبب تحديد بيئة مغايرة أثناء التطوير عن البيئة الحالية وبذلك يمكن تنفيذ الأمر التالي: php artisan migrate --env=production وبذلك سيتم أخذ قيم المتغيرات بشكل صحيح من ملف .env في حال كانت للنشر production. من إحدى الحلول أيضاً هو بتغيير قيمة DB_HOST من localhost إلى 127.0.0.1 والسبب في ذلك هو أن localhost يستخدم UNIX socket، أما 127.0.0.1 يستخدم TCP وهو Transmission Control Protocol والذي يجري عبر الانترنت. في حال لم تجدِ الطرق السابقة نفعاً، يمكن أن يكون ذلك بسبب اعتماد نسخة قديمة من mysql، ولذلك يجب التأكد من الإعدادات الموجودة عن طريق الدخول إلى خادم قواعد البيانات mysql و إجراء الأمر التالي: show variables like '%sock%' ثم أخذ القيمة التالية التي ستظهر نتيجة تنفيذ الأمر: /tmp/mysql.sock ثم التوجه إلى ملف database.php في مشروع لارافيل ووضع القيمة ضمن اتصال mysql كالتالي: 'mysql' => array( 'driver' => 'mysql', 'host' => 'localhost', 'database' => 'SchoolBoard', 'username' => 'root', 'password' => 'venturaa', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'unix_socket' => '/tmp/mysql.sock', ),
  8. يوجد طريقتين لإتاحة الصلاحيات على المشروع: إما أن يتم منح الصلاحيات للخادم، وهي الطريقة المفضلة عند أغلب المبرمجين وأيضاً التي ينصح بها التوثيق الرسمي للارافيل. فمثلاً باعتبار www هو الخادم يمكننا منح صلاحيات الكتابة كالتالي: sudo chown -R www-data:www-data /path/to/your/laravelproject وبذلك يمتلك خادم الويب جميع الملفات ضمن مجلد المشروع، وهنا ستواجه بعض المشاكل في حال كنت تستخدم FTP من طرف المستخدم لأنه الاتصال عبر FTP سيكون مسجل دخول وبدوره لا يملك الملفات الموجودة ضمن المشروع. لذلك يجب عليك بعدها إضافة المستخدم إلى نفس المجموعة التي تحوي الخادم كالتالي: sudo usermod -a -G www-data ubuntu وبعدها يمكن إعطاء الصلاحيات على الملفات جميعها كالتالي: sudo find /path/to/your/laravelproject -type f -exec chmod 644 {} \; وصلاحيات المجلدات: sudo find /path/to/your/laravelproject -type d -exec chmod 755 {} \; أما الطريقة الثانية، فهي عن طريق منح الصلاحيات للمستخدم نفسه. والذي يسهّل آلية العمل عن طريق منح الصلاحيات مباشرةً للمستخدم. ولتنفيذ ذلك أولاً نتوجه إلى مسار مجلد المشروع: cd /var/www/html/laravelproject ثم نقوم بتنفيذ الأمر التالي: sudo chown -R $USER:www-data . ثم نقوم بإعطاء الصلاحيات للمستخدم على الملفات والمجلدات: sudo find . -type f -exec chmod 664 {} \; sudo find . -type d -exec chmod 775 {} \; وأخيراً، يجب أيضاً إعطاء الصلاحيات للقراءة والكتابة على storage و cache ضمن لارافيل كالتالي: sudo chgrp -R www-data storage bootstrap/cache sudo chmod -R ug+rwx storage bootstrap/cache
  9. إن كل اتصال مع قاعدة بيانات في لارافيل يلزمه الخصائص التالية ضمن ملف .env: DB_CONNECTION=mysql نوع قاعدة البيانات DB_HOST=127.0.0.1 المضيف إما محلي أو خادم خارجي DB_PORT=3306 المنفذ DB_DATABASE=database1 اسم قاعدة البيانات DB_USERNAME=root اسم المتسخدم DB_PASSWORD=pass كلمة المرور ولذلك يمكن تكرارها عند كل تعريف لقاعدة بيانات. أما بالنسبة لاستخدام الاتصال فبالإضافة لما تم شرحه في التعليق السابق، يمكنك عن طريق Eloquent المقدّمة من لارافيل تعريف الاتصال، فمثلاً في حال وجود model ترغب باستخدامه دائماً مع اتصال محدد أو قاعدة بيانات محددة، فلا داعي لتكرار ذكر عملية الاتصال في كل مرة ستقوم باستخدامه، يكفي وضع $connection في Eloquent ضمن المودل الخاص بك وذلك سيضمن إبقاء الاتصال نفسه، كالتالي: class SomeModel extends Eloquent { protected $connection = 'mysql2'; }
  10. لارافيل هو إطار عمل مبني بلغة PHP وإطار العمل عبارة عن مجموعة من المفاهيم والخطوط العريضة والأكواد البرمجية والتي تستخدم لبناء شيء مفيد. فبدل من إعادة اختراع العجلة كل مرة عندما تقوم ببناء موقع , تقوم باستخدام إطار عمل يوفر عليك الوقت والجهد. وتتم إضافة الميزات للمشروع عن طريق إضافة الأكواد عن طريق معايير ثابتة محددة من إطار العمل. ومن الممكن في بعض الأحيان اختصار وقت كبير بكتابة تعليمة واحدة فقط تنفذ لك الكثير من الإجراءات الأخرى. أما بالنسبة لـ MVC: فهو اختصاراً ل Model - View - Controller ويعتمد على عملية الفصل الواجهة Interface التي نقصد بها View عن التطبيق والدي يحدد مشكلة البرنامج Business Logic والدي نقصد به Model وعن التحكم في الواجهه اي Controller . بعبارة اخرى ينص نمط MVC على الفصل بين الواجهة و البرنامج نفسه، بحيث في حالة أردنا تغيير Busniess Logic فإن View يبقى كما هو بدون تغيير، والعكس صحيح إذا تغيرت الواجهة View فان Model يبقى كماهو بدون تغيير. وبذلك، يمكننا القول على أن Controllor يعتبر حلقة الوصل في نمط MVC، بحيت أن أي عملية يقوم بالتحكم بها Controllor قبل أن يقوم بإرسالها إلى Model الذي يقوم بمعالجة البيانات من قاعدة البيانات ثم يعيدها إلى Controller قبل أن يقوم هذا الأخير بإرسال البيانات إلى View والذي يقوم بدوره بعرضها للمستخدم على شكل واجهة Interface. لمزيد من التفاصيل حول آلية العمل والميزات، أقترح عليك قراءة هذا المقال الموجود ضمن أكادمية حسوب والذي يحوي الكثير من التفاصيل الأخرى حول لارافيل.
  11. يجب أولاً تحميل المكتبة عن طريق npm كالتالي: npm install vuetify إضافة السطر التالي في تروسية ملف /resources/views/app.blade.php لكي يتم التعرف على الأيقونات الخاصة ب vuetify: <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet"> ثم في ملف /resources/js/app.js نضيف التالي فقط: import Vuetify from 'vuetify'; import 'vuetify/dist/vuetify.min.css'; Vue.use(Vuetify) مع التأكد بإضافتهم بعد Vue الأساسية بحيث يصبح شكل الملف كالتالي: require('./bootstrap'); import Vue from 'vue'; import Vuetify from 'vuetify'; import { InertiaApp } from '@inertiajs/inertia-vue'; import { InertiaForm } from 'laravel-jetstream'; import PortalVue from 'portal-vue'; import 'vuetify/dist/vuetify.min.css'; Vue.mixin({ methods: { route } }); Vue.use(InertiaApp); Vue.use(InertiaForm); Vue.use(PortalVue); Vue.use(Vuetify) const app = document.getElementById('app'); new Vue({ vuetify: new Vuetify(), render: (h) => h(InertiaApp, { props: { initialPage: JSON.parse(app.dataset.page), resolveComponent: (name) => require(`./Pages/${name}`).default, }, }), }).$mount(app); ويجب أيضاً التأكد من ملف webpack.mix.js أنه يحوي vuetify loader كالتالي: const mix = require('laravel-mix') const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin') mix .js('resources/js/app.js', 'public/js') .webpackConfig({ plugins: [ new VuetifyLoaderPlugin() ], }) .browserSync('tb8.test');
  12. يجب التوجه أولاً إلى مجلد المشروع الرئيسي وتنفيذ الأمر: sail shell بعدها سيتم تسجيل الدخول إلى المحفظة الخاصة بالمشروع ويمكنك تنفيذ أمر التهجير: sail artisan migrate يمكنك أيضاً استخدام اسم المحفظة نفسه الموجود في docker والذي تستطيع إيجاده ضمن: docker-compose.yml والذي يكون بشكل افتراضي: DB_HOST=mysql
  13. في PHP بدءً من الإصدار 5 ومافوق يوجد التابع imagegrabscreen: <?php $im = imagegrabscreen(); imagepng($im, "myscreenshot.png"); imagedestroy($im); ?> وأيضاً، يمكنك استخدام الجافاسكريبت والتي بدورها موجودة من طرف المستخدم أي متصفح الويب. ويوجد العديد من المكتبات التي تساعدك في ذلك منها html2canvas ، على سبيل المثال الكود التالي يقوم بالتقاط الشاشة وإظهارها في نافذة منبثقة جديدة: const screenshotTarget = document.body; html2canvas(screenshotTarget).then((canvas) => { const base64image = canvas.toDataURL("image/png"); window.location.href = base64image; }); يمكنك أيضاً عن طريق الجافاسكريبت استخدام getDisplayMedia والتي بدورها تتيح لك التعامل مع API للشاشة، مثال: const capture = async () => { const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); const video = document.createElement("video"); try { const captureStream = await navigator.mediaDevices.getDisplayMedia(); video.srcObject = captureStream; context.drawImage(video, 0, 0, window.width, window.height); const frame = canvas.toDataURL("image/png"); captureStream.getTracks().forEach(track => track.stop()); window.location.href = frame; } catch (err) { console.error("Error: " + err); } }; capture();
  14. إن كاربون يدعم العديد من اللغات ومنها العربية دون الحاجة لاستخدام مكتبات إضافية، يمكنك في أول الصفحة بين سطور التضمين ومباشرة بعد تضمين كاربون اختيار اللغة على الشكل التالي: use Carbon\Carbon; Carbon::setLocale('ar'); يوجد العديد من الطرق وكلها تؤدي إلى نفس النتيجة لذلك يمكنك استخدام النمط الذي تفضلّ، مثال: $newss = News::orderBy('created_at', 'desc')->take(10)->get(); أما في حال كان قصدك في post:All الحصول مثلاُ على آخر مقالات ضمن تصنيف أو مجموعة محددة، يمكنك كتابة التالي: //الحصول على المجموعات $categories = Category::all(); //وضع النتيجة النهائية $latest_posts_by_category = []; $ids = []; foreach($categories as $category){ $post = Post::with(['categories' => function($query){ $query->latest()->first(); }]) ->latest() ->whereHas('categories', function($query) use($category) { $query->whereName($category->name); })->take(1)->first(); if(!in_array($post->id, $ids)){ $latest_posts_by_category[] = $post; $ids[] = $post->id; } }
  15. إن memcache يختلف عن memcached في PHP. memcache هي النسخة القديمة ولم يعد يتم استخدامها مؤخراً بسبب محدوديتها. ولارافيل يتطلب تحميل memcached والتي تعتمد على مكتبة libMemcached client لذلك حتى بعد تحميل memcache سيبقى يظهر لك الخطأ. لذلك يمكنك تحميل المكتبة من التوثيق في launchpad في حال كان نظام التشغيل ويندوز. أما في حال كان لينكس يمكنك تنفيذ الخطوات التالية: تحميل المكتبة: sudo apt-get install php5-memcached مع استخدام النسخة الموافقة لنسخة PHP التي لديك. وبعدها يجب إعادة تشغيل الخدمة: sudo service php7.2-fpm restart وفي حال كان خادم الويب apache أو nginx: sudo service apachectl2 restart sudo service nginx restart أما في لارافيل: يجب التأكد من ربط driver بشكل صحيح ضمن المسار /config/app.php: 'default' => 'memcached', و memcache server بشكل مشابه للكود التالي: 'memcached' => [ 'driver' => 'memcached', 'servers' => [ [ 'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100, ], ], ]
  16. بما أنه قد تم إضافة الشهادة بالشكل الصحيح، يجب الآن إنشاء مسار على الخادم عبر proxy لتلقي الاتصالات. وبهذه الطريقة يستطيع nginx الحصول على بروتوكول ssl وبالتالي لا تحتاج لاستخدام منفذ port آخر إضافي. يمكن تعديل إعدادات nginx لتصبح على الشكل التالي: location /ws/{ proxy_pass http://127.0.0.1:3000/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-For $remote_addr; } وبعدها يتم الاتصال على العنوان التالي: https://localhost/ws وضمن الجافاسكريبت أيضاً يجب تعديل المسار ليصبح: window.Echo = new Echo({ broadcaster: 'socket.io', host: window.host, path: '/ws/socket.io', });
  17. يمكن تنفيذ ذلك بإدخال قيمة التاريخ المراد الوصول له ثم إنشاء عداد تنازلي، يمكنك تحويل التاريخ إلى ثواني عن طريق أي وسيلة موجودة على الانترنت. مثال بسيط لآلية العمل: # تضمين مكتبة الوقت import time # تعريف تابع العداد def countdown(t): while t: mins, secs = divmod(t, 60) timer = '{:02d}:{:02d}'.format(mins, secs) print(timer, end="\r") time.sleep(1) t -= 1 print('لقد تم الوصول إلى التاريخ') # input time in seconds t = input("Enter the time in seconds: ") # function call countdown(int(t)) تنفيذ الكود السابق سيطلب من المستخدم إدخال قيمة التاريخ بالثواني، ثم سيتم استدعاء عداد تنازلي مع تأخير بمقدار ثانية واحدة بين كل دورة وأخرى. وأيضاً يمكنك تخصيص الكود السابق بالشكل المناسب لك وحسب متطلباتك.
  18. إن السبب في ذلك هو أن middlewares في لارافيل والموجودة ضمن مصفوفة $routeMiddleware يتم تطبيقها والتحقق منها مباشرةً بعد تأكد لارافيل من المسار المزود عن طريق HTTP والسبب في ذلك لأن مسارات الطلبات المختلفة قد يكون لها middlewares مختلفة أيضاً. لأنه عندما يتم إرسال الطلبات POST, PUT, DELETE وغيرها... سيتم إرسالها إلى /api/authenticate والمتصفح يقوم بإرسال Options أولاً وبالتالي لارافيل يقوم بتسجيل المسار والتحقق من تطابقه مع المسارات الموجودة قبل الدخول والتحقق في middlewares وبما أن الموارد resources لا تحوي Options أو دوال معينة للتعامل معها لن تقوم بالتالي بالتحقق من أي middleware مرفق مع المسار وهنا يحدث الخطأ. مثال: Route::group(['middleware' => 'cors'], function () { Route::group(['prefix' => 'api'], function() { Route::resources('authenticate', 'AuthenticateController', ['only' => ['index']]); Route::post('authenticate', 'AuthenticateController@authenticate'); }); }); أما middlewares الموجودة ضمن مصفوفة $middleware يتم التحقق منها وتطبيقها (قبل) أن يقوم لارافيل بتسجيل المسار والتحقق من وجوده. فعملية المطابقة matching تستدعي findRoute الموجود ضمن: vendor/laravel/framework/src/Illuminate/Routing/Router.php على الشكل التالي: /** * Find the route matching a given request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Routing\Route */ protected function findRoute($request) { $this->current = $route = $this->routes->match($request); $this->container->instance(Route::class, $route); return $route; } لذلك لحل هذه المشكلة، يجب استخدام middleware عام أي (global) والذي بدوره يستقبل الخيارات الموجودة ضمن الترويسة OPTIONS ولاختصار الوقت والجهد يمكن استعمال مكتبة fruitcake / laravel-cors الموجودة والتي يمكن إضافتها إلى لارافيل والتي ستقوم بدورها باستعمال CORS الخاصة بها مثل أن يكون cors خاصة لكل مسار أو مجموعة أو لاحقة prefix في ملف api.php وتقوم بحل المشكلة الموجودة.
  19. يبدو أن المنفذ الحالي قيد الاستخدام من قبل النظام. لذلك أثناء تنفيذ الأمر يمكنك تمرير أي رقم منفذ آخر كالتالي: php artisan websockets:serve --port=7000 وأيضاً، بنفس الطريقة تتيح المكتبة تحديد رقم IP Address محدد ليتم التشغيل عليه، وذلك مفيد في حالات الحماية من تشغيل أو إيقاف السيرفر وتقيّده على رقم IP Address محدد بالشكل التالي: php artisan websockets:serve --host=127.0.0.1
  20. من الممكن أن تحدث المشكلة بسبب عدم استخدام مسار صحيح أو إشارة ( / ) قبل المسارات. فيتم حقن المسار الذي تتوجه إليه بعد المسار الحالي عند عدم وجود العلامة / ، وفي الكود الخاص بك يبدو أنك قد أخطأت بكتابة المسارات لكل من login و register كالتالي: بدلاً من استخدام: <Link to="/">Home</Link> <Link to="login">Login</Link> <Link to="register">Register</Link> تصبح كالتالي: <Link to="/">Home</Link> <Link to="/login">Login</Link> <Link to="/register">Register</Link>
  21. يجب أن تقوم بتمرير رقم IP Address للزبون مع ترويسة X_FORWARDED_FOR وبهذه الطريقة لن يتم حجب رقم IP Address للسيرفر الثاني. ويمكن القيام بذلك كالتالي: Route::get('/', function (Request $request) { $client = new \GuzzleHttp\Client(); $request = $client->request('GET', '/api/example', [ 'headers' => ['X_FORWARDED_FOR' => $request->ip()] ]); $response = $request->getBody(); }); حيث يتم وضع رقم IP ضمن الترويسة 'X_FORWARDED_FOR. ثم في السيرفر الأساسي يجب أن تقوم بإضافة عنوان السيرفر الآخر ضمن trusted proxy ضمن المسار التالي: App\Http\Middleware\TrustProxies ليتم أخذ عنوان IP Address من الترويسة Header بالشكل المطلوب. ويمكن القيام بذلك كالتالي: class TrustProxies extends Middleware { /** * The trusted proxies for this application. * * @var array */ protected $proxies = [ '192.168.1.1', // <-- يتم هنا وضع عنوان السيرفر الثاني ]; //... } الآن مع كل عملية استدعاء من الشكل على السيرفر الأول، ستتمكن من الوصول إلى عنوان الزبون Client IP بدلاً من عنوان السيرفر الثاني وبالتالي سيتم التخلص من الاختناق الحاصل: $request->ip()
  22. بعد نشر ملفات vendor يمكنك التعديل على مكوّن ما عن طريق إضافة وسم jetstream-views حتى يتم إنشاء الواجهات الموافقة بتنفيذ الأمر التالي: php artisan vendor:publish --tag=jetstream-views وبعد تنفيذ هذا الأمر ستجد UpdateProfileInformationForm ضمن المسار: app\Http\Livewire\UpdateProfileInformationForm.php وستجد الواجهة المرافقة له ضمن المسار التالي: resources\views\profile\update-profile-information-form.blade.php وعندها يمكنك التعديل عليها بالشكل المطلوب
  23. إن لارافيل بشكل افتراضي لديه آلية لالتقاط الأخطاء وبالتالي لديه مجموعة واسعة من رسائل الخطأ الموجودة بشكل تلقائي ضمن المكتبات المستخدمة، و رسالة TOO MANY REQUESTS من ضمن هذه الرسائل. يمكنك إنشاء extend للوسيط middleware الذي تقوم باستخدامه وعمل override لـ buildException لإنشاء رسالة خطأ خاصة جديدة بدلاً من الرسالة الافتراضية في لارافيل عندما يقوم هذا الصف برمي خطأ من نوع ThrottleRequestsException أو يمكنك إنشاء handler جديد خاص بك للتحكم بالأخطاء المراد إنشاء رسائل جديدة لها وبالتالي يمكنه التقاط الأخطاء من نوع ThrottleRequestsException ومعالجتها بالشكل المطلوب. مثال، ضمن Exceptions/Handler.php يمكننا كتابة التالي: use Illuminate\Http\Exceptions\ThrottleRequestsException; public function render($request, Exception $exception) { if ($exception instanceof ThrottleRequestsException) { //--> هنا يمكننا تنفيذ الذي نرغب به مثل إرسال رسالة خاصة أو تنفيذ إجرائية معينة } return parent::render($request, $exception); }
  24. يجب ترميز الملف (الصورة) بالصيغة base64 وطباعته في shell قبل نقله إلى لارافيل، ثم يتم فك الترميز base64 في لارافيل. فبفرض لديك السكريبت التالي في بايثون: import base64 from io import BytesIO from PIL import Image, ImageDraw background = Image.new('RGBA', (500, 500)) d = ImageDraw.Draw(background) d.text((10, 10), "Hello World", fill=(255, 255, 0)) imgByteArr = BytesIO() background.save(imgByteArr, format='PNG') imgByteArr = base64.b64encode(imgByteArr.getvalue()) --> يتم هنا الترميز في base64 قبل الطباعة print(imgByteArr) ثم في لارافيل يتم استدعاء process وانتظار انتهاء تنفيذ السكريبت واختبار حدوث أي خطأ أثناء التنفيذ عن طريق استخدام process->isSuccessful كالتالي: public function newImage() { $process = new Process('python3 /path-to-script/shell.py'); $process->run(); if ( ! $process->isSuccessful()) { return abort(404); } return response(base64_decode(str_replace_first('b', '', $process->getOutput())))->header('Content-Type', 'image/png'); } حيث يتم استخدام base64_decode لفك الترميز ونمرر له القيمة الناتجة من تنفيذ السكريبت السابق عن طريق process->getOutput وأخيراً يجب إضافة الترويسة المناسبة لنمط الملف، في حال (صورة) يكون image/png.
  25. إن سبب ظهور المشكلة فقط عند تنفيذ command هو لأن CLI في لارافيل يستخدم php.ini مغاير للذي يتم استخدامه ضمن المشروع أو بيئة التطوير. ويمكن حل المشكلة إما عن طريق التعديل على ملف GuzzleHttp\Client بتغيير مفتاح verify إلى القيمة false بدلاً من true من configureDefaults بالشكل التالي: $this->client = new GuzzleClient(['defaults' => [ 'verify' => false ]]); ويمكن أيضاً تحميل الشهادة الرقمية باللاحقة .pem ثم تعديل ملف php.ini الخاص بالبيئة التي يتم استخدامها كالتالي: curl.cainfo = "[pathtothisfile]\cacert.pem" حيث نستبدل pathtothisfile بالمسار المطلق للشهادة ليتم التعرف عليها بداخل الملف php.ini ومن ثم نقوم بالإشارة للشهادة بالشكل التالي: $guzzle->setDefaultOption('verify', '/path/to/cacert.pem'); ففي كلتا الحالتين يجب أن يكون التحقق ضمن GuzzleHttp\Client في لارافيل على الشكل التالي: // تعطيل التحقق $guzzle->setDefaultOption('verify', false); // استخدام الشهادة $guzzle->setDefaultOption('verify', '/path/to/cacert.pem');
×
×
  • أضف...