Verification: a143cc29221c9be0

Php artisan storage link на хостинге

Php artisan storage link на хостинге

Подготовка

Вне зависимости от выбранного фреймоворка потребуется Composer - менеджер зависимостей для PHP. Если на аккаунте его ещё нет - установить его Вы можете по нашей инструкции.

Установка Yii

Yii имеет два варианта установки - basic и advanced. Они имеют достаточно существенные различия, поэтому разберём каждый вариант по отдельности.

Установка Yii Basic

Начнём с наиболее простого варианта веб-приложения - Yii Basic. Сначала создадим сайт, на который будет произведена установка. Для этого откройте раздел Сайты в панели управления и задайте имя каталога, в котором будет размещён сайт.

После этого нажмите напротив сайта кнопку "Прикрепить домен" и выберите домен, по которому сайт должен быть доступен.

Если своего домена у Вас ещё нет - Вы можете зарегистрировать его в разделе Домены и поддомены Панели управления либо воспользоваться предоставляемым нами техническим доменом. Мы воспользуемся техническим доменом и добавим к нему поддомен yii-basic. Для этого откроем раздел "Домены и поддомены" и введём полное имя домена в форму добавления. Прикрепим домен к ранее созданному нами сайту. Также сайт можно создать при добавлении поддомена - выбирайте удобный Вам вариант.

После проделанных действий в разделе Сайты Вы должны видеть примерно такую структуру:

Далее подключимся к нашей учётной записи по SSH и произведём установку фреймворка. Мы будем устанавливать его в каталог yii-basic. Для этого нам понадобится удалить всё его содержимое:

account@server:~ [0] $ rm -r yii-basic/public_html/

Перейдём в каталог для установки.

account@server:~ [0] $ cd yii-basic/

Загрузим архив с готовым шаблоном приложения и распакуем его:

account@server:~/yii-basic [0] $ wget -q https://github.com/yiisoft/yii2/releases/download/2.0.11/yii-basic-app-2.0.11.tgz
account@server:~/yii-basic [0] $ tar xzf yii-basic-app-2.0.11.tgz --strip 1
account@server:~/yii-basic [0] $

Обновим зависимости:

account@server:~/yii-basic [0] $ composer update
The "extra.asset-installer-paths" option is deprecated, use the "config.fxp-asset.installer-paths" option
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 26 updates, 0 removals
  - Updating swiftmailer/swiftmailer (v5.4.5 => v5.4.8) Loading from cache
  - Updating ezyang/htmlpurifier (v4.8.0 => v4.9.2) Loading from cache
  - Updating bower-asset/jquery.inputmask (3.3.4 => 3.3.6) Loading from cache
  - Updating yiisoft/yii2 (2.0.11 => 2.0.11.2) Loading from cache
  - Updating yiisoft/yii2-swiftmailer (2.0.6 => 2.0.7) Loading from cache
  - Updating yiisoft/yii2-debug (2.0.7 => 2.0.9) Loading from cache
  - Updating symfony/debug (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/console (v3.2.2 => v3.2.8) Loading from cache
  - Installing stecman/symfony-console-completion (0.7.0) Loading from cache
  - Updating sebastian/diff (1.4.1 => 1.4.2) Loading from cache
  - Updating symfony/dom-crawler (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/css-selector (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/browser-kit (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/yaml (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/event-dispatcher (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/finder (v3.2.2 => v3.2.8) Loading from cache
  - Updating guzzlehttp/psr7 (1.3.1 => 1.4.2) Loading from cache
  - Updating sebastian/code-unit-reverse-lookup (1.0.0 => 1.0.1) Loading from cache
  - Updating phpunit/php-token-stream (1.4.9 => 1.4.11) Loading from cache
  - Updating phpunit/php-code-coverage (4.0.5 => 4.0.8) Loading from cache
  - Updating sebastian/object-enumerator (2.0.0 => 2.0.1) Loading from cache
  - Updating phpunit/php-timer (1.0.8 => 1.0.9) Loading from cache
  - Updating phpspec/prophecy (v1.6.2 => v1.7.0) Loading from cache
  - Updating myclabs/deep-copy (1.6.0 => 1.6.1) Loading from cache
  - Updating phpunit/phpunit (5.7.9 => 5.7.19) Loading from cache
  - Updating codeception/base (2.2.8 => 2.2.11) Loading from cache
  - Updating codeception/verify (0.3.2 => 0.3.3) Loading from cache
Writing lock file
Generating autoload files
account@server:~/yii-basic [0] $

Для корректной работы веб-сервера необходимо создать ссылку c именем public_html, указывающую на каталог web.

account@server:~/yii-basic [0] $ ln -s web public_html

Теперь необходимо дополнить базовую конфигурацию. Сгенерируем ключ, который будет использоваться для валидации cookies. Его необходимо внести в файл конфигурации config/web.php как значение ключа cookieValidationKey.

account@server:~/yii-basic [0] $ openssl rand -base64 12 | md5sum
84f8bcc820c11850a6c34afc2b192e29 -
account@server:~/yii-basic [0] $

Если на сайте предполагается использование базы данных - понадобится также отредактировать файл config/db.php. В этом файле нужно изменить dsn, указав в параметре dbname имя Вашей базы, а также ключи username и password. Значение параметра dsn в результате должно быть примерно таким: mysql:host=localhost;dbname=account_yii2

Обратите внимание!

На нашем хостинге имя пользователя MySQL всегда соответствует имени базы данных.

На этом настройка базовой версии Yii завершена и приложение полностью готово к дальнейшемму использованию.

Установка Yii Advanced

Версия Advanced имеет более сложную структуру и собственную админ-панель, которую обычно размещают на отдельном домене. Соответственно, несколько изменяется и порядок установки. Подготовительный этап с установкой Composer (при необходимости) и созданием сайта аналогичен процессу установки Yii Basic. Единственное отличие - в необходиомости прикрепления к сайту двух доменов, а не одного. У нас будут поддомены yii-advanced и backend.yii-advanced, прикреплённые к сайту yii-advanced.

В панели управления эта структура будет выглядеть так:

Удалим содержимое созданного сайта, загрузим и распакуем архив с приложением, обновим зависимости.

account@server:~/yii-advanced.account.beget.tech [0] $ rm -r public_html/
account@server:~/yii-advanced.account.beget.tech [0] $ wget -q https://github.com/yiisoft/yii2/releases/download/2.0.11/yii-advanced-app-2.0.11.tgz
account@server:~/yii-advanced.account.beget.tech [0] $ tar xzf yii-advanced-app-2.0.11.tgz --strip 1
account@server:~/yii-advanced.account.beget.tech [0] $ composer update
The "extra.asset-installer-paths" option is deprecated, use the "config.fxp-asset.installer-paths" option
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 26 updates, 0 removals
  - Updating swiftmailer/swiftmailer (v5.4.5 => v5.4.8) Loading from cache
  - Updating ezyang/htmlpurifier (v4.8.0 => v4.9.2) Loading from cache
  - Updating bower-asset/jquery.inputmask (3.3.4 => 3.3.6) Loading from cache
  - Updating yiisoft/yii2 (2.0.11 => 2.0.11.2) Loading from cache
  - Updating yiisoft/yii2-swiftmailer (2.0.6 => 2.0.7) Loading from cache
  - Updating yiisoft/yii2-debug (2.0.7 => 2.0.9) Loading from cache
  - Updating symfony/debug (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/console (v3.2.2 => v3.2.8) Loading from cache
  - Installing stecman/symfony-console-completion (0.7.0) Loading from cache
  - Updating sebastian/diff (1.4.1 => 1.4.2) Loading from cache
  - Updating symfony/dom-crawler (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/css-selector (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/browser-kit (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/yaml (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/event-dispatcher (v3.2.2 => v3.2.8) Loading from cache
  - Updating symfony/finder (v3.2.2 => v3.2.8) Loading from cache
  - Updating guzzlehttp/psr7 (1.3.1 => 1.4.2) Loading from cache
  - Updating sebastian/code-unit-reverse-lookup (1.0.0 => 1.0.1) Loading from cache
  - Updating phpunit/php-token-stream (1.4.9 => 1.4.11) Loading from cache
  - Updating phpunit/php-code-coverage (4.0.5 => 4.0.8) Loading from cache
  - Updating sebastian/object-enumerator (2.0.0 => 2.0.1) Loading from cache
  - Updating phpunit/php-timer (1.0.8 => 1.0.9) Loading from cache
  - Updating phpspec/prophecy (v1.6.2 => v1.7.0) Loading from cache
  - Updating myclabs/deep-copy (1.6.0 => 1.6.1) Loading from cache
  - Updating phpunit/phpunit (5.7.9 => 5.7.19) Loading from cache
  - Updating codeception/base (2.2.8 => 2.2.11) Loading from cache
  - Updating codeception/verify (0.3.2 => 0.3.3) Loading from cache
Writing lock file
Generating autoload files

Нам также потребуется создать ссылку с именем public_html, но в этом случае она уже будет указывать на каталог frontend/web.

account@server:~/yii-advanced.account.beget.tech [0] $ ln -s frontend/web public_html
account@server:~/yii-advanced.account.beget.tech [0] $

Выполним инициализацию приложения:

account@server:~/yii-advanced.account.beget.tech [0] $ composer install
The "extra.asset-installer-paths" option is deprecated, use the "config.fxp-asset.installer-paths" option
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update
Generating autoload files
> php init --env=Development --overwrite=n
Yii Application Initialization Tool v1.0


  Start initialization ...

   generate yii_test
   generate yii_test.bat
   generate backend/web/index.php
   generate backend/web/index-test.php
   generate backend/config/test-local.php
   generate backend/config/main-local.php
   generate backend/config/params-local.php
   generate console/config/main-local.php
   generate console/config/params-local.php
   generate frontend/web/index.php
   generate frontend/web/index-test.php
   generate frontend/config/test-local.php
   generate frontend/config/main-local.php
   generate frontend/config/params-local.php
   generate common/config/test-local.php
   generate common/config/main-local.php
   generate common/config/params-local.php
   generate yii
   generate cookie validation key in backend/config/main-local.php
   generate cookie validation key in frontend/config/main-local.php
      chmod 0777 backend/runtime
      chmod 0777 backend/web/assets
      chmod 0777 frontend/runtime
      chmod 0777 frontend/web/assets
      chmod 0755 yii
      chmod 0755 yii_test

  ... initialization completed.
account@server:~/yii-advanced.account.beget.tech [0] $

Теперь создадим в корневом каталоге публичной части ссылку на каталог административной части сайта:

account@server:~/yii-advanced.account.beget.tech [0] $ cd frontend/web/
account@server:~/yii-advanced.account.beget.tech/frontend/web [0] $ ln -s ../../backend/web backend

После этого необходимо внести правила в файл .htaccess, чтобы при переходе по поддомену backend.yii-advanced срабатывало перенаправление на созданную нами ссылку.

RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^(www.)?backend.domain.ru$ [NC]
RewriteCond %{REQUEST_URI} !^/backend
RewriteRule ^(.*)$ backend/$1 [L]

Ключи валидации cookies указываются в следующих файлах (пути от корневого каталога проекта):

  • environments/prod/backend/config/main-local.php
  • environments/prod/frontend/config/main-local.php
  • environments/dev/backend/config/main-local.php
  • environments/dev/frontend/config/main-local.php

Настройка подключения к базе данных производится в нескольких файлах (пути от корневого каталога проекта):

  • environments/dev/common/config/main-local.php
  • environments/prod/common/config/main-local.php
  • environments/dev/common/config/test-local.php

Настройка параметров аналогична basic-версии. На этом настройка завершена, приложение полностью готово к работе.

Установка через Composer

Кроме загрузки архивом имеется также возможность установки через Composer. Сначала установим Composer Asset Plugin.

account@server:~ [0] $ composer global require "fxp/composer-asset-plugin:^1.2.0"
Changed current directory to /home/v/account/.composer
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files
account@server:~ [0] $

Теперь установим Yii. Структура команды следующая:

composer create-project yiisoft/yii2-app-вариант_установки каталог_проекта 2.0.11

Начнём с Yii Basic (каталог проекта должен быть пуст!):

account@server:~ [0] $ composer create-project yiisoft/yii2-app-basic yii-basic 2.0.11
Installing yiisoft/yii2-app-basic (2.0.11)
- Installing yiisoft/yii2-app-basic (2.0.11) Downloading: 100%
Created project in yii-basic
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 59 installs, 0 updates, 0 removals
- Installing yiisoft/yii2-composer (2.0.5) Downloading: 100%
- Installing swiftmailer/swiftmailer (v5.4.8) Loading from cache
- Installing bower-asset/jquery (2.2.4) Downloading: 100%
- Installing bower-asset/yii2-pjax (v2.0.6) Downloading: 100%
- Installing bower-asset/punycode (v1.3.2) Downloading: 100%
- Installing cebe/markdown (1.1.1) Downloading: 100%
- Installing ezyang/htmlpurifier (v4.9.2) Downloading: 100%
- Installing bower-asset/jquery.inputmask (3.3.6) Downloading: 100%
- Installing yiisoft/yii2 (2.0.11.2) Downloading: 100%
- Installing yiisoft/yii2-swiftmailer (2.0.7) Downloading: 100%
- Installing bower-asset/bootstrap (v3.3.7) Downloading: 100%
- Installing yiisoft/yii2-bootstrap (2.0.6) Downloading: 100%
- Installing yiisoft/yii2-debug (2.0.9) Downloading: 100%
- Installing bower-asset/typeahead.js (v0.11.1) Downloading: 100%
- Installing phpspec/php-diff (v1.1.0) Downloading: 100%
- Installing yiisoft/yii2-gii (2.0.5) Downloading: 100%
- Installing fzaninotto/faker (v1.6.0) Loading from cache
- Installing yiisoft/yii2-faker (2.0.3) Downloading: 100%
- Installing psr/log (1.0.2) Loading from cache
- Installing symfony/debug (v3.2.8) Loading from cache
- Installing symfony/polyfill-mbstring (v1.3.0) Loading from cache
- Installing symfony/console (v3.2.8) Loading from cache
- Installing stecman/symfony-console-completion (0.7.0) Downloading: 100%
- Installing sebastian/diff (1.4.3) Downloading: 100%
- Installing sebastian/recursion-context (2.0.0) Loading from cache
- Installing sebastian/exporter (2.0.0) Loading from cache
- Installing sebastian/comparator (1.2.4) Loading from cache
- Installing behat/gherkin (v4.4.5) Downloading: 100%
- Installing symfony/dom-crawler (v3.2.8) Downloading: 100%
- Installing symfony/css-selector (v3.2.8) Loading from cache
- Installing symfony/browser-kit (v3.2.8) Downloading: 100%
- Installing symfony/yaml (v3.2.8) Loading from cache
- Installing symfony/event-dispatcher (v3.2.8) Loading from cache
- Installing symfony/finder (v3.2.8) Loading from cache
- Installing psr/http-message (1.0.1) Downloading: 100%
- Installing guzzlehttp/psr7 (1.4.2) Downloading: 100%
- Installing doctrine/instantiator (1.0.5) Loading from cache
- Installing phpunit/php-text-template (1.2.1) Loading from cache
- Installing phpunit/phpunit-mock-objects (3.4.3) Loading from cache
- Installing sebastian/version (2.0.1) Loading from cache
- Installing sebastian/code-unit-reverse-lookup (1.0.1) Loading from cache
- Installing phpunit/php-token-stream (1.4.11) Loading from cache
- Installing phpunit/php-file-iterator (1.4.2) Loading from cache
- Installing sebastian/environment (2.0.0) Loading from cache
- Installing phpunit/php-code-coverage (4.0.8) Loading from cache
- Installing sebastian/resource-operations (1.0.0) Loading from cache
- Installing sebastian/global-state (1.1.1) Loading from cache
- Installing phpunit/php-timer (1.0.9) Loading from cache
- Installing webmozart/assert (1.2.0) Loading from cache
- Installing phpdocumentor/reflection-common (1.0) Loading from cache
- Installing phpdocumentor/type-resolver (0.2.1) Loading from cache
- Installing phpdocumentor/reflection-docblock (3.1.1) Loading from cache
- Installing phpspec/prophecy (v1.7.0) Loading from cache
- Installing myclabs/deep-copy (1.6.1) Loading from cache
- Installing sebastian/object-enumerator (2.0.1) Loading from cache
- Installing phpunit/phpunit (5.7.20) Downloading: 100%
- Installing codeception/base (2.3.1) Downloading: 100%
- Installing codeception/verify (0.3.3) Downloading: 100%
- Installing codeception/specify (0.4.6) Downloading: 100%
symfony/console suggests installing symfony/filesystem ()
symfony/console suggests installing symfony/process ()
symfony/browser-kit suggests installing symfony/process ()
symfony/event-dispatcher suggests installing symfony/dependency-injection ()
symfony/event-dispatcher suggests installing symfony/http-kernel ()
phpunit/php-code-coverage suggests installing ext-xdebug (^2.5.1)
sebastian/global-state suggests installing ext-uopz (*)
phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)
phpunit/phpunit suggests installing ext-xdebug (*)
codeception/base suggests installing flow/jsonpath (For using JSONPath in REST module)
codeception/base suggests installing phpseclib/phpseclib (for SFTP option in FTP Module)
codeception/base suggests installing league/factory-muffin (For DataFactory module)
codeception/base suggests installing league/factory-muffin-faker (For Faker support in DataFactory module)
codeception/base suggests installing symfony/phpunit-bridge (For phpunit-bridge support)
Writing lock file
Generating autoload files
> yii\composer\Installer::postCreateProject
chmod('runtime', 0777)...done.
chmod('web/assets', 0777)...done.
chmod('yii', 0755)...done.
account@server:~ [0] $

Теперь перейдём в каталог с проектом и создадим ссылку public_html, указывающую на каталог public:

account@server:~ [0] $ cd yii-basic
account@server:~/yii-basic [0] $ ln -s web public_html
account@server:~/yii-basic [0] $

Настройка подключения к базе данных описана выше, в разделе Yii Basic.

Установим Yii Advanced:

account@server:~ [0] $ composer create-project yiisoft/yii2-app-advanced yii-advanced 2.0.11
Installing yiisoft/yii2-app-advanced (2.0.11)
  - Installing yiisoft/yii2-app-advanced (2.0.11) Downloading: 100%
Created project in yii-advanced
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 58 installs, 0 updates, 0 removals
  - Installing yiisoft/yii2-composer (2.0.5) Loading from cache
  - Installing swiftmailer/swiftmailer (v5.4.8) Loading from cache
  - Installing bower-asset/jquery (2.2.4) Loading from cache
  - Installing bower-asset/yii2-pjax (v2.0.6) Loading from cache
  - Installing bower-asset/punycode (v1.3.2) Loading from cache
  - Installing cebe/markdown (1.1.1) Loading from cache
  - Installing ezyang/htmlpurifier (v4.9.2) Loading from cache
  - Installing bower-asset/jquery.inputmask (3.3.6) Loading from cache
  - Installing yiisoft/yii2 (2.0.11.2) Loading from cache
  - Installing yiisoft/yii2-swiftmailer (2.0.7) Loading from cache
  - Installing bower-asset/bootstrap (v3.3.7) Loading from cache
  - Installing yiisoft/yii2-bootstrap (2.0.6) Loading from cache
  - Installing yiisoft/yii2-debug (2.0.9) Loading from cache
  - Installing bower-asset/typeahead.js (v0.11.1) Loading from cache
  - Installing phpspec/php-diff (v1.1.0) Loading from cache
  - Installing yiisoft/yii2-gii (2.0.5) Loading from cache
  - Installing fzaninotto/faker (v1.6.0) Loading from cache
  - Installing yiisoft/yii2-faker (2.0.3) Loading from cache
  - Installing psr/log (1.0.2) Loading from cache
  - Installing symfony/debug (v3.2.8) Loading from cache
  - Installing symfony/polyfill-mbstring (v1.3.0) Loading from cache
  - Installing symfony/console (v3.2.8) Loading from cache
  - Installing stecman/symfony-console-completion (0.7.0) Loading from cache
  - Installing sebastian/diff (1.4.3) Loading from cache
  - Installing sebastian/recursion-context (2.0.0) Loading from cache
  - Installing sebastian/exporter (2.0.0) Loading from cache
  - Installing sebastian/comparator (1.2.4) Loading from cache
  - Installing behat/gherkin (v4.4.5) Loading from cache
  - Installing symfony/dom-crawler (v3.2.8) Loading from cache
  - Installing symfony/css-selector (v3.2.8) Loading from cache
  - Installing symfony/browser-kit (v3.2.8) Loading from cache
  - Installing symfony/yaml (v3.2.8) Loading from cache
  - Installing symfony/event-dispatcher (v3.2.8) Loading from cache
  - Installing symfony/finder (v3.2.8) Loading from cache
  - Installing psr/http-message (1.0.1) Loading from cache
  - Installing guzzlehttp/psr7 (1.4.2) Loading from cache
  - Installing doctrine/instantiator (1.0.5) Loading from cache
  - Installing phpunit/php-text-template (1.2.1) Loading from cache
  - Installing phpunit/phpunit-mock-objects (3.4.3) Loading from cache
  - Installing sebastian/version (2.0.1) Loading from cache
  - Installing sebastian/code-unit-reverse-lookup (1.0.1) Loading from cache
  - Installing phpunit/php-token-stream (1.4.11) Loading from cache
  - Installing phpunit/php-file-iterator (1.4.2) Loading from cache
  - Installing sebastian/environment (2.0.0) Loading from cache
  - Installing phpunit/php-code-coverage (4.0.8) Loading from cache
  - Installing sebastian/resource-operations (1.0.0) Loading from cache
  - Installing sebastian/global-state (1.1.1) Loading from cache
  - Installing phpunit/php-timer (1.0.9) Loading from cache
  - Installing webmozart/assert (1.2.0) Loading from cache
  - Installing phpdocumentor/reflection-common (1.0) Loading from cache
  - Installing phpdocumentor/type-resolver (0.2.1) Loading from cache
  - Installing phpdocumentor/reflection-docblock (3.1.1) Loading from cache
  - Installing phpspec/prophecy (v1.7.0) Loading from cache
  - Installing myclabs/deep-copy (1.6.1) Loading from cache
  - Installing sebastian/object-enumerator (2.0.1) Loading from cache
  - Installing phpunit/phpunit (5.7.20) Loading from cache
  - Installing codeception/base (2.3.1) Loading from cache
  - Installing codeception/verify (0.3.3) Loading from cache
symfony/console suggests installing symfony/filesystem ()
symfony/console suggests installing symfony/process ()
symfony/browser-kit suggests installing symfony/process ()
symfony/event-dispatcher suggests installing symfony/dependency-injection ()
symfony/event-dispatcher suggests installing symfony/http-kernel ()
phpunit/php-code-coverage suggests installing ext-xdebug (^2.5.1)
sebastian/global-state suggests installing ext-uopz (*)
phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)
phpunit/phpunit suggests installing ext-xdebug (*)
codeception/base suggests installing codeception/specify (BDD-style code blocks)
codeception/base suggests installing flow/jsonpath (For using JSONPath in REST module)
codeception/base suggests installing phpseclib/phpseclib (for SFTP option in FTP Module)
codeception/base suggests installing league/factory-muffin (For DataFactory module)
codeception/base suggests installing league/factory-muffin-faker (For Faker support in DataFactory module)
codeception/base suggests installing symfony/phpunit-bridge (For phpunit-bridge support)
Writing lock file
Generating autoload files

Нам также потребуется создать ссылку с именем public_html, но в этом случае она уже будет указывать на каталог frontend/web.

account@server:~ [0] $ cd yii-advanced
account@server:~/yii-advanced [0] $ ln -s frontend/web public_html
account@server:~/yii-advanced [0] $

Теперь создадим в корневом каталоге публичной части ссылку на каталог административной части сайта:

account@server:~/yii-advanced [0] $ cd frontend/web/
account@server:~/yii-advanced/frontend/web [0] $ ln -s ../../backend/web backend

После этого необходимо внести правила в файл .htaccess, чтобы при переходе по поддомену backend.yii-advanced срабатывало перенаправление на созданную нами ссылку.

RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^(www.)?backend.domain.ru$ [NC]
RewriteCond %{REQUEST_URI} !^/backend
RewriteRule ^(.*)$ backend/$1 [L]

Настройка подключения к базе данных описана выше, в разделе Yii Advanced.

Установка Symfony

Установка этого фреймворка возможна двумя путями: собственным инсталлятором и через Composer. Рассмотрим оба варианта.

Установка с помощью Symfony Installer

Для начала мы создадим сайт и привяжем к нему домен. Для этого откойте раздел Сайты и создайте сайт с нужным именем по инструкции: Сайты. Если свободный домен, на котором требуется разместить сайт, уже есть, прикрепите его в этом же разделе. Если домена нет - откройте раздел Домены и поддомены и добавьте домен в панель управления либо создайте поддомен на уже существующем.

Подключимся к серверу по SSH, перейдём в каталог с нашим сайтом и удалим всё его содержимое.

account@server:~ [0] $ cd symfony/
account@server:~/symfony [0] $ rm -rf * .*
rm: refusing to remove '.' or '..' directory: skipping '.'
rm: refusing to remove '.' or '..' directory: skipping '..'
account@server:~/symfony [1] $

Загрузим Symfony Installer и разместим его в директории ~/.local/bin.

account@server:~/symfony [0] $ curl -LsS https://symfony.com/installer -o ~/.local/bin/symfony
account@server:~/symfony [0] $ chmod a+x ~/.local/bin/symfony
account@server:~/symfony [0] $

Теперь создадим проект:

account@server:~/symfony [0] $ symfony new .

 Downloading Symfony...

    5.5 MiB/5.5 MiB ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓  100%

 Preparing project...

 ✔  Symfony 3.2.8 was successfully installed. Now you can:

    * Change your current directory to /home/account/Projects/PHP/My_own/symf/.

    * Configure your application in app/config/parameters.yml file.

    * Run your application:
        1. Execute the php bin/console server:start command.
        2. Browse to the http://localhost:8000 URL.

    * Read the documentation at http://symfony.com/doc

Если требуется настроить подключение к базе данных - откройте файл app/config/parameters.yml и внесите в него данные для подключения. Для подключение к БД на нашем хостинге требуется изменить параметры database_port, database_name, database_user и database_password.

Обратите внимание!

Имя пользователя БД в нашей системе всегда соответствует имени БД. Порт для подключения к MySQL - 3306.

Теперь создадим символьную ссылку public_html, указывающую на корневой каталог проекта:

account@server:~/symfony [0] $ ln -s web public_html
account@server:~/symfony [0] $

На этом установка Symfony завершена.

Установка с помощью Composer

Установка с помощью Composer производится практически так же, но настройка параметров подключения к БД производится в процессе установки. Перед продолжением установки выполните команду

openssl rand -base64 12 | md5sum 

и скопируйте сгенерированный хэш. Его нужно будет использовать в качестве токена, который будет запрошен при настройке.

account@server:~/symfony [0] $ composer create-project symfony/framework-standard-edition .
Installing symfony/framework-standard-edition (v3.2.8)
  - Installing symfony/framework-standard-edition (v3.2.8) Downloading: 100%
Created project in .
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 34 installs, 0 updates, 0 removals
  - Installing doctrine/lexer (v1.0.1) Downloading: 100%
  - Installing doctrine/annotations (v1.2.7) Downloading: 100%
  - Installing twig/twig (v1.33.2) Downloading: 100%
  - Installing symfony/polyfill-util (v1.3.0) Downloading: 100%
  - Installing paragonie/random_compat (v2.0.10) Downloading: 100%
  - Installing symfony/polyfill-php70 (v1.3.0) Downloading: 100%
  - Installing symfony/polyfill-php56 (v1.3.0) Downloading: 100%
  - Installing symfony/polyfill-mbstring (v1.3.0) Downloading: 100%
  - Installing symfony/symfony (v3.2.8) Downloading: 100%
  - Installing symfony/polyfill-intl-icu (v1.3.0) Downloading: 100%
  - Installing psr/log (1.0.2) Downloading: 100%
  - Installing psr/cache (1.0.1) Downloading: 100%
  - Installing doctrine/inflector (v1.1.0) Downloading: 100%
  - Installing doctrine/collections (v1.3.0) Downloading: 100%
  - Installing doctrine/cache (v1.6.1) Downloading: 100%
  - Installing doctrine/common (v2.6.2) Downloading: 100%
  - Installing jdorn/sql-formatter (v1.2.17) Downloading: 100%
  - Installing doctrine/doctrine-cache-bundle (1.3.0) Downloading: 100%
  - Installing doctrine/dbal (v2.5.12) Downloading: 100%
  - Installing doctrine/doctrine-bundle (1.6.7) Downloading: 100%
  - Installing doctrine/instantiator (1.0.5) Downloading: 100%
  - Installing doctrine/orm (v2.5.6) Downloading: 100%
  - Installing incenteev/composer-parameter-handler (v2.1.2) Downloading: 100%
  - Installing composer/ca-bundle (1.0.7) Downloading: 100%
  - Installing sensiolabs/security-checker (v4.0.4) Downloading: 100%
  - Installing sensio/distribution-bundle (v5.0.19) Downloading: 100%
  - Installing sensio/framework-extra-bundle (v3.0.25) Downloading: 100%
  - Installing monolog/monolog (1.22.1) Downloading: 100%
  - Installing symfony/monolog-bundle (v3.1.0) Downloading: 100%
  - Installing symfony/polyfill-apcu (v1.3.0) Downloading: 100%
  - Installing swiftmailer/swiftmailer (v5.4.7) Downloading: 100%
  - Installing symfony/swiftmailer-bundle (v2.5.4) Downloading: 100%
  - Installing sensio/generator-bundle (v3.1.4) Downloading: 100%
  - Installing symfony/phpunit-bridge (v3.2.8) Downloading: 100%
paragonie/random_compat suggests installing ext-libsodium (Provides a modern crypto API that can be used to generate random bytes.)
doctrine/doctrine-cache-bundle suggests installing symfony/security-acl (For using this bundle to cache ACLs)
sensio/framework-extra-bundle suggests installing symfony/psr-http-message-bridge (To use the PSR-7 converters)
monolog/monolog suggests installing aws/aws-sdk-php (Allow sending log messages to AWS services like DynamoDB)
monolog/monolog suggests installing doctrine/couchdb (Allow sending log messages to a CouchDB server)
monolog/monolog suggests installing ext-amqp (Allow sending log messages to an AMQP server (1.0+ required))
monolog/monolog suggests installing ext-mongo (Allow sending log messages to a MongoDB server)
monolog/monolog suggests installing graylog2/gelf-php (Allow sending log messages to a GrayLog2 server)
monolog/monolog suggests installing mongodb/mongodb (Allow sending log messages to a MongoDB server via PHP Driver)
monolog/monolog suggests installing php-amqplib/php-amqplib (Allow sending log messages to an AMQP server using php-amqplib)
monolog/monolog suggests installing php-console/php-console (Allow sending log messages to Google Chrome)
monolog/monolog suggests installing rollbar/rollbar (Allow sending log messages to Rollbar)
monolog/monolog suggests installing ruflin/elastica (Allow sending log messages to an Elastic Search server)
monolog/monolog suggests installing sentry/sentry (Allow sending log messages to a Sentry server)
Generating autoload files
> Incenteev\ParameterHandler\ScriptHandler::buildParameters
Creating the "app/config/parameters.yml" file
Some parameters are missing. Please provide them.
database_host (127.0.0.1):
database_port (null): 3306
database_name (symfony): beget_demo
database_user (root): beget_demo
database_password (null): nopassword
mailer_transport (smtp):
mailer_host (127.0.0.1): smtp.beget.com
mailer_user (null): user@domain.com
mailer_password (null): nopassword
secret (ThisTokenIsNotSoSecretChangeIt): 15fc0b767c8fba6c602450e5106e48b4
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::buildBootstrap
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache

 // Clearing the cache for the dev environment with debug
 // true


 [OK] Cache for the "dev" environment (debug=true) was successfully cleared.


> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::installAssets

 Trying to install assets as relative symbolic links.

 -- -------- ----------------
     Bundle   Method / Error
 -- -------- ----------------


 [OK] All assets were successfully installed.


> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::installRequirementsFile
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::prepareDeploymentTarget
account@server:~/symfony [0] $

Теперь создадим символьную ссылку public_html, указывающую на корневой каталог проекта:

account@server:~/symfony [0] $ ln -s web public_html
account@server:~/symfony [0] $

На этом установка Symfony завершена.

Временна́я зона пользователя

У нас есть еще проблема с временно́й зоной — в базе данных мы храним дату и время в UTC. Будем показывать московское время для всех не аутентифицированных пользователй, а для аутентифицированных добавим возможность задать часовой пояс в личном кабинете. Мы добавим поле timezone в таблицу базы данных users и будем хранить в нем часовые пояса — Europe/Moscow, Asia/Irkutsk, Asia/Magadan.

> php artisan make:migration alter_users_table --table=users
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AlterUsersTable extends Migration {
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up() {
        Schema::table('users', function (Blueprint $table) {
            $table->string('timezone')->after('email')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('timezone');
        });
    }
}
> php artisan migrate
Migrating: 2021_02_26_074945_alter_users_table
Migrated:  2021_02_26_074945_alter_users_table (0.08 seconds)

Теперь в модели User, Post и Comment добавим аксессоры, которые будут изменять значения свойств моделей в момент доступа.

class User extends Authenticatable {
    /**
     * Преобразует дату и время регистрации пользователя из UTC в Europe/Moscow
     *
     * @param $value
     * @return \Carbon\Carbon|false
     */
    public function getCreatedAtAttribute($value) {
        $timezone = 'Europe/Moscow';
        if ($this->timezone) {
            $timezone = $this->timezone;
        }
        return Carbon::createFromFormat('Y-m-d H:i:s', $value)
            ->timezone($timezone)->format('d.m.Y H:i');
    }

    /**
     * Преобразует дату и время обновления пользователя из UTC в Europe/Moscow
     *
     * @param $value
     * @return \Carbon\Carbon|false
     */
    public function getUpdatedAtAttribute($value) {
        $timezone = 'Europe/Moscow';
        if ($this->timezone) {
            $timezone = $this->timezone;
        }
        return Carbon::createFromFormat('Y-m-d H:i:s', $value)
            ->timezone($timezone)->format('d.m.Y H:i');
    }
}
class Post extends Model {
    /**
     * Преобразует дату и время создания поста из UTC в Europe/Moscow
     *
     * @param $value
     * @return \Carbon\Carbon|false
     */
    public function getCreatedAtAttribute($value) {
        $timezone = 'Europe/Moscow';
        if (auth()->check() && auth()->user()->timezone) {
            $timezone = auth()->user()->timezone;
        }
        return Carbon::createFromFormat('Y-m-d H:i:s', $value)
            ->timezone($timezone)->format('d.m.Y H:i');
    }

    /**
     * Преобразует дату и время обновления поста из UTC в Europe/Moscow
     *
     * @param $value
     * @return \Carbon\Carbon|false
     */
    public function getUpdatedAtAttribute($value) {
        $timezone = 'Europe/Moscow';
        if (auth()->check() && auth()->user()->timezone) {
            $timezone = auth()->user()->timezone;
        }
        return Carbon::createFromFormat('Y-m-d H:i:s', $value)
            ->timezone($timezone)->format('d.m.Y H:i');
    }

    /**
     * Преобразует дату и время удаления поста из UTC в Europe/Moscow
     *
     * @param $value
     * @return \Carbon\Carbon|false
     */
    public function getDeletedAtAttribute($value) {
        $timezone = 'Europe/Moscow';
        if (auth()->check() && auth()->user()->timezone) {
            $timezone = auth()->user()->timezone;
        }
        return Carbon::createFromFormat('Y-m-d H:i:s', $value)
            ->timezone($timezone)->format('d.m.Y H:i');
    }
}
class Comment extends Model {
    /**
     * Преобразует дату и время создания комментария из UTC в Europe/Moscow
     *
     * @param $value
     * @return \Carbon\Carbon|false
     */
    public function getCreatedAtAttribute($value) {
        $timezone = 'Europe/Moscow';
        if (auth()->check() && auth()->user()->timezone) {
            $timezone = auth()->user()->timezone;
        }
        return Carbon::createFromFormat('Y-m-d H:i:s', $value)
            ->timezone($timezone)->format('d.m.Y H:i');
    }

    /**
     * Преобразует дату и время обновления комментария из UTC в Europe/Moscow
     *
     * @param $value
     * @return \Carbon\Carbon|false
     */
    public function getUpdatedAtAttribute($value) {
        $timezone = 'Europe/Moscow';
        if (auth()->check() && auth()->user()->timezone) {
            $timezone = auth()->user()->timezone;
        }
        return Carbon::createFromFormat('Y-m-d H:i:s', $value)
            ->timezone($timezone)->format('d.m.Y H:i');
    }

    /**
     * Преобразует дату и время удаления комментария из UTC в Europe/Moscow
     *
     * @param $value
     * @return \Carbon\Carbon|false
     */
    public function getDeletedAtAttribute($value) {
        $timezone = 'Europe/Moscow';
        if (auth()->check() && auth()->user()->timezone) {
            $timezone = auth()->user()->timezone;
        }
        return Carbon::createFromFormat('Y-m-d H:i:s', $value)
            ->timezone($timezone)->format('d.m.Y H:i');
    }
}

Теперь в личном кабинете добавим возможность для пользователя указать свой часовой пояс. В модель User добавим константу TIMEZONES с перечислением всех часовых поясов России. И создадим форму с выпадающим списком, где пользователь сможет выбрать подходящую — и будем хранить зону для каждого пользователя в базе данных.

class User extends Authenticatable {
    /* ... */
    const TIMEZONES = [
        'Europe/Kaliningrad' => 'Калининград, Россия (+02:00)',
        'Europe/Moscow' => 'Москва, Россия (+03:00)',
        'Europe/Astrakhan' => 'Астрахань, Россия (+04:00)',
        'Asia/Yekaterinburg' => 'Екатеринбург, Россия (+05:00)',
        'Asia/Omsk' => 'Омск, Россия (+06:00)',
        'Asia/Novosibirsk' => 'Новосибирск, Россия (+07:00)',
        'Asia/Irkutsk' => 'Иркутск, Россия (+08:00)',
        'Asia/Chita' => 'Чита, Россия (+09:00)',
        'Asia/Vladivostok' => 'Владивосток, Россия (+10:00)',
        'Asia/Magadan' => 'Магадан, Россия (+11:00)',
        'Asia/Kamchatka' => 'Петропавловск-Камчатский, Россия (+12:00)'
    ];
    /* ... */
}

Два новых маршрута:

/*
 * Личный кабинет пользователя
 */
Route::group([
    'as' => 'user.', // имя маршрута, например user.index
    'prefix' => 'user', // префикс маршрута, например user/index
    'namespace' => 'User', // пространство имен контроллеров
    'middleware' => ['auth'] // один или несколько посредников
], function () {
    /* ..... */
    /*
     * Редактирование персональных данных
     */
    Route::get('edit/{user}', 'DataController@edit')->name('edit');
    Route::put('update/{user}', 'DataController@update')->name('update');
});

Новый контроллер:

> php artisan make:controller User/DataController
namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Http\Request;

class DataController extends Controller {
    /**
     * Показывает форму для редактирования данных
     */
    public function edit(User $user) {
        $timezones = User::TIMEZONES;
        return view('user.data', compact('user', 'timezones'));
    }

    /**
     * Обновляет данные пользователя в базе данных
     */
    public function update(Request $request, User $user) {
        /*
         * Проверяем данные формы
         */
        $request->validate([
            'name' => 'string|required|max:255',
            'timezone' => 'nullable|string|max:255'
        ]);
        /*
         * Обновляем пользователя
         */
        $user->update($request->only(['name', 'timezone']));
        /*
         * Возвращаемся на главную
         */
        return redirect()
            ->route('user.index')
            ->with('success', 'Данные успешно обновлены');
    }
}

Шаблон user.data:

@extends('layout.user', ['title' => 'Личные данные'])

@section('content')
    

class

="mb-4">Личные данные
method
="post" action="{{ route('user.update', ['user' => $user->id]) }}"> @csrf @method('PUT')
class="form-group"> type="text" class="form-control" name="name" placeholder="Имя, Фамилия" required maxlength="255" value="{{ old('name') ?? $user->name }}">
class="form-group"> @php $timezone = old('timezone') ?? $user->timezone ?? null; @endphp ="timezone" class="form-control" title="Часовой пояс"> ="">Выберите @foreach($timezones as $key => $value) ="{{ $key }}" @if ($key === $timezone) selected @endif> {{ $value }} @endforeach
class="form-group"> ="submit" class="btn btn-success">Сохранить
@endsection

На главной странице личного кабинета разместим ссылку для перехода к редактированию личных данных:

@extends('layout.user', ['title' => 'Личный кабинет'])

@section('content')
    

Личный кабинет

Добрый день {{ auth()->user()->name }}! .......... href="{{ route('user.edit', ['user' => auth()->user()->id]) }}" class="btn btn-primary"> Личные данные @endsection