Skip to content

Instantly share code, notes, and snippets.

@LordJohn42
Last active September 26, 2019 14:37
Show Gist options
  • Save LordJohn42/4ec2a0a1592fb7bb4d3e54754b55ad4e to your computer and use it in GitHub Desktop.
Save LordJohn42/4ec2a0a1592fb7bb4d3e54754b55ad4e to your computer and use it in GitHub Desktop.
PHP code examples.
<?php
// Simple container
// Простая реализация контейнера.
namespace System\Container;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionException;
/**
* Class Container
* @package System\Container
*/
class Container implements ContainerInterface
{
/**
* @var array
*/
private $instances = [];
/**
* @var array
*/
private $bindings = [];
/**
* @var Container
*/
private static $instance;
/**
* Container constructor.
*/
private function __construct()
{
}
/**
* Get container instance
*
* @return Container
*/
public static function getInstance()
{
if (static::$instance === null) {
static::$instance = new static();
}
return static::$instance;
}
/**
* Added bind with the name
*
* @param string $name
* @param mixed $source
* @param mixed $params
* @return $this
*/
public function bind($name, $source, $params = [])
{
if (($source instanceof \Closure) || is_string($source)) {
$this->bindings[$name] = [$source, $params];
} else {
$this->instances[$name] = $source;
}
return $this;
}
/**
* @param string $name
* @return mixed
* @throws NotFoundException
* @throws ReflectionException
*/
public function get($name)
{
if ($this->has($name)) {
if ($this->hasInstance($name)) {
$instance = $this->instances[$name];
} else {
$instance = $this->binding($name);
$this->instances[$name] = $instance;
}
return $instance;
}
throw new NotFoundException();
}
/**
* Binding instance to the name
*
* @param string $name
* @return mixed
* @throws NotFoundException
* @throws ReflectionException
*/
private function binding($name)
{
list($source, $params) = $this->bindings[$name];
if (is_string($source) || class_exists($source)) {
$reflector = new ReflectionClass($source);
return $reflector->newInstanceArgs($params);
} elseif ($source instanceof \Closure) {
return call_user_func_array($source, $params);
}
throw new NotFoundException();
}
/**
* Check exist instance with the name
*
* @param string $name
* @return bool
*/
private function hasInstance($name)
{
return isset($this->instances[$name]);
}
/**
* Check exist bind with the name
*
* @param string $name
* @return bool
*/
private function hasBinding($name)
{
return isset($this->bindings[$name]);
}
/**
* @param string $name
* @return bool
*/
public function has($name)
{
return $this->hasBinding($name) || $this->hasInstance($name);
}
}
<?php
// Пример CRUD контроллера хранения справочника валют.
namespace App\Http\Controllers\Cabinet;
use App\Criterias\VisibilityCriteria;
use App\Http\Controllers\Controller;
use App\Http\Requests\Currency\CurrencyFormRequest;
use App\Models\Currency;
use App\Repositories\Contracts\CurrencyRepository;
use App\Repositories\CurrencyRepositoryEloquent;
use App\Services\StoryWriter;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Session;
use DebugBar;
class CurrenciesController extends Controller
{
/** @var CurrencyRepositoryEloquent */
protected $repository;
public function __construct(CurrencyRepository $repository)
{
$this->repository = $repository;
}
//
public function index(Request $request)
{
if(!Auth::user()->hasSystemRole('Суперадмин'))
return redirect()->back()->with('error', 'У вас нет прав');
$this->repository->pushCriteria(new VisibilityCriteria('Смотреть валюту'));
$currencies = $this->repository->paginate(Currency::$per_page);
return view('cabinet.currencies.index')->with('items',$currencies);
}
public function create()
{
if(!Auth::user()->hasSystemRole('Суперадмин')) abort(403);
return view('cabinet.currencies.create')->with('currency', new Currency() );
}
public function store(CurrencyFormRequest $request)
{
if(!Auth::user()->hasSystemRole('Суперадмин'))
return redirect()->back()->with('error', 'У вас нет прав на добавление валюты');
$script = new Currency();
$script->fill($request->input('currency'));
$script->save();
StoryWriter::created($script);
Session::flash('success', 'Валюта добавлена');
return Redirect::route('cabinet.currencies.index');
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return Response
*/
public function edit($id)
{
if(!Auth::user()->hasSystemRole('Суперадмин'))
return redirect()->back()->with('error', 'У вас нет прав на редактирование валюты');
$currency = Currency::find($id);
if(is_null($currency))
return redirect()->route('cabinet.currencies.index')
->with('error','Ошибка, валюта не найдена :(');
Debugbar::info($currency->toArray());
return view('cabinet.currencies.edit')
->with('currency', $currency);
}
/**
* Update the specified resource in storage.
*
* @param CurrencyFormRequest $request
* @param int $id
* @return Response
*/
public function update(CurrencyFormRequest $request, $id)
{
if(!Auth::user()->hasSystemRole('Суперадмин'))
return redirect()->back()->with('error', 'У вас нет прав на изменение валюты');
$currency = Currency::find($id);
if(is_null($currency))
return redirect()->route('cabinet.currencies.index')
->with('error','Ошибка, валюта не найдена :(');
$input = $request->input('currency');
$currency->fill($input);
$currency->save();
StoryWriter::updated($currency);
return Redirect::route('cabinet.currencies.index')->with('success','Сохранено');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return Response
*/
public function destroy($id)
{
if(!Auth::user()->hasSystemRole('Суперадмин'))
return redirect()->back()->with('error', 'У вас нет прав на удаление валюты');
$currency = Currency::find($id);
if($currency) {
$currency->delete();
return redirect()->back()->with('success', 'Валюта '.$currency->name.' удалена');
} else {
return redirect()->back()->with('error', 'Ошибка, валюта не найдена :(');
}
}
/**
* @param $id
* @return Response
*/
public function restore($id)
{
if(!Auth::user()->hasSystemRole('Суперадмин'))
return redirect()->back()->with('error', 'У вас нет прав на восстановление валюты');
$script = Currency::onlyTrashed()->whereId($id)->first();
if($script) {
$script->restore();
return redirect()->back()->with('success', 'Валюта '.$script->name.' восстановлена');
} else {
return redirect()->back()->with('error', 'Ошибка, валюта не найдена :(');
}
}
}
<?php
// Получение курса валют с сайта ЦБРФ
namespace App\Console\Commands;
use App\Models\Currency;
use Exception;
use Illuminate\Console\Command;
class CurrencyUpdateCBRF extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'currency:updatecbrf';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Update currency from CBRF';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
public function loadByCurl($url, $agentName, $referrer='', $ip = '', $proxy = [], $isAjax = false, $postData = [] )
{
$errors = [];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 25);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 25);
if ($isAjax) {
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-Requested-With' => 'XMLHttpRequest'));
}
if ($referrer){
curl_setopt($ch, CURLOPT_REFERER, $referrer);
}
if( !empty( $postData ) ) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query( $postData ) );
}
if( !empty( $agentName ) ) {
curl_setopt($ch, CURLOPT_USERAGENT, $agentName);
}
if( !empty( $ip ) ) {
curl_setopt($ch, CURLOPT_INTERFACE, $ip);
} else if( !empty( $proxy ) && is_array( $proxy ) ) {
curl_setopt($ch, CURLOPT_PROXY, $proxy['host'] . ':' . $proxy['port']);
if ($proxy['login'] && $proxy['password']) {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy['login'] . ':' . $proxy['password']);
}
}
$data = curl_exec($ch);
$status = curl_getinfo($ch,CURLINFO_HTTP_CODE);
if( curl_errno($ch) !== 0 ) {
$errors[] = curl_error($ch);
}
if( $status !== 200 ) {
$errors[] = 'End load with HTTP code: '.$status;
}
curl_close($ch);
return $data;
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
/** @var $oDefaultCurrency Currency */
/** @var $oCurrentCurrency Currency */
setlocale(LC_NUMERIC, 'POSIX');
// При увеличении курса ЦБ на 2% установите значение 1.02
$coefficient = 1.02;
$cbrf = [];
$exchangeRate = [];
$url = 'http://www.cbr.ru/scripts/XML_daily.asp';
//$url = 'https://www.cbr-xml-daily.ru/daily_utf8.xml';
$xml = $this->loadByCurl(
$url,
'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/45.0.2454.101 Chrome/45.0.2454.101 Safari/537.36'
);
$oXml = @simplexml_load_string($xml);
if (is_object($oXml)) {
$oDefaultCurrency = Currency::default()->first();
foreach ($oXml->Valute as $Valute) {
$code = iconv('windows-1251','utf-8', trim( strval($Valute->CharCode) ) );
$cbrf[$code] = [
'value' => floatval((str_replace(',', '.', $Valute->Value))),
'nominal' => floatval((str_replace(',', '.', $Valute->Nominal)))
];
$exchangeRate[$code] = floatval((str_replace(',', '.', $Valute->Value))) / floatval(str_replace(',', '.', $Valute->Nominal));
}
if ($oDefaultCurrency->code != 'RUB' && !isset($exchangeRate[$oDefaultCurrency->code])) {
throw new Exception('Default currency does not exist in the XML');
}
// любая валюта по умолчанию равна 1
$oDefaultCurrency->exchange_rate = 1;
$oDefaultCurrency->rate_value = 1;
$oDefaultCurrency->updated_at = $oDefaultCurrency->freshTimestamp();
if( $oDefaultCurrency->save() ) {
$this->info('Updated default currency ' . $oDefaultCurrency->code . ' rate is ' . $oDefaultCurrency->exchange_rate);
}
/* Рубль - не всегда валюта по умолчанию, но он всегда отсутствует во входящем XML.
* Итак, если:
валюта по умолчанию НЕ рубль
И рубль присутсвует в списке валют
ставим рублю его котировку, относительно валюты по умолчанию
*/
if ($oDefaultCurrency->code != 'RUB') {
$fRubRate = 1.0 / $exchangeRate[$oDefaultCurrency->code];
$oRubCurrency = Currency::where('code','=','RUB')->first();
if( !empty($oRubCurrency) ) {
$oRubCurrency->exchange_rate = $fRubRate;
$oRubCurrency->rate_value = $fRubRate;
$oRubCurrency->save();
}
}
foreach ($exchangeRate as $code => $rate) {
$rate *= $coefficient;
// ищем текущую валюту
$oCurrentCurrency = Currency::where('code','=',$code)->first();
if(empty($oCurrentCurrency)) {
// валюта не найдена, пропускаем итерацию
$this->info('Currency '.$code.' not found in list');
continue;
}
if ($oDefaultCurrency->code == 'RUB') {
$oCurrentCurrency->exchange_rate = $rate;
$oCurrentCurrency->rate_value = $rate;
$oCurrentCurrency->save();
}
elseif (isset($exchangeRate[$oDefaultCurrency->code])) {
$oCurrentCurrency->exchange_rate = $rate * $fRubRate;
$oCurrentCurrency->rate_value = $rate * $fRubRate;
$oCurrentCurrency->save();
}
$this->info('Updated currency '.$code.' rate is '.$oCurrentCurrency->exchange_rate);
}
}
$this->info('OK');
}
}
<?php
// Фоновая команда рассылки почты
namespace App\Console\Commands;
use App\Models\Mailbox;
use Illuminate\Console\Command;
use Symfony\Component\Process\Process;
use App\Collections\ProcessCollection;
/**
*
* Эта команда запускает
* кучу подпроцессов получения почты
* но не более чем $processCollection->max
* при достижении максимального лимита процессов
* ждет пока закончит один из процессов (любой)
* и запускает следующий
*
*/
class MailGetAll extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'mail:getall';
/**
* The console command description.
*
* @var string
*/
protected $description = 'start subprocesses of get mail';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// Все процессы получения почты будем складывать сюда
$process_list = new ProcessCollection();
// Возьмем все почтовые ящики без ошибок (не более 3х попыток, попытки инкрементируются в attempted)
// И не остановленные вручную (критерий != PAUSED)
$mailboxes = Mailbox::paused(false)
->attempted(false)
->get();
// Подготовим процессы к старту (создадим команды)
// и засунем их в коллекцию
$mailboxes->each(function($mailbox) use (&$process_list)
{
// Создадим процесс (не запустим, а создадим экземпляр)
$process = new Process('php artisan mail:pick '.$mailbox->account);
$process->setTimeout(1000);
// И засунем его в коллекцию
$process_list->push($process);
});
// Будем запускать
// все процессы из
// из коллекции
$k = 0;
$process_list->each(function($process) use (&$process_list,&$k)
{
// Запустим процесс
$process->start();
// exec($process->getCommandLine());
$this->info('process started.. ['.$process->getCommandLine().']');
// Если уже запущено максимальное кол-во процессов
// подождем пока не умрет какой-нибудь процесс
while($process_list->isRunCount() >= $process_list->max)
{
sleep(2);
$k++;
if($k%3 ==0) $this->info('max processes runned.. sleep');
}
});
// Подождем пока все процессы выполнятся
while($process_list->isRunCount())
{
sleep(2);
$k++;
if($k%3 ==0) {
$this->info('..sleep.. process runned: '.$process_list->isRunCount());
$i=0;
foreach($process_list->runned() as $process)
{
$i++;
$this->info($i.'. '.$process->getCommandLine().PHP_EOL);
}
}
}
$this->info('All process down');
$process_list->each(function($process)
{
$this->info('process ['.$process->getCommandLine().'] with code '.$process->getExitCode());
$this->error($process->getErrorOutput());
// $this->info($process->getOutput());
// $this->info($process->getErrorOutput());
});
// Для заметки оставлю здесь как убивать процессы
// Вдруг пригодится :)
// $process->stop(3, SIGINT);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment