• Что такое static в ООП php?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Для этого вам надо понимать в чем разница между классами и объектами. Вот есть методы и свойства объектов а есть методы и свойства классов. Последние как раз статические свойства и методы. Отсюда и все особенности их работы и возможные варианты использования. Класс у нас в системе может быть только один, а экземпляров этого класса (объектов) много.

    Как правило статические методы используются в качестве порождающих. То есть вы вызываете статический метод класса а он тебе экземпляр этого класса.

    $foo = Singleton::instance();
    $bar = AbstractFactory::create('bar');
    $buz = Buz::fromArray([
        'many' => 'arguments', 'Buz' => 'has', 'private' => 'constructor'
    ]);


    В PHP статику еще любят применять как замену обычным функциям в силу того, что для классов автозагрузка у нас есть, а для функций нету. Не сказать что это сильно хорошо, я бы даже сказал что это плохо. Учитывая что сейчас есть composer а благодаря opcache оверхэда от подключения для каждого запроса файла особо и нет. В целом лучше стараться избегать использования статики или во всяком случае делать в статических методах хоть сколько нибудь сложные вещи. И лучше всегда ограничиваться только случаями для порождения объектов, тут статика выглядит логично.

    Если рассматривать с точки зрения пораждающиз статических методов, нам так же надо знать кого создавать. И тут появляются два ключевых слова - self и static. Причем self равносильно написанию имени класса в котором наш статический метод находится и просто позволяет уменьшить дублирование. static же намного интереснее, так как оно указывает непосдерственно на тот класс, из под которого был совершен вызов. Скажем если у вас есть наследование вы можете запихнуть порождающий метод в базовый класс, и тогда узнать кого создавать в принципе не проблема.

    class Foo {
        public static function createWithSelf() {
             // равносильно new Foo();
             return new self();
        }
        public static function createWithStatic() {
             // а тут мы пока не знаем кто такой этот static
             $foo = new static();
        }
    }
    
    class Bar extends Foo {}
    
    $foo = Bar::createWithSelf(); // тут будет экземпляр Foo
    $bar = Bar::createWithStatic(); // тут будет экземпляр Bar
    Ответ написан
    1 комментарий
  • Почему не работает форма генерации промокодов?

    dimonchik2013
    @dimonchik2013
    non progredi est regredi
    маловато кода
    Ответ написан
    Комментировать
  • Как создать простой сайт для заказа роллов?

    @Otrivin
    junior full-stack сисадмин
    Какой ВордПресс, коллеги, вы чего
    Есть опенкарт, спецом заточенный под эти ваши интернет-магазины (корзина, история заказов, личные кабинеты, доставка - всё из коробки). Его легко можно будет расширять и допиливать, если проект взлетит.

    От себя порекомендую сборку ocStore версии 2.3.0.2 (последняя на 2 ветке). Опционально - натянуть какой-нибудь сторонний шаблон, нашпиговать плагинами типа "расчета стоимости доставки" или прочим.
    Ответ написан
    Комментировать
  • PHPStorm + Битрикс?

    ssenj
    @ssenj
    HTML, CSS, PHP, WordPress, Bitrix
    Будет лучше, если ты сюда напишешь работающий код и не работающий.
    Думаю, экстрасенсы не посещают этот сайт )
    Ответ написан
    Комментировать
  • Что должно быть включено в стоимость почасовой работы?

    @choupa
    Архитектор (обычный, который строит)
    В фильме "Адвокат дьявола" Аль Пачино учил молодого адвоката Киану Ривза, что надо включать в счёт клиенту даже то время, когда он думает о его деле пока бреется утром.
    Ответ написан
    Комментировать
  • Можете объяснить зеленому что такое MVC?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Господи, в который раз-то уже?

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

    Самое главное, что надо понимать про эмвэцэ.
    Это не 50% твоего приложения. И даже не 10.
    Это тонюсенькая прослоечка, которая обслуживает только один канал общения твоего приложения с внешним миром - браузер. Есть и другие каналы, их много.

    Исходя из этого, получается что
    • Модель входит в эту тройку чисто номинально. Поскольку это и есть все твое приложение, только без интерфейса. И к модели обращаются не только веб контроллеры, но и консольные скрипты, REST контроллеры, сервер очередей и прочее. Отсюда становится понятно, что "модель - это запросы в БД в основном-то" - это дикая чушь.
    • Контроллер - это, как правильно нарисовано на картинке в соседнем ответе - это такая официантка, подай-принеси. Принять запрос от НТТР клиента, преобразовать в понятный для модели вид, запросить модель, получить ответ, вернуть что-нибудь клиенту. Также может заниматься чисто браузерными заморочками типа заголовков, авторизации и пр.
    • Вью - если модель вернула что-то для показа клиенту, то вью это превращает в понятный для браузера вид.
    • Роутер - не упоминается, но незримо присутствует. Преобразует НТТР адреса в вызовы контроллеров.

    Традиционно рекомендую доклад Дмитиря Елисеева с ПХП Раша 2019, там все раскладывается по полочкам.

    5dc1688cad3db637954994.png
    Ответ написан
    7 комментариев
  • Сайт выдает ошибку(500). Как правильно написать код?

    DevMan
    @DevMan
    правильно – включить вывод ошибок и/или читать логи.
    Ответ написан
    Комментировать
  • Для чего в классах после названий функций пишут :void, :bool, :string и подобные указания?

    yarkov
    @yarkov
    Помог ответ? Отметь решением.
    Тип данных, которые вернет функция
    Ответ написан
    Комментировать
  • Как выбрать одну строку с более поздней датой?

    irishmann
    @irishmann
    Научись пользоваться дебаггером
    SELECT
    /* твой код*/
    ORDER BY create_date DESC 
    LIMIT 1
    Ответ написан
    Комментировать
  • Возвращает NULL в $_POST запросе,когда есть капча,и выбрано 2 файла на загрузку,почему?

    Ninazu
    @Ninazu
    Рекомендую начать с работающего примера, и потом усложнять его капчами и прочей логикой

    <?php
    if ($_POST) {
    	die(json_encode([$_POST, $_FILES]));
    }
    ?>
    
    <form enctype="multipart/form-data" method="POST">
    	<input type="text" name="name" required></br>
    	<input type="file" name="file[]" multiple style="margin-bottom: 5px;">
    	<input type="submit" name="gsubmit" value="Отправить"></br>
    </form>
    <script>
    	document.querySelector("form").addEventListener("submit", function(e) {
    		let form = e.target;
    		e.preventDefault();
    		e.stopImmediatePropagation();
    		let xhr = new XMLHttpRequest();
    
    		xhr.open(form.method, form.action);
    		xhr.onreadystatechange = function(result) {
    			if (xhr.readyState === 4 && xhr.status === 200) {
    				let responseData = JSON.parse(xhr.responseText);
    				console.log(responseData);
    			}
    		};
    
    		xhr.send(new FormData(form));
    	}, true);
    </script>
    Ответ написан
    2 комментария
  • Как связать рецепт и продукты?

    daemonhk
    @daemonhk
    ПсиХоПат
    Почитайте про связь таблиц, в частности ManyToMany. Если конкретнее - создается еще одна таблица, скажем, RelationsRecipeProduct, которая будет содержать всего 2 поля - idRecipe и idProduct. Затем с помощью джойнов подхватываются данные с 3 таблиц и вуаля!
    Ответ написан
    5 комментариев
  • Как сверстать горизонтальный сайт?

    @Giperoglif
    ужасно тормознутая и бесящая фигня, конечно.
    Ответ написан
    Комментировать
  • Как сделать динамические мета-теги?

    @choupa
    Архитектор (обычный, который строит)
    if (strpos( $_SERVER['HTTP_HOST'], 'krd.site.ru') !== false)
      echo "<meta name='title' content='Краснодар'>";
    else
      echo "<meta name='title' content='Петербург'>";


    Но я вам писал в другом вашем вопросе, что так делать (через if) не надо, особенно если у вас городов больше двух. Учитесь сразу программировать хорошо.

    $host = $_SERVER[ 'HTTP_HOST' ];
    $city = array(
      "krd.site.ru" => "Краснодара",
      "spb.site.ru" => "Санкт-Петербурга",
      "msk.site.ru" => "Москвы",
      "urp.site.ru" => "Урюпинска",
    );
    
    echo "
      <header>
        <meta name='title' content='Лучшие индивидуалки из'".$city[ $host ].">
      </header>";
    Ответ написан
    2 комментария
  • Как переписать функцию, чтобы была multi загрузка изображений?

    @Mike_Polit Автор вопроса
    Автор ответа:
    Антон Р. Антон Р.

    function upload_image()
    {
      if(isset($_FILES['user_image']))
      {
        // Count total files
        $countfiles = count($_FILES['user_image']['name']);
    
        for($i=0;$i<$countfiles;$i++){
          $extension = explode('.', $_FILES['user_image']['name'][$i]);
          $new_name = rand() . '.' . $extension[1];
          $destination = '../portfolio/upload/' . $new_name;
          $thumbDestination = '../portfolio/upload/thumb/' . $new_name;
          
          move_uploaded_file($_FILES['user_image']['tmp_name'][$i], $destination);
          
          resize($destination, $thumbDestination, 300);
        }
        return $new_name;
      }
    }
    
    
    function resize($source, $destination, $width){
      
        $image = new Imagick($source);
        
        // Получаем соотношение сторон для пропорционального ресайза.
        $d = $image->getImageGeometry();
        $w = $d['width'];
        $h = $d['height'];
        $aspectratio = $h / $w;
        
        // Ресайзим и сохраняем.
        $image->resizeImage($width, $width*$aspectratio, Imagick::FILTER_LANCZOS, 1);
        $image->writeImage($destination);
        $image->destroy();
        
    }
    Ответ написан
    Комментировать
  • Как эффективно выучить технологии для backend'a?

    @frozen_coder
    Java-developer
    Я за изучение через практику. Поэтому вот вам несколько ссылок с идеями для проектов.

    1. https://eax.me/programming-language-learning/ - вот это просто огненная статья с примерами проектов для любого ЯП. Выбирайте что-нибудь по душе и пилите, в процессе изучите всё, что надо.
    2. https://proglib.io/p/project-list/ - тут дофига всякого
    3. https://habr.com/ru/post/345092/ - ну и тут чуток
    Ответ написан
    Комментировать
  • Изменение html в зависимости от radio?

    @2bllk
    Почему бы Вам этим на сервере не заниматься?
    <form target="_blank" method="POST" action="../index.php">
        <input type="radio" name="paymentType" value="PC">
        <input type="radio" name="paymentType" value="AC">
        <input type="radio" name="paymentType" value="MC">
    </form>

    index.php
    if (isset($_POST['paymentType'])){
        if ($_POST['paymentType'] === 'PC')
            header('Location: ../page/sds/3')
            // ...
    }


    это все понятно но мне нужно изменить форму до её отправки!!!
    Тоесть в зависимости от выбранного radio форма будет уходить на другой сайт


    Второй вариант:
    <html>
    <head>
    	<title>Document</title>
    </head>
    <body>
    	<form target="_blank" method="POST" action="../index.php" name="form">
    	    <input type="radio" name="paymentType" value="PC">
    	    <input type="radio" name="paymentType" value="AC">
    	    <input type="radio" name="paymentType" value="MC">
    	</form>
    
    	<script type="text/javascript">
    		document.form.onchange = () => {
    			switch ((new FormData(document.form)).get('paymentType')){
    				case 'PC':
    					document.form.action = '/page/sds/3';
    				break;
    				case 'AC':
    					document.form.action = '/page/sds/4';
    				break;
    				case 'MC':
    					document.form.action = '/page/sds/5';
    				break;
    			}
    		}
    	</script>
    </body>
    </html>
    Ответ написан
    9 комментариев
  • Yii2 HTTP Basic аутентификация, как сделать?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Надо не на форум ползать. А в документацию.

    Вот вам готовый пример.

    Вам Дмитрий когда-то давал видео Елисеева Дмитрия по API. Вы сначала изучите, посмотрите, потом вопросов не останется. Если лень смотреть долго, то есть Кратче у Максима
    Ответ написан
    7 комментариев
  • Количество выполненных перевозок на сайте. Как будет логичнее генерировать?

    mahmudchon
    @mahmudchon
    Компания же реальная? Узнать у них средние значения заказов в каких-то временных рамках. Мб временные рамки работы. Чтобы счетчик не крутить в часы за пределами рабочего графика. В формулу можно занести также прогрессивный рост, основываясь на данных динамики роста и развития компании или наоборот. Если ежедневно будет выполняться по 100 заказов - не обязательно распределять их равномерно на 24 часа. Например, в зависимости от времени суток может быть увеличенный спрос и тп. Как то это обыграть. Все еще скучно?
    А обновлять это дело по cron, как уже отметили, с частотой, выбранной вами.
    Ответ написан
    1 комментарий
  • Как исправить эту ошибку?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Проблема в области видимости - переменная $mysqli недоступна в функции fakePayout(). Решается одним из способов:

    1. Явной передачей переменной внутрь функции function fakePayout($mysqli, ...) {
    2. Корректным доступом к данной переменной, поместив ее в свойство класса, содержащего функцию fakePayout():
    class SomeClass 
    {
        private $mysqli;
    
        public function __construct(DataBase $mysqli)
        {
            $this->mysqli = $mysqli;
        }
    
        public function fakePayout($user, $amount, $time)
        {
            // Теперь можно использовать
            $this->mysqli->query()
        }
    }

    3. Вариации #2 с dependency injection контейнерами, фасадами и прочее.

    ЗЫ: Можно еще внутри самой функции создавать соединение, или хранить его в глобальной переменной / синглтоне - но это уже совсем дичь.
    Ответ написан
    24 комментария
  • В чем разница между 'фабричным методом' и 'простой фабрикой'?

    @rundle
    Привет.

    Пример с сайта неудачный. Он не показывает выразительность фабричного метода в отличие от фабрики. Я изменил пример ниже.

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

    Один из принципов проектирования - выделите то, что изменяется и отделите от того, что остается постоянным. Все паттерны в какой-то мере обеспечивают возможность изменения некоторой части системы независимо от других частей.

    Например, мы открыли в Москве и Питере магазин по продаже телефонов и в классе BeelineStore есть общие методы для всех телефонов (код на java схематичный). Samsung стал поддерживать 5G интернет, поэтому сделаем тариф для этих телефонов дороже.

    spoiler
    abstract class IMobile {
    	void prepare() {
    		System.out.println("Подготовим документы по продаже от ООО Билайн");
    	}
    	void setInternetTariff() {
    		System.out.println("Установим стандартный тариф Билайна для интернета");
    	}
    	void box() {
    		System.out.println("Упакуем в желтый пакетик");
    	}
    }
    
    class BeelineSamsung extends IMobile {
    	void setInternetTariff() {
    		System.out.println("Установим отдельный тариф для 5G интернета");
    	}
    }
    
    class BeelineIPhone extends IMobile {}
    
    class BeelineStore {
    	public IMobile orderPhone(String type) {
    		IMobile phone = null;
    
    		if (type.equals("samsung")) {
    			phone = new BeelineSamsung();
    		} else if (type.equals("iphone")) {
    			phone = new BeelineIPhone();
    		}
    
    		phone.prepare();
    		phone.setInternetTariff(); 
    		phone.box();
    
    		return phone;
    	}
    }
    
    // использование
    // var mobileStore = new BeelineStore();
    // mobileStore.orderPhone("samsung"); <- клиентский код

    Однако при изменении, удалении или добавлении новых видов телефонов мы бы открывали наш класс BeelineStore и расширяли новыми конкретными типами. А если мы добавим модели телефонов, то дерево условий станет сложнее. Если одни аспекты системы изменяются, а другие остаются неизменными — пора заняться инкапсуляцией.

    spoiler
    class MobileFactory {
    	public IMobile getMobile(String type) {
    		if (type.equals("samsung")) {
    			return new BeelineSamsung();
    		} else if (type.equals("iphone")) {
    			return new BeelineIPhone();
    		}
    
    		return null;
    	}
    }
    
    class BeelineStore {
    	MobileFactory factory;
    
    	public BeelineStore(MobileFactory factory) {
    		this.factory = factory;
    	}
    
    	public IMobile orderPhone(String type) {
    		IMobile phone;
    
    		phone = factory.getMobile(type);
    
    		phone.prepare(); 
    		phone.setInternetTariff();
    		phone.box();
    
    		return phone;
    	}
    }
    // использование 
    // var mobileFactory = new MobileFactory();
    // mobileStore = new BeelineStore(mobileFactory);
    // mobileStore.orderPhone("samsung"); <- замечу, клиентский код не изменился

    Окей - мы вынесли процесс создания телефонов - это и есть фабрика. И тут мы расширяемся, дела в нашей компании пошли хорошо и мы открываем филиалы на Урале. Тарифы на Урале будут дешевле, как стандартные, так и для 5G интернета. А также в Москве и Питере запускается программа по обмену старых телефонов на новые. И тут нам помогает фабричный метод.

    spoiler
    abstract class BeelineStore { // класс становится абстрактным
    	protected abstract IMobile getMobile(String type); // возвращается метод getMobile
    
    	public IMobile orderPhone(String type) {
    		IMobile phone = getMobile(type);
    
    		phone.prepare(); 
    		phone.setInternetTariff();
    		phone.box(); 
    
    		return phone;
    	}
    }
    
    class CenterBeelineSamsung extends IMobile {
    	void setInternetTariff() {
    		System.out.println("Отдельный тариф для 5G интернета в центре России");
    	}
    }
    
    class CenterBeelineIPhone extends IMobile {}
    
    class СenterBeelineStore extends BeelineStore {
    	public IMobile getMobile(String type) {
    		if (type.equals("samsung")) {
    			return new CenterBeelineSamsung();
    		} else if (type.equals("iphone")) {
    			return new CenterBeelineIPhone();
    		}
    
    		return null;
    	}
    	
    	public void tradeIn(String phone) {
    		System.out.println("Вы обменяли старый телефон на новый с доплатой");
    	}
    }
    
    class UralBeelineSamsung extends IMobile {
    	void setInternetTariff() {
    		System.out.println("Отдельный тариф для 5G интернета на Урале");
    	}
    }
    
    class UralBeelineIPhone extends IMobile {
    	void setInternetTariff() {
    		System.out.println("Отдельный тариф для стандартного интернета на Урале");
    	}
    }
    
    class UralBeelineStore extends BeelineStore {
    	public IMobile getMobile(String type) {
    		if (type.equals("samsung")) {
    			return new UralBeelineSamsung();
    		} else if (type.equals("iphone")) {
    			return new UralBeelineIPhone();
    		}
    
    		return null;
    	}
    }
    // использование
    // var centerBeelineStore = new СenterBeelineStore();
    // centerBeelineStore.orderPhone("samsung");
    // var uralBeelineStore = new UralBeelineStore();
    // uralBeelineStore.orderPhone("samsung");

    Мы смогли сохранить единые для всех магазинов стандарты оформления заказа, а также добавили региональные отличия.
    То есть фабричный метод гораздо гибче. Простая Фабрика обладает узкой специализацией, а фабричный метод ведет к созданию инфраструктуры, в которой реализация выбирается субклассами.
    Простая Фабрика инкапсулирует создание объектов, но она лишена гибкости фабричного метода в изменении создаваемых продуктов.
    Ответ написан
    Комментировать