-
المساهمات
1388 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
16
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Sam Ahw
-
يوجد العديد من الطرق، وذلك يعتمد على النمط الذي تقوم باستخدامه في العرض Flex أو Grid أو حسب توزع العناصر ضمن الصفحة. ولكن أسهل طريقة في حال لم تكن تستخدم بنية محددة ولسرعة التوسيط يمكنك استخدام margin: auto مثال: <!DOCTYPE html> <html> <head> <style> .center { margin: auto; width: 60%; border: 3px solid #73AD21; padding: 10px; } </style> </head> <body> <div style="background-color:yellow"> <div class="center">Hello World!</div> </div> </body> </html> وستحصل على النتيجة التالية: وكذلك margin-left: auto و margin-right: auto معاً لنفس العنصر. أما لتوسيط عنصر نصّي نستخدم text-align مع القيمة center كالتالي: .center { text-align: center; } وسيتم توسيط النص ضمن العنصر الحاوي له.
- 5 اجابة
-
- 1
-
إن الاختبار يتم بتفيذ الأمر مباشرةً ورؤية النتائج: php artisan schedule:run ولكن في حال كان الهدف هو طباعة رسائل الخطأ المخصصة في حالات معيّنة، فإن scheduler لا يقوم بالطباعة بطبيعته، ولكن يمكنك توجيه الطباعة للكود الذي يتم تنفيذه لأي ملف آخر عن طريق استخدام: writeOutputTo() أو: appendOutputTo() وهو مايعرف في TaskOutput في التوثيق الرسمي للارافيل، مثال: $schedule->command('emails:send') ->daily() ->sendOutputTo($filePath); حيث نستبدل $filepath بمسار الملف الذي نريد الطباعة عليه. أما لإجراء Unit Test للعمل بشكل مخصص أكثر، فيمكن إضافة التالي ليتم اختبار schedule محدد مثل الكود السابق لديك: public function testIsAvailableInTheScheduler() { /** @var \Illuminate\Console\Scheduling\Schedule $schedule */ $schedule = app()->make(\Illuminate\Console\Scheduling\Schedule::class); $events = collect($schedule->events())->filter(function (\Illuminate\Console\Scheduling\Event $event) { return stripos($event->command, 'NewCommand'); }); if ($events->count() == 0) { $this->fail('No events found'); } $events->each(function (\Illuminate\Console\Scheduling\Event $event) { // This example is for hourly commands. $this->assertEquals('0 * * * * *', $event->expression); }); }
- 1 جواب
-
- 1
-
يوجد نقص في بعض التعاريف في الملف، فيجب التأكد من تعريف ملف bootstrap بشكل صحيح وربطه ضمن kernel التطبيق قبل البدء بإجراء أي task، مثال شامل: @servers(['localhost' => '127.0.0.1']) @setup define('LARAVEL_START', microtime(true)); $app = require_once __DIR__.'/bootstrap/app.php'; $kernel = $app->make(Illuminate\Contracts\Console\Kernel::class); $kernel->bootstrap(); dump(config('database')); @endsetup @task('new', ['on' => 'localhost']) ls @endtask وبمجرد الدلالة على bootstrap ضمن kernel و إضافة Laravel_START لا داعي لإدخال ملفات vendor فسيتم اعتمادها بشكل تلقائي. ثم تأكد من إجراء العمليات التالية لتجنّب أي مشاكل: php artisan config:clear php artisan cache:clear composer dump-autoload php artisan view:clear php artisan route:clear
- 1 جواب
-
- 1
-
يمكن إجراء تنفيذ scripts بداخل الاختبار، ولكنها يجب ألا تكون متتالية. بل يجب تعريف كل جزء على حدى، مثال: public function testExample() { $this->browse(function ($browser) { $browser ->visit('http://localhost:8000/home') ->driver->executeScript('window.scrollTo(0, 500);'); // browser لا يمكن إجراء أوامر أخرى هنا مباشرةً يجب تعريف غرض جديد من $browser->click('label[for=test_1]') ->pause(500) }); } حيث قمنا باستخدام الدالة window.scrollTo، في حال كنت تستخدم نسخة أقدم من لارافيل، يمكنك استخدام jquery لتنفيذ ذلك: public function scrollTo($selector) { $this->ensurejQueryIsAvailable(); $selector = $this->resolver->format($selector); $this->driver->executeScript("jQuery(\"html, body\").animate({scrollTop: jQuery(\"$selector\").offset().top}, 0);"); return $this; }
- 1 جواب
-
- 1
-
يمكنك التواصل مع مركز الدعم الفني من هنا وفتح تذكرة هناك (مع اختيار قسم أكادمية حسوب) لمساعدتك بشكل أفضل فيما يتعلّق بأمور الدفع، وأيضاً أي استفسار آخر لديك.
- 3 اجابة
-
- 1
-
يجب تغيير الإعدادات الافتراضية في إعدادات php في حال كنت تقوم بإجراء عمليات على جداول كبيرة الحجم. ويمكن ذلك عن طريق الذهاب إلى ملف تعريف إعدادات php ضمن خادم الويب ويكون عادةً ضمن المسار : /etc/php7/fpm/php.ini في حال لديك إصدار آخر يجب أن تستبدل رقم الإصدار 7 بالرقم الذي لديك، ولكنه سيكون موجود ضمن etc غالباً، ثم نقوم بتعديل الحد الأقصى للذاكرة بأن نقوم بالبحث عن التالي: القيمة السابقة memory_limit = 512M القيمة الجديدة memory_limit = 2048M ثم يجب بعد ذلك إعادة تشغيل خادم الويب: sudo systemctl restart nginx
- 2 اجابة
-
- 1
-
يجب أولاً أن تقوم بتغيير الكود الموجود في المتحكم لاستخدام لغة افتراضية في حال الفشل، كالتالي: public function handle($request, Closure $next) { if (Session::has('locale')) { App::setLocale(Session::get('locale')); } else { //تقوم لارافيل تلقائياً باستعادة اللغة الافتراضية الموجودة App::setLocale(Config::get('app.fallback_locale')); } return $next($request); } ثم تأكد من إضافة middleware في Kernal.php: \App\Http\Middleware\Language::class, وأخيراً ضمن المتحكم الخاص باللغة: public function index($locale) { session(['locale' => $locale]); App::setLocale($locale); return Redirect::back(); } وأيضاً يتم تعريف اللغة الافتراضية للتطبيق ضمن ملف .env : APP_LOCALE=en ويتم الدلالة عليها في ملف config/app.php كالتالي: 'locale' => env('APP_LOCALE', 'en'), أما للتغيير إلى أكثر من لغة فيمكن إنشاء قائمة باللغات بحيث عندما يتم الضغط على خيار لغة معيّنة يتم التوجيه إلى مسارات هذه اللغة: <ul class="dropdown-menu" role="menu"> <li>{!! link_to('lang/en', trans('menus.language-picker.langs.en')) !!}</li> <li>{!! link_to('lang/es', trans('menus.language-picker.langs.es')) !!}</li> <li>{!! link_to('lang/fr-FR', trans('menus.language-picker.langs.fr-FR')) !!}</li> <li>{!! link_to('lang/it', trans('menus.language-picker.langs.it')) !!}</li> <li>{!! link_to('lang/pt-BR', trans('menus.language-picker.langs.pt-BR')) !!}</li> <li>{!! link_to('lang/ru', trans('menus.language-picker.langs.ru')) !!}</li> <li>{!! link_to('lang/sv', trans('menus.language-picker.langs.sv')) !!}</li> </ul> ويكون المسار لذلك كالتالي: get('lang/{lang}', 'LanguageController@changeLang');
- 3 اجابة
-
- 1
-
يجب التأكد من تعريفه ضمن config في providers والإشارة له ضمن aliases: 'providers' => [ .... Laravel\Socialite\SocialiteServiceProvider::class ], 'aliases' => [ .... 'Socialite' => Laravel\Socialite\Facades\Socialite::class ], ثم عند استخدامه في أي متحكم، يجب استخدام alias الذي قمنا بتعريفه: namespace App\Http\Controllers; use Illuminate\Http\Request; use Socialite; use App\Http\Requests; use App\Http\Controllers\Controller; class SocialAuthController extends Controller { public function redirect() { return Socialite::driver('facebook')->redirect(); } public function callback() { } }
- 2 اجابة
-
- 1
-
يمكنك الإشارة إلى هذا الصف على شكل اعتمادية أو dependency في أي متحكم آخر، فسيتم إنشاؤه حتى لو لم تقم باستخدام واجهة Interface بداخل هذا المتحكم. مثال: <?php namespace App\Http\Controllers; use App\Users\Repository as UserRepository; class UserController extends Controller { /** * The user repository instance. */ protected $users; /** * Create a new controller instance. * * @param UserRepository $users * @return void */ public function __construct(UserRepository $users) { $this->users = $users; } } أما في حال كنت ستستخدم واجهة، تأكد من أن الصف يقوم بعمل implement لهذه الواجهة ثم يجب القيام باستدعائه عن طريق التابع bind في أي مقدّم خدمة. على الشكل التالي: $this->app->bind(UserRepository::class, EloquentUserRepository::class);
- 1 جواب
-
- 2
-
يمكنك الدخول إلى الغرض والحصول على قيمة المتغيّر jobPushed عن طريق استخدام Laravel Horizon عن طريق الاستماع إلى الحدث jobPushed. فإن البيانات المرسلة مع هذا الحدث فيها جميع البيانات المتعلقة بالعمل الذي يتم إدخاله مثل: ID, name, connection, queue إلخ. وبذلك يمكنك معرفة عند إدخال هذا العمل إلى الرتل وإجراء أي عمليات معالجة ترغب بها بمجرّد تشغيل الحدث. ويمكنك تنفيذ ذلك كالتالي: Event::listen(JobPushed::class, function(JobPushed $event){ \Log::debug('JobPushed Event Fired ', [ 'connection' => $event->connectionName, 'queue' => $event->queue, 'payload' => [ 'id' => $event->payload->id(), 'displayName' => $event->payload->displayName(), 'commandName' => $event->payload->commandName(), 'isRetry' => $event->payload->isRetry(), 'retryOf' => $event->payload->retryOf(), ] ]); });
- 1 جواب
-
- 1
-
بما أنك تقوم باستعادة البيانات للمستخدم من قاعدة البيانات بعد تسجيل دخوله وتحفظها في الجلسة، تستطيع أيضاً تحديد الحقول الفارغة في سجله، وبعدها بنفس الطريقة التي ترسل فيها البيانات من الخادم إلى المستخدم تستطيع إرسال رسائل مخصصة تفيد بأن بعض الحقول فارغة ويجب تعديلها. في حال لم تتمكن من حل المشكلة يمكنك مشاركة جزء من الكود الذي ترغب بالمساعدة به لنستطيع مساعدتك بشكل أفضل.
- 11 اجابة
-
- 1
-
إن التحقق من صحة المدخلات أو البيانات يمكن أن يتم في منطقتين: إما عند المستخدم أي متصفح الويب وبذلك يتم التأكد من المدخلات قبل إرسالها إلى خادم الويب. وأيضاً عند خادم الويب نفسه، بحيث عند وصول البيانات إليه يقوم بالتحقق من صحتها قبل البدء بعملية معالجتها أو تخزينها في قاعدة البيانات. للتحقق من البيانات عند طرف المستخدم (أي متصفح الويب) يتم استخدام javascript في ال forms المستخدمة والتي يتم إدخال البيانات فيها، مثال ليكن لدينا حقل البريد الالكتروني التالي: <form name="myForm" action="/action_page.php" onsubmit="return validateForm()" method="post"> Name: <input type="text" name="email"> <input type="submit" value="Submit"> </form> وعندها يمكن عند الضغط على زر submit التحقق من حقل البريد الالكتروني قبل إرسال الطلب إلى خادم الويب كالتالي: function validateForm() { var x = document.forms["myForm"]["email"].value; if (x == "") { alert("يرجى تعبئة حقل البريد الالكتروني"); return false; } وبالتالي سيظهر رسالة خطأ في حال كانت خانة البريد الالكتروني فارغة. وبنفس الطريقة يمكنك وضع الشروط الأخرى حسب الطلب مثل أن يكون البريد الالكتروني صحيح أو كلمة المرور أكبر من عدد محدد من المحارف،...إلخ. أما من جهة خادم الويب، فإن ذلك يعتمد على حسب لغة البرمجة التي تقوم باستخدامها من طرف الخادم، ولكن عموماً المبدأ هو نفسه فعند استقبال البيانات يتم أيضاً التحقق من صحتها عن طريق وضع شروط if else وفي حال لم تكن البيانات موافقة للشروط المذكورة يتم إرسال رسالة خطأ من الخادم إلى المستخدم. بعد التعديل على سؤالك: يمكنك عند القيام بجلب بيانات المستخدم من القاعدة وتخزينها في الجلسة التأكد من الحقول الفارغة في سجله في قاعدة البيانات وإرسال الرسالة المطلوبة إلى المستخدم.
- 11 اجابة
-
- 1
-
المشكلة تحدث هنا لأن متصفح الويب أو تطبيق Angular سيقوم فقط بإرفاق الـ cookie للطلبات التي تنتمي لنفس اسم النطاق التي يتم عبره استقبال الطلبات. لحل هذه المشكلة أولاً تأكد من أنك تقوم باستخدام relative routes فمثلاً بدلاً من: /api/sanctum/crsf نقوم بكتابة: http://example.com/sanctum/crsf ثم يجب عليك إعداد خصائص البروكسي ضمن ملف proxy.conf.json ونضعه في المجلّد الجذر للمشروع: { "/api/*": { "target": "http://example.ocm", "secure": false, "changeOrigin": true, "logLevel": "debug", "pathRewrite": { "^/api": "" } } } ثم نقوم بتعديل الملف angular.json: "architect": { ... "serve": { ... "options": { .... "proxyConfig": "proxy.conf.json" } } } ثم أخيراً في ملف .env نقوم بالتعديلات التالية للتأكد من أن sanctum يقوم بالتعرف على الطلبات وإرفاق cookies معها: SANCTUM_STATEFUL_DOMAINS=localhost,.example.com SESSION_DRIVER=cookie SESSION_DOMAIN=localhost
- 1 جواب
-
- 1
-
قد يحدث تضارب عند تحديث النسخة إلى 8 مع blade في استخدام routes خاصةً في حال تم اختيار Jetstream لحل هذه المشكلة أولاً يمكن إنشاء مجلد resources كالتالي: composer require tightenco/ziggy npm install ziggy-js php artisan ziggy:generate "resources/js/ziggy.js" ثم يجب تعديل ملف webpack.mix.js: mix.js('resources/js/app.js', 'public/js') .webpackConfig(require('./webpack.config')); وأيضاً الملف ./webpack.config: لكي يتم التعرف على المسارات routes: const path = require('path'); module.exports = { resolve: { alias: { '@': path.resolve('resources/js'), ziggy: path.resolve('vendor/tightenco/ziggy/src/js/route.js'), }, }, }; وأخيراً ضمن الملف app.js: import route from 'ziggy'; import { Ziggy } from './ziggy'; ... Vue.mixin({ methods: { route: (name, params, absolute) => route(name, params, absolute, Ziggy), }, }); ... new Vue({ el: "#app", render: (h) => h(InertiaApp, { props: { initialPage: JSON.parse(app.dataset.page), resolveComponent: (name) => require(`./Pages/${name}`).default, }, }), }); وبذلك يتم الاستغناء عن vue-router ويتم أخذ jetstreams ليصبح توجيه المسارات من قبل Laravel
- 1 جواب
-
- 1
-
إن استخدام Laravel Fortify هو فقط لتسهيل الإجراءات الأساسية لعمليات التحقق وتسجيل الدخول وإعادة تعيين كلمة المرور...إلخ. بالإضافة إلى أنه يقوم بإنشاء المسارات لها وبذلك يسهّل العمل ويختصر الوقت. في حال الحاجة لوجود مسارات مخصصة أو تعديل هذه المسارات التي يقوم fortify بإنشائها فعندها لا حاجة لاستخدامه، ويمكن إنشائها بشكل مخصص كما هو الوضع الطبيعي في أي مشروع. لأن أي تعديل على الملف التالي: /vendor/laravel/fortify/routes/routes.php وعند القيام بالأمر: composer update ستذهب أي تعديلات تم إجرائها ضمن المجلد vendor. وبالتالي لن يتم حفظها بشكل دائم. أما عند استخدام Fortify وإضافة مسارات أخرى في المشروع فيتم ذلك عن طريق وضع وسيط middleware باسم fortify ضمن نفس مجلد تعريف مسارات المشروع web.php كالتالي: Route::group(['middleware' => config('fortify.middleware', ['web'])], function () { Route::get('home', function () { return 'Home'; }) }); ويمكن أيضاً استخدام auth لمسارات معيّنة عن طريق إضافة: Route::get('newpage', function () { return 'newpage'; }) ->middleware(['auth']);
- 1 جواب
-
- 2
-
معنى هذا الخطأ هو عدم وجود صلاحيات للكتابة على المسار المذكور. حيث سيتم المتابعة بتحميل المكتبات المستخدمة في Laravel ولكن لن يملك المشروع القدرة على استخدام الكاش بسبب عدم امتلاكه الصلاحيات للكتابة أو التعديل على المجلد cache. لذلك يجب عليك تعديل الصلاحيات على مجلد المشروع بشكل عام أو فقط مجلد الكاش في حال كانت المشكلة موجود فقط ضمنه أولاً: نقوم بتغيير صلاحيات المجموعة على المجلد كالتالي: sudo chown -R amir123 /home/amir123/.composer/cache/repo/mynewwebsite.org بافتراض أن اسم المستخدم الجذر لديك هو كما مذكور في نص السؤال amir123 وأيضاً نقوم بتعديل صلاحيات الكتابة على المجلد Files: sudo chown -R amir123 /home/amir123/.composer/cache/files/ وفي حال بقيت المشكلة، أيضاً حاول تعديل الصلاحيات على composer: sudo chown -R amir123 /home/amir123/.composer ليتمكن من الكتابة وتعديل الملفات في حال كانت إعدادات الخادم لديك عكس ذلك.
- 1 جواب
-
- 1
-
سبب المشكلة التي تواجهها هو عدم توافق بين الإصدارات، فيبدو أنك تقوم باستخدام مكتبة React /DNS ضمن التطبيق، و إن البعض من إصداراتها غير متوافق مع آخر نسخة من Laravel websockets. الحل هو بأن تقوم بتخفيض النسخة المستخدمة من Reac/DNS إلى النسخة 0.4.19 عن طريق composer كالتالي: composer require react/dns:^0.4.19 بعدها يمكنك إعادة التشغيل عن طريق نفس الأمر للتأكد من أن الإصدار 0.4.19 متوافق ويعمل بشكل صحيح مع laravel websockets: php artisan websockets:serve
- 1 جواب
-
- 2
-
أولاً يجب عليك التأكد من استخدام نفس المنفذ الذي يتم استعماله في websockets ضمن الحزمة، ووضعه في ملف dokcer-compose. علماً بأن المنفذ الافتراضي في حال لم تقم بتغييره هو 6001. ثم يمكنك فصّل الخصائص عن بعضها لحاويتين منفصلتين، بحيث تقوم الحاوية الأولى بتشغيل تطبيق لارافيل والحاوية الأخرى تقوم بالاتصال مع websockets على الشكل التالي: ملف الحاوية الأولى app.dockerfile FROM php:7-cli-alpine RUN apk --update add wget \ curl \ git \ grep \ build-base \ libmemcached-dev \ libmcrypt-dev \ libxml2-dev \ imagemagick-dev \ pcre-dev \ libtool \ make \ autoconf \ g++ \ cyrus-sasl-dev \ libgsasl-dev RUN docker-php-ext-install mysqli pdo pdo_mysql tokenizer xml RUN pecl channel-update pecl.php.net \ && pecl install memcached \ && pecl install imagick \ && pecl install mcrypt-1.0.3 \ && docker-php-ext-enable memcached \ && docker-php-ext-enable imagick \ && docker-php-ext-enable mcrypt RUN rm /var/cache/apk/* && \ mkdir -p /var/www ENTRYPOINT ["/usr/bin/php", "/var/www/html/websocket-service/artisan", "websockets:serve"] ملف web.dockerfile: FROM php:7-fpm-alpine RUN apk --update add wget \ curl \ git \ grep \ build-base \ libmemcached-dev \ libmcrypt-dev \ libxml2-dev \ imagemagick-dev \ pcre-dev \ libtool \ make \ autoconf \ g++ \ cyrus-sasl-dev \ libgsasl-dev RUN docker-php-ext-install mysqli pdo pdo_mysql tokenizer xml RUN pecl channel-update pecl.php.net \ && pecl install memcached \ && pecl install imagick \ && pecl install mcrypt-1.0.3 \ && docker-php-ext-enable memcached \ && docker-php-ext-enable imagick \ && docker-php-ext-enable mcrypt RUN rm /var/cache/apk/* && \ mkdir -p /var/www ولجعل المنفذ 6001 مرئياً خارج الحاوية، نقوم بتغيير التوجيهات لتصبح كالتالي: app: build: context: ./ dockerfile: app.dockerfile working_dir: /var/www/html volumes: - ./:/var/www/html ports: - "6001:6001" environment: - DB_PORT=${DB_PORT} - DB_HOST=${DB_HOST}
- 1 جواب
-
- 2
-
يمكنك إنشاء middleware جديد خاص بال broadcast وربطه مع kernel.php: 'broadcast' => \App\Http\Middleware\Broadcast::class ثم تعديل broadcast.php ليصبح كالتالي: public function handle($request, Closure $next) { $web = Auth::guard('web')->user(); if ($web) { return response()->json(\Illuminate\Support\Facades\Broadcast::auth($request)); } return response()->json('Unauthorized.', 500); } ثم للمصدر الآخر المختلف عن الويب، يجب إرسال التحقق على الشكل التالي: Route::post('/guard/broadcast/auth', function(\Illuminate\Support\Facades\Request $req){ return true; })->middleware('broadcast'); بحيث يتم استخدام middleware نفسه. ثم عند إرسال الطلب من جهة المستخدم pusher، يجب الإرسال للقناة التابعة ل guard معيّن: <script> let pusher = new Pusher("{{ env('PUSHER_APP_KEY') }}", { cluster: 'ar2', encrypted: true, auth: { headers: { 'X-CSRF-TOKEN': "{{ csrf_token() }}" } }, authEndpoint: '{{ env('APP_URL') }}' + '/guard/broadcast/auth', }); let channel = pusher.subscribe('private-channel.{{ Auth::user()->id }}'); channel.bind('my-event', addMessage); function addMessage(data) { console.log(data); } </script> وبذلك يمكن تحديدها عن طريق تزويد الطلب ب parameter يدعى authEndpoint authEndpoint: '{{ env('APP_URL') }}' + '/guard/broadcast/auth',
- 1 جواب
-
- 1
-
يحدث هذا الخطأ عندما تمرر قيمة null إلى الحلقة، أي بمعنى آخر عند عدم وجود أعمال للقيام بها. وبالتالي يتم التوقف عن إرسال العمليات إلى الرتل ويعطي رسالة الخطأ لعدم وجود أي بيانات لإجراء حلقة التكرار عليها. يوجد أمر آخر لمنع حدوث ذلك أثناء تشغيل الرتل هو: php artisan queue:work --stop-when-empty ويقوم بدوره بإيقاف العمل عند عدم وجود أي عمليات ضمن الرتل. ولكن هذه الطريقة متبعة فقط للأعمال الصغيرة والتي لا تتطلب الكثير من الوقت. فبفرض تراكم عدد من الأعمال أكبر من 20 مثلاً وسيتم تكراره كل دقيقة، فذلك أيضاً سيسبب خطأ آخر أو تضارب في المعلومات لأن العملية السابقة لم تكن قد انتهت قبل البدء بالعملية التالية وهكذا. الأسلوب المتبع لحل هذه المشاكل وخاصة عند وجود كمية أكبر من العمليات هو كالتالي: أولاً نقوم بإنشاء أمر جديد لإرسال الرسائل: php artisan make:command SendContactEmails ضمن الملف SendContactEmails.php نقوم بالتغيير التالي: protected $signature = 'emails:work'; وضمن التابع handle: return $this->call('queue:work', [ '--queue' => 'emails', '--stop-when-empty' => null, ]); ثم ضمن app/Console/Kernal.php نضيف الأمر السابق: protected $commands = [ \App\Console\Commands\SendContactEmails::class ]; وأخيراً يتم جدولة الأمر السابق كل دقيقة بالشكل التالي: protected function schedule(Schedule $schedule) { $schedule->command('emails:work')->everyMinute()->withoutOverlapping(); } حيث سيسمح استخدام withoutOverlapping من تضارب العمليات وانتهاء العملية السابقة قبل البدء بالعملية التي تليها ويتم بعدها تشغيل cron بالأمر التالي: * * * * * /usr/local/bin/php /home/username/project/artisan schedule:run > /dev/null 2>&1
- 1 جواب
-
- 1
-
يمكنك معالجة هذه المشكلة باستخدام قيم متغيّرة بدلاً من القيم الثابتة أثناء تعريف Redis. فأولاً يجب تغيير تعريف redis ضمن config/database.php ليصبح على الشكل التالي: 'redis' => [ 'cluster' => false, 'default' => [ 'host' => env('REDIS_HOST', 'localhost'), 'password' => env('REDIS_PASSWORD', null), 'port' => env('REDIS_PORT', 6379), 'database' => 0, ], 'session' => [ 'host' => env('REDIS_HOST', 'localhost'), 'password' => env('REDIS_PASSWORD', null), 'port' => env('REDIS_PORT', 6379), 'database' => 1, ], ], وبذلك يتم استخدام قيم قابلة للتغير من بين القيم المعرفة ضمن .env وبعدها ستحتاج لتغيير ioc binding باستخدام الصف Illuminate\Cache\CacheManager : class MyCacheManager extends Illuminate\Cache\CacheManager { protected function createRedisDriver(array $config) { try { return parent::createRedisDriver($config); } catch (\Exception $e) { //يتم العودة للتخزين الافتراضي Redis في حال حدوث خطأ في return $this->resolve('file'); } } } ثم ضمن ملف مزود الخدمة ServiceProvider تأكد من استخدام النمط singleton أثناء التعامل مع البيانات وتعديل التابع الخاص بذلك بإضافة الصف الذي قمت بإنشائه: $this->app->singleton('cache', function($app) { return new MyCacheManager($app); }); وأيضاً هنالك بعض المكتبات والحزم التي أنجزها مطورين لحل هذه المشكلة، ومنها حزمة Laravel-Redis-Fallback وأيضاً حزمة Laravel-cache-fallback
-
يوجد طريقتين لمعالجة هذا الخطأ عند الحاجة لإرسال كمية كبيرة من البيانات دفعة واحدة: إما يتم فقط إرسال ID معيّن ونوع الحدث إلى pusher وبالتالي تجعل المستخدم هو من يقوم بطلب البيانات عن طريق HTTP: public function broadcastWith() { return [ 'id' => $this->content->id, 'event_type' => 'request_content' ]; } أو عن طريق تخفيض حجم البيانات المرسلة باستخدام JsonResource: public function broadcastWith() { return [ 'content' => new \App\Http\Resources\PostResource($this->content), ]; } وعندها يتم الوراثة من صف JsonResource كالتالي: class ContentResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'title' => $this->title, 'body' => $this->body, ]; } } ومع ذلك ، فإن هذا النهج آمن فقط إذا كنت تعرف بالتأكيد أن البيانات التي ترسلها لا يمكن بأي حال من الأحوال تجاوز حد 10 كيلوبايت. ويمكن ضمان ذلك من خلال التحقق من صحة الإدخال ، والقيود المفروضة على أعمدة قاعدة البيانات (الحجم المحدد لكل عمود) أو وسائل أخرى إضافية مثل Request Validations.
- 1 جواب
-
- 1
-
بمجرّد التحدث عن نسبة أمان عالية، فهذا يعني (الحاجة) لاستخدام mysql. فنسبة الأمان العالية تعني تشفير كلمات المرور وتخزينها في بيئة محمية لمنع الوصول لها. وتخزينها ضمن بيئة mysql بما يحويه من عوامل حماية وصلاحيات تجعل ذلك ممكناً بدلاً من تخزينها ضمن ملفات موجودة بين ملفات الموقع الأخرى على الخادم وبالتالي تكون عرضة للوصول إليها. كما أنه من ناحية الأداء، التعامل مع البيانات ضمن ملفات لا يقارن بالتعامل مع البيانات في قاعدة بيانات فهي أسرع بأضعاف وتوفر سهولة وديناميكية في التعامل مع البيانات.
- 4 اجابة
-
- 1