• Можно ли сделать бота для нажатия на кнопки?

    Ninazu
    @Ninazu
    1. Там за каждое нажатие кнопки без капчи, нужно заплатить 1 reward point
    2. Капчу можно решить с помощью сервисов вроде rucaptcha

    package main
    
    import (
    	"context"
    	"fmt"
    	"github.com/chromedp/cdproto/network"
    	"github.com/chromedp/chromedp"
    	"log"
    	"time"
    )
    
    var (
    	dir = "ПАПКА_КУДА_СОХРАНЯЮТСЯ_COOKIE"
    	domain = "https://freebitco.in/"
    	wait   = 3
    	login = true //Выставить в false, после авторизации
    )
    
    func main() {
    	opts := append(chromedp.DefaultExecAllocatorOptions[:],
    		chromedp.DisableGPU,
    		chromedp.NoDefaultBrowserCheck,
    		chromedp.Flag("enable-automation", true),
    		chromedp.Flag("use-mock-keychain", true),
    		chromedp.Flag("headless", !login),
    		chromedp.Flag("no-first-run", true),
    		chromedp.Flag("no-sandbox", true),
    		chromedp.Flag("ignore-certificate-errors", true),
    		chromedp.Flag("user-data-dir", dir),
    	)
    
    	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
    	defer cancel()
    
    	taskCtx, cancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
    	defer cancel()
    
    	if err := chromedp.Run(taskCtx); err != nil {
    		panic(err)
    	}
    
    	var reward string
    
    	err := chromedp.Run(taskCtx,
    		network.Enable(),
    		chromedp.Navigate(domain),
    		chromedp.Action(chromedp.ActionFunc(func(ctx context.Context) error {
    			time.Sleep(time.Duration(wait) * time.Second)
    
    			return nil
    		})),
    		chromedp.WaitVisible(`#play_without_captchas_button`),
    		chromedp.Click(`#play_without_captchas_button`, chromedp.NodeVisible),
    		chromedp.Action(chromedp.ActionFunc(func(ctx context.Context) error {
    			time.Sleep(time.Duration(wait) * time.Second)
    
    			return nil
    		})),
    		chromedp.Click(`#free_play_form_button`, chromedp.NodeVisible),
    		chromedp.Action(chromedp.ActionFunc(func(ctx context.Context) error {
    			time.Sleep(time.Duration(wait) * time.Second)
    
    			return nil
    		})),
    		chromedp.TextContent(`#winnings`, &reward),
    	)
    
    	if err != nil {
    		panic(err)
    	}
    
    	fmt.Println(reward)
    }
    Ответ написан
  • Как распарсить массив c частичным совпадением ключей?

    Ninazu
    @Ninazu
    Если неизвестны возможные ключи и количество индексов, а вывод нужно нормализировать

    <?php
    $array = [
    	'text_1' => ['I am so clever that sometimes I do not underst'],
    	//'text_2' => ['It is better to be hated for what you are than f.'],
    	'text_3' => ['Whenever you find yourself on the .'],
    	'text_4' => ['Whenever you find yourself on the side of the majority.'],
    	'title_1' => ['Responsive design'],
    	'title_2' => ['Web development'],
    	'title_3' => ['Customer support'],
    	'title_4' => ['images included'],
    	'title_text_1' => ['Unexpected'], //Может и такое быть
    	'_edit_lock' => ['1570606503:1'],
    	'_thumbnail_id' => ['59'],
    	'_edit_last' => ['1'],
    	'single_image_1' => ['94'],
    	'single_image_2' => ['91'],
    	'single_image_3' => ['92'],
    	'single_image_4' => ['93'],
    ];
    
    $prefixes = [];
    $maxIndex = 0;
    
    foreach (array_keys($array) as $key) {
    	$parts = explode('_', $key);
    	$index = array_pop($parts);
    
    	if (!is_numeric($index)) {
    		continue;
    	}
    
    	$prefixes[implode('_', $parts)] = null;
    
    	if ($index > $maxIndex) {
    		$maxIndex = $index;
    	}
    }
    
    $output = [];
    $prefixes = array_keys($prefixes);
    
    for ($index = 1; $index <= $maxIndex; $index++) {
    	$row = [];
    
    	foreach ($prefixes as $prefix) {
    		$key = "{$prefix}_{$index}";
    		$row[$key] = @$array[$key];
    	}
    
    	$output[] = $row;
    }
    
    var_dump($output);


    sandbox.onlinephpfunctions.com/code/1fd759f48a4653...
    Ответ написан
    Комментировать
  • Как осуществить перенаправление запроса с одного сайта на другой с выводом результата на первый?

    Ninazu
    @Ninazu
    В htaccess site1 добавить
    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^site1.com
    RewriteRule ^(.*) http://site2.com/$1 [P]


    P.S. Если не взлетело, и падает с 500-й ошибкой. Проверить также что включены модули mod_rewrite, mod_proxy и на всякий случай mod_proxy_http
    Ответ написан
    Комментировать
  • Как составить регулярку?

    Ninazu
    @Ninazu
    <?php
      
    $regExp = "/(\.(\w+){1})|(^\w+$)/";
    
    
    $tests = [
        "web.test1.pages.page",
        "web.test2",
        "web.test3.yes",
        "test4",
    ];
    
    foreach($tests as $test){
        if(preg_match($regExp, $test, $matches)){
            var_dump(end($matches));
        }
    }
    Ответ написан
  • Какие принципы SOLID здесь нарушены?

    Ninazu
    @Ninazu Автор вопроса
    Сделал через Visitor, по моему получилось неплохо.

    <?php
    
    interface IVisitor {
    
    	public function getResult();
    
    	public function visit(IShape $element): void;
    }
    
    interface IShape {
    
    	public function accept(IVisitor $visitor): void;
    }
    
    interface IArea extends IShape {
    
    	public function getArea(): float;
    }
    
    interface IFillColor extends IShape {
    
    	public function setFillColor(string $rgb);
    
    	public function getFillColor(): int;
    }
    
    trait TFillColor {
    
    	protected $fillColor = 0;
    
    	public function getFillColor(): int {
    		return $this->fillColor;
    	}
    
    	public function setFillColor(string $rgb) {
    		$this->fillColor = (int)hexdec($rgb);
    	}
    }
    
    class Line implements IArea {
    
    	protected $length;
    
    	public function __construct(float $length) {
    		$this->length = $length;
    	}
    
    	public function getArea(): float {
    		return $this->length;
    	}
    
    	public function accept(IVisitor $visitor): void {
    		$visitor->visit($this);
    	}
    }
    
    class Rectangle implements IShape, IFillColor {
    
    	use TFillColor;
    
    	protected $width;
    
    	protected $height;
    
    	public function __construct(float $width, float $height) {
    		$this->width = $width;
    		$this->height = $height;
    	}
    
    	public function getArea(): float {
    		return $this->width * $this->height;
    	}
    
    	public function accept(IVisitor $visitor): void {
    		$visitor->visit($this);
    	}
    }
    
    class Box {
    
    	/**@var IShape[] $shapes */
    	protected $shapes = [];
    
    	public function addShape(IShape $shape): self {
    		$this->shapes[] = $shape;
    
    		return $this;
    	}
    
    	public function executeVisitor(IVisitor $visitor) {
    		foreach ($this->shapes as $shape) {
    			$shape->accept($visitor);
    		}
    
    		return $visitor->getResult();
    	}
    }
    
    class TotalAreaWithColor implements IVisitor {
    
    	protected $total = 0;
    
    	protected $color;
    
    	public function __construct(int $color) {
    		$this->color = $color;
    	}
    
    	public function visit(IShape $element): void {
    		if ($element instanceof IFillColor && $element->getFillColor() === $this->color) {
    			$this->total += $element->getArea();
    		}
    	}
    
    	public function getResult() {
    		return $this->total;
    	}
    }
    
    $rect  = new Rectangle(4, 10);
    $rect->setFillColor("FF0000");
    
    $line = new Line(10);
    
    echo (new Box())
    	->addShape($rect)
    	->addShape($line)
    	->executeVisitor(new TotalAreaWithColor(hexdec("FF0000")));
    Ответ написан
  • Как отсортировать такой массив?

    Ninazu
    @Ninazu
    Если уровней вложенности только два. То можно и без рекурсии

    $categories = [];
    
    foreach($list as $row){
        if ($row['parent_id'] == 0) {
            continue;
        }
    
        $categories[$row['parent_id']][] = $row['name'];
    }
    
    foreach($categories as $names){  
         echo "<ul>";
         foreach($names as $name){
                  echo "<li>{$name}</li>";
         }
         echo "</ul>";
    }
    Ответ написан
    Комментировать
  • Как передать ошибку пользователю из класса?

    Ninazu
    @Ninazu
    Можно ловить все ошибки в одном месте

    <?php
    
    class Response {
    
    	public function sendResponse(array $data) {
    		echo json_encode($data);
    
    		return true;
    	}
    
    	public function sendError(string $message) {
    		echo json_encode(['error' => $message]);
    
    		return false;
    	}
    }
    
    class ErrorHandler {
    
    	private $response;
    
    	public function __construct(Response $response) {
    		$this->response = $response;
    	}
    
    	public function handlerError($error_code, $message, $file = null, $line = null) {
    		if ($error_code) {
    			throw new Exception($message, $error_code);
    		}
    
    		return true;
    	}
    
    	public function handlerShutdown() {
    		$error = error_get_last();
    
    		if ($error) {
    			$this->handlerException(new Error($error['message'], $error['type']));
    		}
    
    		exit(0);
    	}
    
    	public function handlerException(Throwable $exception) {
    		if (ob_get_length()) {
    			ob_end_clean();
    		}
    
    		if (!headers_sent()) {
    			return $this->response->sendError($exception->getMessage());
    		}
    
    		return true;
    	}
    }
    
    $response = new Response();
    $handler = new ErrorHandler($response);
    register_shutdown_function([$handler, 'handlerShutdown']);
    set_error_handler([$handler, 'handlerError']);
    set_exception_handler([$handler, 'handlerException']);
    
    #region Logic
    
    $cnt = 0;
    
    if ($cnt === 0) {
    	throw new Exception("Нулевое количество");
    }
    
    #endregion
    
    $response->sendResponse([
    	'message' => "Всё окей"
    ]);
    Ответ написан
    2 комментария
  • Зачем нужны абстрактные классы и интерфейсы в php?

    Ninazu
    @Ninazu
    1. Абстрактный класс нельзя создать, только создать обьект от наследуемого класса
    2. Абстрактный класс может содержать реализацию, в отличии от интерфейса
    3. Абстрактный класс может содержать абстрактные методы, которые необходимо будет реализовать в дочерних классах
    4. Можно имплементировать сразу несколько интерфейсов, а наследовать только от одного класса.
    5. Трейты очень хорошо комбинируются с интерфейсами

    Осознание зачем это нужно, прийдёт к вам в процессе использования)) Почитайте также про SOLID, и попробуйте реализовать эти принципы без абстракций и интерфейсов)

    P.S. Домашнее задание
    Есть три класса. Квадрат, Прямоугольник, Круг. И класс Ящик. Мы добавляем в ящик, произвольные наборы из фигур, и нужно посчитать площадь всех фигур в ящике.
    Ответ написан
  • Почему AJAX запрос обрывается на 5-ой минуте выполнения PHP скрипта, к которому обращаемся через AJAX на JavaScript?

    Ninazu
    @Ninazu
    Дело в серверной части. Время жизни скрипта видимо 5-ть минут. Это ненормально ждать ответа минутами. Если логика того требует то переделайте на WebSocket. Ну или на крайний случай LongPooling, хотя я бы всё же пересмотрел логику и двигался в сторону либо WebSocket, либо очередей и получение данных со следующими запросами
    Ответ написан
    Комментировать
  • Как правильно выполнить запрос mysql с INNER JOIN с большими базами?

    Ninazu
    @Ninazu
    Проще двумя запросами. Подзапросы и джоин сам на себя не советую если база большая и индексы не расставлены или более сложная логика присутсвует вроде (показать картинку последнего продукта).
    Вытащить все категории, потом вытащить по одному продукту для каждой через IN
    Либо вариант второй, денормализировать, и хранить картинку категории в категории

    P.S. Если всё же захотите через INNER JOIN, то не забудьте индекс на image добавить, и я бы делал не пустую строку а NULL

    SELECT
        p.product_id,
        p.image
    FROM oc_product_to_category c
        INNER JOIN oc_product p ON p.product_id = c.product_id
            AND p.image IS NOT NULL
    WHERE c.id_categor = :categoryId
    LIMIT 1
    Ответ написан
    Комментировать
  • Как реализовать подобную пагинацию на php?

    Ninazu
    @Ninazu
    Такое делается не специально, это скорее рукожопы сделали плохой роутинг на JS в SPA. Настоятельно не рекоммендую такое повторять, ничего хорошего от отсутсвия прямых ссылок не ждите. Ну или напишите зачем оно вам, может вы не в ту сторону копаете вообще?

    P.S. На ServerSide можно сделать через цепочку хешей
    Ответ написан
    Комментировать
  • Как переслать сообщения Telegram из закрытой группы?

    Ninazu
    @Ninazu
    forward канал, вроде позволяет пересылать сообщения. Если можно из интерфейса, то можно и программно
    Ответ написан
  • Нужно ли защищать обработчик формы (PHP файл) от прямого доступа?

    Ninazu
    @Ninazu
    1. Создай единую точку входа, и оставь ее в корне сайта, остальные файлы вынеси за пределы (Это не только сделает твое приложении более гибким, понятным, и структурированным, но и в случае отваливания веб сервера, такое когда-то у меня было, после кривого обновлении до php7, исходный код показывался браузером)
    2. Не забудь про SQL иньекции. Никакой конкатенации или вставок PHP. Только плейсхолдеры и байндинг
    3. Если есть возможность загружать файлы, нужно исключить возможность исполнения в этой папке.
    Ответ написан
    3 комментария
  • Могут ли пользователи загрузить вирус на сайте?

    Ninazu
    @Ninazu
    Зависит от того как генерируется конфиг по введенным данным пользователя. И как потом используется. В генераторах обычно данные экранируются, если пользователь сможет обойти экранирование. Если этот конфиг потом подключается, то у вас проблеммы)
    Ответ написан
    Комментировать
  • Как перенести содержимое ключа массива в следующий ключ массива по условию?

    Ninazu
    @Ninazu
    function fixArray($input){
        $output = [];
        
        foreach($input as $value){
            if(preg_match("/^0(\d+.*$)/", $value, $match)){
                $output[] = "0"; 
                $output[] = $match[1];
            }else{
                $output[] = $value;
            }
        }
    
        return $output;
    }
    Ответ написан
  • Почему PhpStorm требует установки расширения для curl и json?

    Ninazu
    @Ninazu
    Расширение - это дополнительные модули в PHP, они реализуют конкретно в вашем случае работу с CURL и JSON.
    Узнать подключенные модули
    https://www.php.net/manual/ru/function.extension-l...
    Список всех модулей
    https://www.php.net/manual/ru/extensions.alphabeti...

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

    Если бесит инспектор, то можете отключить это уведомление.
    5d4061ba05631701466003.png
    Ответ написан
    3 комментария
  • Php - вложеные вызовы в echo?

    Ninazu
    @Ninazu
    Сложность в том, что phpinfo, не возвращает значение, а выводит его. Поэтому нужно перехватить вывод, направить его в переменную, ну а потом можно делать что угодно уже с ним))

    $getPHPInfo = function () {
    	ob_start();
    	phpinfo();
    	$result = ob_get_contents();
    	ob_clean();
    
    	return $result;
    };
    
    
    echo "123 {$getPHPInfo()}";
    Ответ написан
    Комментировать
  • Как защитить php код от прямого запуска?

    Ninazu
    @Ninazu
    1. Выносить всё за пределы корня. Оставив единую точку входа
    2. Что вынести нельзя, можно закрыть с помощью .htaccess
    Ответ написан
    Комментировать
  • Linux Mint 19.1 - как починить индикатор батареи?

    Ninazu
    @Ninazu
    В BIOS проверяли лимиты на максимальный и минимальный заряд? В dmesg что-то есть?
    Ответ написан
    Комментировать
  • Чем отличаются миграции от доктрины?

    Ninazu
    @Ninazu
    Миграции - это последовательность модифицирующих запросов к базе.
    Доктрина - это ORM, способ работы с реляционными данными через обьекты.

    P.S. Не рекоммендую делать миграции на базе ORM. Представим сценарий миграции
    1. Создать таблицу пользователей
    2. Переименовать таблицу пользователей в клиентов
    3. Добавить столбец с таблицу клиентов.

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