قررت أن أصنع محفظتي باستخدام Laravel 7. بحيث تكون الصفحة الرئيسية هي الصفحة المقصودة، ويمكن تغيير جميع المعلومات الموجودة عليها باستخدام لوحة الإدارة. لا نقطة. وصل الأمر إلى النشر. لقد وجدت بضعة برامج تعليمية جيدة حول كيفية القيام بذلك على خادم كامل مع كل المشاكل. أنا لست قويًا جدًا في النشر، فأنا بشكل عام أكثر تقدمًا من المكدس الكامل. وإذا كان لا يزال بإمكاني الكتابة والاختبار في PHP، فقبل إدارة الخادم، وما إلى ذلك. أنا لم أكبر بعد. ولكن كان علي معرفة ذلك.
الآن سننفذ جميع الخطوات، بدءًا من التشغيل عبر SSH وانتهاءً بموقع العمل. سنحاول تجنب كل المزالق.
قد تتمكن من العثور على تعليمات مماثلة عبر الإنترنت. بعد كل شيء، وأخيرا وجدت ذلك. صحيح، ليس في مكان واحد، وليس بدون مساعدة StackOverflow، وبالكاد باللغة الروسية. عانيت. ولهذا السبب قررت تبسيط حياتك.
سنفعل كل شيء بقطرة صغيرة على DigitalOcean. وهذا بالطبع ليس ضروريا، اختر أي استضافة. عندما تصل إلى خادم يعمل على Ubuntu، عد. بالنسبة لأولئك الذين ما زالوا يقررون القيام بذلك على DigitalOcean، سيكون هناك المزيد من النصائح حول إعداد النطاق. و
سيتم ذكر جميع الخطوات الخاصة بـ DigitalOcean في الحواشي السفلية مثل هذه.
هيا بنا نبدأ.
TL;DR (الأوامر الأساسية فقط)
قم بإنشاء مستخدم
ssh root@[IP-адрес вашего дроплета]
adduser laravel
usermod -aG sudo laravel
su laravel
أضف SSH إليها
mkdir ~/.ssh
chmod 700 ~/.ssh
vim ~/.ssh/authorized_keys
- أدخل المفتاح العام
chmod 600 ~/.ssh/authorized_keys
جدار الحماية
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
إنجن إكس
sudo apt update
sudo apt install -y nginx
sudo ufw allow 'Nginx HTTP'
sudo ufw status
MySQL
sudo apt install -y mysql-server
sudo mysql_secure_installation
,NYNNY
sudo mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '<Ваш пароль для MySQL>';
SELECT user,authentication_string,plugin,host FROM mysql.user;
FLUSH PRIVILEGES;
exit
PHP
-
sudo apt update
-
sudo apt install -y curl wget gnupg2 ca-certificates lsb-release apt-transport-https
-
sudo apt-add-repository ppa:ondrej/php
-
sudo apt update
-
7.3:
sudo apt install -y php7.3-fpm php7.3-mysql
-
7.4:
sudo apt install -y php7.4-fpm php7.4-mysql
-
sudo vim /etc/nginx/sites-available/<Ваш домен>
الإعداد الأساسي:
server {
listen 80;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name <Ваш домен или IP>;
location / {
try_files $uri $uri/ =404;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location ~ /.ht {
deny all;
}
}
إعداد HTTP فقط لـ Laravel:
server {
listen 80;
listen [::]:80;
root /var/www/html/<Имя проекта>/public;
index index.php index.html index.htm index.nginx-debian.html;
server_name <Ваш домен или IP>;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location ~ /.ht {
deny all;
}
}
إعداد HTTPS لـ Laravel:
server {
listen 80;
listen [::]:80;
server_name <Ваш домен> www.<Ваш домен>;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name <Ваш домен> www.<Ваш домен>;
root /var/www/html/<Имя проекта>/public;
ssl_certificate /etc/letsencrypt/live/<Ваш домен>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<Ваш домен>/privkey.pem;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers on;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.php index.html index.htm index.nginx-debian.html;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location ~ /.ht {
deny all;
}
location ~ /.well-known {
allow all;
}
}
sudo ln -s /etc/nginx/sites-available/<Ваш домен> /etc/nginx/sites-enabled/
sudo unlink /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
لارافل
-
7.3:
sudo apt install -y php7.3-mbstring php7.3-xml composer unzip
-
7.4:
sudo apt install -y php7.4-mbstring php7.4-xml composer unzip
-
mysql -u root -p
-
CREATE DATABASE laravel DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
-
GRANT ALL ON laravel.* TO 'root'@'localhost' IDENTIFIED BY '<Ваш пароль от MySQL>';
-
FLUSH PRIVILEGES;
-
exit
-
cd /var/www/html
-
sudo mkdir -p <Имя проекта>
-
sudo chown laravel:laravel <Имя проекта>
-
cd ./<Имя проекта>
-
git clone <ссылка на проект> .
/git clone -b <имя ветки> --single-branch <ссылка на проект> .
-
composer install
-
vim .env
APP_NAME=Laravel
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=http://<Ваш домен>
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=<Ваш пароль от MySQL>
-
php artisan migrate
-
php artisan key:generate
-
sudo chown -R $USER:www-data storage
-
sudo chown -R $USER:www-data bootstrap/cache
-
chmod -R 775 storage
-
chmod -R 775 bootstrap/cache
HTTPS
-
sudo add-apt-repository ppa:certbot/certbot
-
sudo apt install -y python-certbot-nginx
-
sudo certbot certonly --webroot --webroot-path=/var/www/html/<Имя проекта>/public -d <Ваш домен> -d www.<Ваш домен>
-
sudo nginx -t
-
sudo ufw allow 'Nginx HTTPS'
-
sudo ufw status
-
sudo systemctl reload nginx
قم بإنشاء قطرة على DigitalOcean وقم بتسجيل مفتاح SSH جديد
أعتقد حقًا أنك ستكتشف كيفية التسجيل في DigitalOcean بنفسك. الأمر ليس سهلاً، مع وجود الكثير من عمليات التحقق وأشياء أخرى. إذا كنت تحصل باستمرار على خطأ في الشبكة عند التحقق باستخدام المستندات، فحاول القيام بكل شيء من خلال VPN، فمن المفترض أن يساعدك ذلك.
في القائمة في الأعلى، انقر على إنشاء->قطرات. يختار أوبونتو.
بمجرد التسجيل، سوف تتلقى 100 دولار في حسابك. ولكن لا تنخدع. لديك 60 يومًا فقط لقضاءها. وهذا قليل جدًا. قد ترغب، مثلي، في استخدام خطة أكثر تكلفة، بحيث يمكنك لاحقًا، عندما يبدأ تدفق الأموال الحقيقية، التبديل إلى خطة أرخص. سأخبرك على الفور أنه لن ينجح. يمكنك زيادتها، لكن لا يمكنك تقليلها. لذلك يذهب. انا اخترت المجموعة الأساسية ->$5.
اخترت المنطقة الأقرب إلينا فرانكفورت. شبكة VPC->الافتراضي-fra1
سنقوم بإجراء المصادقة على الفور عبر SSH. انقر مفتاح SSH جديد. إذا لم يكن لديك SSH، فهناك تعليمات بسيطة جدًا على اليمين. افتح محطة bash والصقها
ssh-keygen
. ثم نذهب إلى الملف بالمفتاح العام/Users/<Ваше имя пользователя>/.ssh/id_rsa.pub
(أو ببساطةcat ~/.ssh/id_rsa.pub
)، انسخ المحتويات والصقه في النافذة الموجودة على اليسار. اي اسم.لقد توصلنا إلى اسم مضيف للقطرة.
انقر إنشاء قطرة
إنشاء مستخدم جديد
ssh root@[IP-адрес вашего дроплета]
- هل أنت متأكد من رغبتك في مواصلة الاتصال (نعم/لا/[بصمة الإصبع])؟
yes
- أدخل كلمة مرور SSH الخاصة بك
- قم بإنشاء مستخدم laravel:
adduser laravel
- أدخل كلمة المرور والمعلومات الأخرى (أدخل الاسم الكامل فقط)
- أضف المستخدم إلى مجموعة Sudo:
usermod -aG sudo laravel
SSH للمستخدم الجديد
- التبديل إلى المستخدم الجديد:
su laravel
نقوم بتنفيذ جميع الإجراءات حتى نهاية المقالة نيابة عن مستخدم Laravel. لذلك، إذا تمت مقاطعتك فجأة، فأعد تسجيل الدخول وادخل su laravel
mkdir ~/.ssh
chmod 700 ~/.ssh
vim ~/.ssh/authorized_keys
فتحنا الملف في Vim. لو مش مطلع عليها خالص تقدر تشتغل بالنانو حقك.
أوامر Vim الأساسية
من أجل استخدام محرر Vim خلال المقالة، تحتاج فقط إلى معرفة ما يلي.
- يحتوي Vim على أوضاع مختلفة: الوضع العادي، حيث تقوم بإدخال الأوامر وتحديد الأوضاع وغيرها.
- للخروج من أي وضع والعودة إلى الوضع العادي، فقط اضغط على
Esc
- التحرك: يمكنك فقط استخدام الأسهم
- الخروج بدون حفظ
<Normal mode>
::q!
- الخروج والحفظ
<Normal mode>
::wq
- التبديل إلى وضع إدخال النص
<Normal mode>
:i
(من اللغة الإنجليزية. أدخل)
- نقوم بإدخال مفتاحنا العام (وهو ما فعلناه أعلاه)
- نحن نحمي من التغييرات:
chmod 600 ~/.ssh/authorized_keys
تثبيت جدار الحماية
- دعونا نلقي نظرة على جميع الإعدادات المتاحة:
sudo ufw app list
- السماح بـ OpenSSH (وإلا فإنه سيغلقنا):
sudo ufw allow OpenSSH
- لنقم بتشغيل جدار الحماية:
sudo ufw enable
,y
- نتحقق من:
sudo ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
كل شيء على ما يرام.
تثبيت نجينكس
أثناء التثبيت، سيتم سؤالك أحيانًا "هل أنت متأكد؟" إجابة y
(حسنا، فقط إذا كنت متأكدا).
sudo apt update
sudo apt install nginx
إضافة Nginx إلى إعدادات جدار الحماية
sudo ufw app list
sudo ufw allow 'Nginx HTTP'
sudo ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)
انتقل إلى IP الخاص بك. إذا سارت الأمور على ما يرام، يجب أن ترى ما يلي.
تثبيت الخلية
sudo apt install mysql-server
- إطلاق برنامج نصي للحماية التلقائية
sudo mysql_secure_installation
أجب عن الأسئلة المطروحة. إذا كنت لا تعرف ماذا تجيب، فإليك بعض الخيارات المقترحة:
-
التحقق من صحة كلمة المرور -
N
-
هل ترغب في إزالة المستخدمين المجهولين؟ —
Y
-
عدم السماح بتسجيل الدخول إلى الجذر عن بعد؟ —
N
-
إزالة قاعدة بيانات الاختبار والوصول إليها؟ —
N
-
هل تريد إعادة تحميل جداول الامتيازات الآن؟ —
Y
-
دعنا نذهب إلى MySQL:
sudo mysql
-
دعونا نلقي نظرة على طرق الوصول:
SELECT user,authentication_string,plugin,host FROM mysql.user;
-
تعيين كلمة مرور للجذر:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '<Ваш пароль для MySQL>';
-
دعونا نلقي نظرة على طرق الوصول مرة أخرى:
SELECT user,authentication_string,plugin,host FROM mysql.user;
-
قم بتطبيق التغييرات والخروج من MySQL:
FLUSH PRIVILEGES;
иexit
-
الآن، لتسجيل الدخول إلى MySQL، عليك استخدام
mysql -u root -p
وأدخل كلمة المرور
تثبيت بي اتش بي
دعونا نستخدم مستودع جهة خارجية من
sudo apt update
sudo apt install -y curl wget gnupg2 ca-certificates lsb-release apt-transport-https
sudo apt-add-repository ppa:ondrej/php
sudo apt update
الآن دعونا نختار. بالنسبة إلى Laravel 7، يمكنك اختيار PHP 7.3 أو 7.4. الفرق الوحيد سيكون في الرقمين 3 و 4.
- 7.3:
sudo apt install -y php7.3-fpm php7.3-mysql
- 7.4:
sudo apt install -y php7.4-fpm php7.4-mysql
يعمل PHP FastCGI Process Manager (fpm) مع طلبات PHP. MySQL، بالطبع، للعمل مع MySQL.
من الآن فصاعدا سأفعل كل شيء على 7.4.
إعداد إنجينكس
sudo vim /etc/nginx/sites-available/<Ваш домен>
بدلاً من "<نطاقك>" أدخل المجال (على سبيل المثال، mysite.ru
) الذي تريد استخدامه في المستقبل. إذا لم يكن لديك واحد حتى الآن، فاكتب أيًا منه، ثم كرر الخطوات الواردة في هذا الفصل لنطاقك عند تحديده.
أدخل التالي:
server {
listen 80;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name <Ваш домен или IP>;
location / {
try_files $uri $uri/ =404;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location ~ /.ht {
deny all;
}
}
إذا اخترت الإصدار 7.3 بدلا من ذلك php7.4-fpm.sock
يدخل php7.4-fpm.sock
.
الاستماع إلى المنفذ 80 على server_name
عندما نصل إلى طلب الجذر /var/www/html
خذ ملف الفهرس. إذا بعد server_name
هناك شيء ما، ونحن نبحث عن مثل هذا الملف. إذا لم نجده، فإننا نطرد 404. إذا انتهى بـ .php
، من خلال fpm
... إذا كان هناك .ht
، المنع (403).
- صنع رابط من
sites-available
вsites-enabled
:sudo ln -s /etc/nginx/sites-available/<Ваш домен> /etc/nginx/sites-enabled/
- إزالة الرابط ل
default
:sudo unlink /etc/nginx/sites-enabled/default
- التحقق من الأخطاء:
sudo nginx -t
- اعادة التشغيل:
sudo systemctl reload nginx
التحقق من العمل:
sudo vim /var/www/html/info.php
- نحن نكتب:
<?php phpinfo();
- المضي قدما
<Ваш IP>/info.php
يجب أن نرى شيئا من هذا القبيل:
الآن يمكن حذف هذا الملف: sudo rm /var/www/html/info.php
قم بتثبيت لارافيل
-
7.3:
sudo apt install php7.3-mbstring php7.3-xml composer unzip
-
7.4:
sudo apt install php7.4-mbstring php7.4-xml composer unzip
-
دعنا نذهب إلى MySQL:
mysql -u root -p
-
إنشاء قاعدة بيانات بالاسم laravel:
CREATE DATABASE laravel DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
-
نحن نقدم الوصول إلى الجذر laravel:
GRANT ALL ON laravel.* TO 'root'@'localhost' IDENTIFIED BY '<Ваш пароль от MySQL>';
-
FLUSH PRIVILEGES;
-
exit
-
cd /var/www/html
-
إنشاء مجلد للمشروع:
sudo mkdir -p <Имя проекта>
-
نحن نقدم للمستخدم laravel حقوق المشروع:
sudo chown laravel:laravel <Имя проекта>
بعد ذلك تحتاج إلى نقل المشروع. على سبيل المثال، الاستنساخ من جيثب.
cd ./<Имя проекта>
git clone <ссылка на проект> .
تجدر الإشارة إلى أنه إذا لم تقم بحفظ الملفات الثابتة (على سبيل المثال، من /public
) على جيثب، فمن الطبيعي أنك لن تحصل عليها. على سبيل المثال، قمت بإنشاء موضوع منفصل لحل هذه المشكلة deploy
، والتي قمت باستنساخها بالفعل: git clone -b <имя ветки> --single-branch <ссылка на проект> .
.
- تثبيت التبعيات:
composer install
- إنشاء .env:
vim .env
النسخة الأساسية منه تبدو كما يلي:
APP_NAME=Laravel
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=http://<Ваш домен>
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=<Ваш пароль от MySQL>
إذا قمت بنسخ ملف .env الخاص بك، فاستبدل APP_ENV بالإنتاج، وAPP_DEBUG بـ false وأدخل الإعدادات الصحيحة لـ MySQL.
- ترحيل قاعدة البيانات:
php artisan migrate
- توليد الكود:
php artisan key:generate
تغيير الأذونات:
sudo chown -R $USER:www-data storage
sudo chown -R $USER:www-data bootstrap/cache
chmod -R 775 storage
chmod -R 775 bootstrap/cache
آخر شيء بقي هو إعادة تكوين Nginx لـ Laravel:
sudo vim /etc/nginx/sites-available/<Ваш домен>
server {
listen 80;
listen [::]:80;
root /var/www/html/<Имя проекта>/public;
index index.php index.html index.htm index.nginx-debian.html;
server_name <Ваш домен или IP>;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location ~ /.ht {
deny all;
}
}
مثل المرة السابقة، إذا اخترت الإصدار 7.3 بدلاً من ذلك php7.4-fpm.sock
يدخل php7.4-fpm.sock
.
إعداد نطاق على DigitalOcean
كل شيء في الواقع بسيط للغاية. يمكنك شراء نطاق (في أي مكان)، ثم التبديل إلى DigitalOcean على إنشاء->المجالات/DNS. п поле إضافة مجال قمت بإدخال هذا المجال وانقر فوق إضافة. ثم انتقل إلى إعدادات المجال وإلى الحقل HOSTNAME يدخل @. حدد المشروع وانقر فوق إنشاء سجل.
انتقل الآن إلى الموقع الذي اشتريت منه النطاق، وابحث عن "خوادم DNS" هناك (أو شيء مشابه) وأدخل إلى خوادم DigitalOcean (أيns1.digitalocean.com
,ns2.digitalocean.com
,ns3.digitalocean.com
). أنت الآن بحاجة إلى الانتظار قليلاً (أو كثيرًا) حتى يتم قبول هذه الإعدادات. مستعد!
المشكلة الوحيدة هي أن موقعك سيتم فتحه فقط بتنسيق HTTP. للحصول على HTTPS، انتقل إلى الجزء التالي.
إعداد HTTPS
قم بتثبيت certbot وتمرير اسم المجال إليه (format mysite.ru
) واسم المجال مع www (www.mysite.ru
).
sudo add-apt-repository ppa:certbot/certbot
sudo apt install python-certbot-nginx
sudo certbot certonly --webroot --webroot-path=/var/www/html/<Имя проекта>/public -d <Ваш домен> -d www.<Ваш домен>
أنت الآن بحاجة إلى إعادة تكوين Nginx (لا تنس استبدال قيمك):
server {
listen 80;
listen [::]:80;
server_name <Ваш домен> www.<Ваш домен>;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name <Ваш домен> www.<Ваш домен>;
root /var/www/html/<Имя проекта>/public;
ssl_certificate /etc/letsencrypt/live/<Ваш домен>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<Ваш домен>/privkey.pem;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers on;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.php index.html index.htm index.nginx-debian.html;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location ~ /.ht {
deny all;
}
location ~ /.well-known {
allow all;
}
}
أعتقد أنك تفهم بالفعل ما يجب تغييره في PHP 7.3.
هنا، في الواقع، كل شيء بسيط. نقوم ببساطة بإعادة توجيه جميع الطلبات من HTTP (المنفذ 80) إلى HTTPS (المنفذ 443). وهناك نفعل كل شيء كما كان من قبل، ولكن مع التشفير.
كل ما تبقى هو تعيين الأذونات في جدار الحماية:
sudo nginx -t
sudo ufw app list
sudo ufw allow 'Nginx HTTPS'
sudo ufw status
sudo systemctl reload nginx
الآن كل شيء يجب أن يعمل كما ينبغي.
[متقدم] تثبيت Node.js
إذا كنت بحاجة فجأة إلى تشغيل أوامر npm مباشرة على الخادم، فستحتاج إلى تثبيت Node.js.
sudo apt update
sudo apt install -y nodejs npm
nodejs -v
وخلاص توقفت عند هذه المرحلة. من حيث المبدأ، أنا راض عن النتيجة. ربما سأتحول من DigitalOcean إلى مكان أقرب إلى روسيا وأرخص. ولكن بما أنني قمت بالفعل بإجراء جميع جولات التحقق على الموقع وفعلت كل شيء هناك، فقد أظهرت لهم المثال. بالإضافة إلى ذلك، فإن مبلغهم المبدئي البالغ 100 دولار هو نقطة انطلاق ممتازة للتدريب.
ملاحظة: شكر خاص للمؤلف
PPS إذا كنت من كبار المهندسين الذين يفكرون في أوامر bash، فيرجى عدم الحكم بقسوة. ربما تجد أن هذه المقالة ذات مستوى منخفض، لكني سأكون سعيدًا بالعثور على واحدة عندما أحتاج إليها. إذا كانت هناك اقتراحات للتحسين، فأنا أؤيدها تمامًا.
المصدر: www.habr.com