За последние 24 часа нас посетили 26284 программиста и 1814 роботов. Сейчас ищут 1027 программистов ...

Как делаете Вы?

Тема в разделе "PHP для новичков", создана пользователем Вероломство, 25 мар 2022.

  1. Вероломство

    Вероломство Активный пользователь

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24
    Вариант 1

    PHP:
    1. class CourseAction extends Base
    2. {
    3.     public function __invoke(User $user)
    4.     {
    5.         $course = Course::findOne($user->course_id);
    6.  
    7.         $this->getView()->setTitle('Курс молодого бойца')->render("Course.$course->id", compact('user', 'course'));
    8.     }
    9. }
    Вывод

    PHP:
    1. <?php
    2.  
    3. use app\models\Course;
    4.  
    5. /**
    6. * @var Course $course
    7. */
    8. ?>
    9. <main class="container px-1">
    10.     <img src="/img/course/<?= $course->id ?>.jpg" class="w-100" alt="course-<?= $course->id ?>">
    11.     <?= $course->description ?>
    12. </main>
    Вариант 2

    PHP:
    1. class CourseAction extends Base
    2. {
    3.     public function __invoke(User $user)
    4.     {
    5.         $this->getView()->setTitle('Курс молодого бойца')->render("Course.$user->course_id", compact('user'));
    6.     }
    7. }
    Вывод

    PHP:
    1. <?php
    2.  
    3. use app\models\Course;
    4. use app\models\User;
    5.  
    6. /**
    7. * @var User $user
    8. */
    9. ?>
    10. <main class="container px-1">
    11.     <img src="/img/course/<?= $user->course_id ?>.jpg" class="w-100" alt="course-<?= $user->course_id ?>">
    12.     <?= Course::findOne($user->course_id)->description ?>
    13. </main>
    Какой вариант предпочтительнее?
     
  2. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.817
    Симпатии:
    1.333
    Адрес:
    Лень
    в шаблонах не должен находится PHP

    index
    PHP:
    1. <h2>Index</h2>
    2.  
    3. {<{@lastUsername}>}
    4.  
    5. <p><a href="/registration">Регистрация</a></p>
    6. <p><a href="/login">Авторизация</a></p>
    7. <p><a href="/logout">Выход</a></p>
    8. <p><a href="/panel">Панель управления</a></p>

    Controller
    PHP:
    1. <?php
    2.  
    3. declare ( strict_types = 1 );
    4.  
    5. namespace Nouvu\Resources\Controllers;
    6.  
    7. use Nouvu\Framework\Http\Controllers\AbstractController;
    8. use Nouvu\Framework\View\Repository\CommitRepository;
    9. use Nouvu\Resources\System\RestApi;
    10.  
    11. use function Nouvu\Resources\System\Helpers\{ isAjax, routerPathByName };
    12.  
    13. final class MainController extends AbstractController
    14. {
    15.     public function index(): CommitRepository
    16.     {
    17.         $this -> setThreadTitles( 'Главная', 'Не главная' );
    18.      
    19.         return $this -> render( 'index' );
    20.     }
    21.  
    22.     public function err404( string | int $_route ): CommitRepository
    23.     {
    24.         $this -> setThreadTitles( 'Страница не найдена' );
    25.      
    26.         if ( isAjax() )
    27.         {
    28.             return $this -> customJson( RestApi :: notFound() -> redirect( routerPathByName( $_route ) ) );
    29.         }
    30.      
    31.         return $this -> render( 'error.404', 'error-template' );
    32.     }
    33.  
    34.     public function err500( string | int $_route ): CommitRepository
    35.     {
    36.         $this -> setThreadTitles( 'Ошибка сервера' );
    37.      
    38.         if ( isAjax() )
    39.         {
    40.             return $this -> customJson( RestApi :: serverError() -> redirect( routerPathByName( $_route ) ) );
    41.         }
    42.      
    43.         return $this -> render( 'error.500', 'error-template' );
    44.     }
    45. }

    Helpers
    PHP:
    1. <?php
    2.  
    3. declare ( strict_types = 1 );
    4.  
    5. namespace Nouvu\Resources\System\Helpers;
    6.  
    7. use Nouvu\Framework\Foundation\Application;
    8. use Nouvu\Framework\Component\{
    9.     Config\Repository,
    10.     Database\DatabaseManager,
    11.     Validator\Exception\ViolationsException
    12. };
    13. use Nouvu\Resources\Entity\Database\{ Permissions };
    14. use Symfony\Component\HttpFoundation\{ Request, Response, Session\SessionInterface };
    15. use Symfony\Component\Security\Core\{ Security, User\UserInterface, Exception\AuthenticationException };
    16.  
    17. function app( Application $data = null ): Application
    18. {
    19.     static $app;
    20.  
    21.     return $app ??= $data;
    22. }
    23.  
    24. function container( string $offset = null ): mixed
    25. {
    26.     if ( is_null ( $offset ) )
    27.     {
    28.         return app() -> container;
    29.     }
    30.  
    31.     return app() -> container -> get( $offset );
    32. }
    33.  
    34.  
    35. function lastUsername(): string
    36. {
    37.     return app() -> session -> get( Security :: LAST_USERNAME, '' );
    38. }
    39.  
    40. .....
     
    Вероломство нравится это.
  3. Вероломство

    Вероломство Активный пользователь

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24
    @MouseZver понял Вас: Вариант 1 :)

    функции твои понравились интересный подход, я ещё видел что-то вроде

    PHP:
    1. $app = new Application();
    2.  
    3. $_SERVER['app'] = &$app;
    4.  
    5. if (!function_exists('app'))
    6. {
    7.     function app()
    8.     {
    9.         return $_SERVER['app'];
    10.     }
    11. }
    прокомментируешь может, если не лень
     
    #3 Вероломство, 26 мар 2022
    Последнее редактирование: 26 мар 2022
  4. twim32

    twim32 Активный пользователь

    С нами с:
    29 мар 2017
    Сообщения:
    275
    Симпатии:
    58
    Полнейшая дичь. Сервер - это сервер, пихать туда свои данные не надо.
    Многие делают App паттерном синглтон и это один из редких случаев когда этот паттерн уместен.
     
    MouseZver нравится это.
  5. Вероломство

    Вероломство Активный пользователь

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24
    ну тоже, как вариант, но проще в самом App сделать статичное свойство, например, public static $here, присвоить ему в конструкторе this и обращаться, где нужно App::$here
     
  6. twim32

    twim32 Активный пользователь

    С нами с:
    29 мар 2017
    Сообщения:
    275
    Симпатии:
    58
    Это и называется синглтоном. :D
     
  7. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.817
    Симпатии:
    1.333
    Адрес:
    Лень
    Мой класс App покрывает удобство использование DI-контейнера и не более, а хелпер делает его "глобальным" для использования

    PHP:
    1. <?php
    2.  
    3. $app -> session -> get( 'KEY_NAME', 'DEFAULT_VALUE' );
    Вместо:
    PHP:
    1. <?php
    2.  
    3. $container -> get( 'session' ) -> get( 'KEY_NAME', 'DEFAULT_VALUE' );
    $_SERVER $_FILES $_COOKIE $_POST $_GET - относится к Request данным, а не хранилище для впихивания чего-то из логики скрипта.
    --- Добавлено ---
    PHP:
    1. <?php
    2.  
    3. declare ( strict_types = 1 );
    4.  
    5. namespace Nouvu\Framework\Foundation;
    6.  
    7. use Psr\Container\ContainerInterface;
    8.  
    9. class Application
    10. {
    11.     //use ApplicationTrait;
    12.  
    13.     public function __construct ( private ContainerInterface $ContainerInterface, array $tools )
    14.     {
    15.         foreach ( $tools + [ \App :: class => ( fn( ContainerInterface $ContainerInterface ): self => $this ) ] AS $name => $packaging )
    16.         {
    17.             //$this -> setContainer( $name, $packaging );
    18.             $this -> ContainerInterface -> set( $name, $packaging );
    19.         }
    20.     }
    21.  
    22.     /*protected function setContainer( string $name, callable $packaging ): void
    23.     {
    24.         $this -> ContainerInterface -> set( $name, $packaging );
    25.     }*/
    26.  
    27.     /*protected function getContainer( string $name ): mixed
    28.     {
    29.         return $this -> ContainerInterface -> get( str_replace ( '.', '\\', $name ) );
    30.     }*/
    31.  
    32.     public function __set( string $name, callable $value ): void
    33.     {
    34.         //$this -> setContainer( $name, $value );
    35.         $this -> ContainerInterface -> set( $name, $packaging );
    36.     }
    37.  
    38.     public function __get( string $name ): mixed
    39.     {
    40.         //return $this -> getContainer( $name );
    41.         return $this -> ContainerInterface -> get( str_replace ( '.', '\\', $name ) );
    42.     }
    43.  
    44.     public function init(): void
    45.     {
    46.         foreach ( $this -> repository ?-> get( 'app.ini_set' ) ?? [] AS $option => $value )
    47.         {
    48.             ini_set ( $option, ( string ) $value( $this ) );
    49.         }
    50.     }
    51. }
    --- Добавлено ---
    даже сейчас увидел недостаток в App
     
    Вероломство и twim32 нравится это.
  8. Вероломство

    Вероломство Активный пользователь

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24
    в каком-то месте неожиданно App::$here = 'Синглтон App накрылся тазиком'; :D

    App::$here->а_гдей-то_мой_метод :)
     
    #8 Вероломство, 26 мар 2022
    Последнее редактирование: 26 мар 2022
  9. twim32

    twim32 Активный пользователь

    С нами с:
    29 мар 2017
    Сообщения:
    275
    Симпатии:
    58
    Что-то по-джуновски...
    Сделать приватным свойство, с доступом через статический метод.
    PHP:
    1. <?php
    2.  
    3. class App
    4. {
    5.   private static $instance;
    6.  
    7.   /**
    8.   * Защищаем от прямого вызова
    9.   */
    10.   protected function __construct() {}
    11.  
    12.   /**
    13.   * Доступ к экземпляру
    14.   */
    15.   public static function getInstance(): App
    16.   {
    17.   if(!self::$instance) {
    18.   self::$instance = new App;
    19.   }
    20.   return self::$instance;
    21.   }
    22. }
    23.  
    24. // Используем:
    25. $app = new App; // ERROR
    26. $app = App::getInstance(); // App
    27. }
    Еще можно добавить защиту от сериализации, но мне лень...
     
    Вероломство и MouseZver нравится это.
  10. Вероломство

    Вероломство Активный пользователь

    С нами с:
    19 июн 2017
    Сообщения:
    626
    Симпатии:
    24
    @twim32

    PHP:
    1. public static function getInstance(): static
    2. {
    3.     return self::$instance ??= new self();
    4. }
     
    twim32 нравится это.
  11. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.817
    Симпатии:
    1.333
    Адрес:
    Лень
    Есть одно НО
    Сколько надо ума чтобы главный, стартовый класс инициализировать множество раз. Тот же composer, есть любители со времен Wordpress пихать инклуд по всему проекту. Окей, для таких существует *_once

    Поэтому за пределами "веб" шаринга, держим папку проекта и в ней существует один как bootstrap главный файл, откуда начинается подключение всего остального.

    /Хостинг/Приложение/service.php
    /Хостинг/www/index.php


    service.php
    PHP:
    1. <?php
    2.  
    3. use Nouvu\Framework\Foundation\Application;
    4.  
    5. $composer = require 'vendor/autoload.php';
    6.  
    7. return static function ( string $name ) use ( $composer ): Application
    8. {
    9.     $composer -> addPsr4( \Nouvu\Resources :: class . '\\', __DIR__ . "/{$name}/Resources" );
    10.  
    11.     return new Application( new \Nouvu\Container\Container, include __DIR__ . "/{$name}/tools.php" );
    12. };

    index.php
    PHP:
    1. <?php
    2.  
    3. $service = require dirname ( __DIR__, 2 ) . '/Nouvu/service.php';
    4.  
    5. $app = $service( 'userdata' );
    6.  
    7. $app -> repository -> set( 'app.system.directory.site', __DIR__ );
    8.  
    9. $app -> kernel -> send();
    Начиная с Kernel, включается возможность использовать helpers функции. Вся задумка полностью в Lazy работе. Т.е. подключается то, что требуется, не трогая остальное. в Конфиге так же есть возможность прописать "что нужно в первую очередь запустить" как "обязательное"
    --- Добавлено ---
    app.system.directory.site - если кто-то не допонял, это многомерный массив ['app']['system']['directory']['site']
    Программисту удобнее в ООП, без вырви глаза.
     
    #11 MouseZver, 26 мар 2022
    Последнее редактирование: 26 мар 2022