$str = '0123456789 abcdKDLAD !@#$%^&*()_+ абвгЖЗИКМ chỉđơngiảnlà 是印刷及排版';
$result = preg_replace('#(*UTF8)[^\pL\pN\s]+#u','', $str);
echo $result; // 0123456789 abcdKDLAD абвгЖЗИКМ chỉđơngiảnlà 是印刷及排版
Так-же можно удалять и пробелы убрав метасимвол \s.
echo $form->field($model, 'is_bot')->radioList(['' => 'Все', false => 'Люди', true => 'Боты'], [
'itemOptions' => ['class' => 'd-none', 'labelOptions' => ['class' => 'btn btn-primary']],
'class' => 'btn-group',
'data-toggle' => 'buttons',
])->label(false);
Пусковой скрипт для запуска cron-команд в docker-контенере. Проверяет cron-выражение и запускает команду. Умеет выход по сигналам SIGTERM
и SIGINT
. В отличии от стандартного cron-демона следующую команду не запустит пока не выполнит предыдущую. Удобно использовать при разработке c docker-compose. В логах докера показывает что запускалось, когда, и с каким результатом.
#!/usr/bin/env php
<?php
/**
* Скрипт для запуска команды по расписанию, для замены cron-а в сети из docker-контейнеров.
*
* Пример команды, которая будет запускаться каждую минуту:
* docker/php/cron.php "* * * * *" php yii rate/update
*
* Зависимости:
* "mtdowling/cron-expression": "~1.2.0"
*
* @author Roman Zhuravlev <zhuravljov@gmail.com>
*/
require(__DIR__ . '/../../vendor/autoload.php');
// Params
$params = $_SERVER['argv'];
array_shift($params);
$expression = array_shift($params);
$command = implode(' ', $params);
$schedule = \Cron\CronExpression::factory($expression);
// Signal handler
$signal = 0;
$signalHandler = function ($sigNum) use (&$signal) {
$signal = $sigNum;
};
pcntl_signal(SIGTERM, $signalHandler);
pcntl_signal(SIGINT, $signalHandler);
// Loop
printLog('Cron started');
while (true) {
sleep(60 - time() % 60);
pcntl_signal_dispatch();
if ($signal) {
printLog("Cron stopped by signal $signal");
exit(0);
}
if (!$schedule->isDue()) {
continue;
}
$startedAt = microtime(true);
printLog("[started] command: $command", $startedAt);
passthru($command, $exitCode);
$finishedAt = microtime(true);
$totalTime = sprintf('%01.3f', $finishedAt - $startedAt);
printLog("[finished] duration $totalTime s, exit code $exitCode");
if ($exitCode) {
exit($exitCode);
}
}
function printLog($message, $time = null)
{
echo date('Y-m-d H:i:s', $time ?? time()), ' ' , $message, PHP_EOL;
}
Функция, позволяющая перевести PhpOffice Spreadsheet в таблицу PhpWord Table, Чтобы напечатать таблицу в .doc файле. Пришлось сделать эту функцию, потому что перевод XLS->HTML и HTML->DOC работает плохо для таблиц.
Из недочетов метода:
Делал этот метод для того, чтобы основная логика генерации таблиц была в XLS и чтобы генерация DOC использовала эту таблицу уже готовую и вставляла таблицу в заготовленный шаблон DOC.
private function convertXlsToDocTable(Worksheet $sheet, Table $table)
{
foreach ($sheet->getRowIterator() as $rowIndex => $row) {
$table->addRow();
$prevMergeRange = null;
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(false);
foreach ($cellIterator as $cellIndex => $cell) {
$value = $cell->getValue();
$mergeRange = $cell->getMergeRange();
if ($mergeRange && $prevMergeRange == $mergeRange) {
continue;
}
if ($mergeRange) {
$mergeCount = 0;
foreach ($row as $mergeCell) {
if ($mergeRange == $mergeCell['mergeRange']) {
$mergeCount++;
}
}
$table->addCell(2000, ['gridSpan' => $mergeCount])->addText($value);
$prevMergeRange = $mergeRange;
} else {
$table->addCell(2000, [])->addText($value);
}
}
}
return $table;
}
function urange($start, $end, $step)
{
if (!is_callable($step)) {
return range($start, $end, $step);
}
$helper = function ($current, $start) use ($end, $step, &$helper) {
if ($start > $end) {
return $current;
}
$current[] = $start;
return $helper($current, $step($start));
};
return $helper([], $start);
}
print_r(urange(20, 39, function ($n) {
$next = ($n / 10) % 10;
return $n + ($next >= 1 ? $next : 1);
}));
print_r(urange(1, 40, function ($n) {
return $n+1;
}));
print_r(urange(1, 40, function ($n) {
return $n+$n;
}));
Если SF3 ставить на Docker, без лишних заморочек с конфигурированием, отдача страницы будет около 30 сек, что очень долго. После долгого чтения гугла, я пробовал вариант с :cached
, стало веселее - отдача страницы 2-3 секунды.
Проблема долгой отдачи страницы - много файлов. В папке vendor
, cache
, много файлов. Для быстрой отдачи страницы, мы должны игнорировать синхронизацию этих папок.
Вот простое решение задачи:
php:
...
volumes:
- ${SYMFONY_APP_PATH}:/var/www/src
- ${SYMFONY_APP_PATH}/var/logs:/var/www/src/var/logs
- /var/www/src/vendor
- /var/www/src/var/cache
Код выше синхронизирует только исходные коды проекта и папку с логами, всё что ниже - игнорируется.
Intervention Image — библиотека с простым API для работы с изображениям.
Что библиотека умеет:
Вы можете использовать Intervention Image двумя способами:
// open an image file
$img = Image::make('public/foo.jpg');
// now you are able to resize the instance
$img->resize(320, 240);
// and insert a watermark for example
$img->insert('public/watermark.png');
// finally we save the image as a new file
$img->save('public/bar.jpg');
Либо, через цепочку вызовов:
$img = Image::make('public/foo.jpg')
->resize(320, 240)
->insert('public/watermark.png')
->save('public/bar.jpg');
Помимо статического вызова, можно создать объект, и работать с ним:
// include composer autoload
require 'vendor/autoload.php';
// import the Intervention Image Manager Class
use Intervention\Image\ImageManager;
// create an image manager instance with favored driver
$manager = new ImageManager(array('driver' => 'imagick'));
// to finally create image instances
$image = $manager->make('public/foo.jpg')->resize(300, 200);
Для разработчиков Laravel, всё работает из коробки.
При сохранении груповых данных, зачастую требуется сопоставить, то-что у нас уже хранится в БД и то-что пришло с формы, для этого приходится сверять элименты по уникальному полю, данный снипет, из одной незамысловатой строки, вернет массив с уникальными ключами. Затем можно уже проверять на isset($models_by_id[$id]) или array_diff_key, ну и т.д.
$models_by_id=Model::find()->indexBy('id')->all(); //yii 2 path @mista twista
$models=Model::model()->findAll(); //yii 1
$models_by_id=array_combine(array_keys(CHtml::listData($models, 'id', 'id')),$models);
$models_by_id=array_combine(array_column($model,'id'),$model); //since php5.5
Стандартный класс LinkPager генерирует HTML-код постраничной навигации, который неправильно отображается с Bootstrap 4. Этот сниппет исправляет эту проблему.
<?php
namespace app\components;
use Yii;
use yii\helpers\Html;
use yii\widgets\LinkPager;
class BootstrapLinkPager extends LinkPager
{
/**
* @inheritdoc
*/
public function init()
{
parent::init();
// In Bootstrap 4 no div's "next" and "prev", so you need to overwrite the default values
$this->prevPageCssClass = 'page-item';
$this->nextPageCssClass = 'page-item';
// Change the location and size of block
// https://v4-alpha.getbootstrap.com/components/pagination/#alignment
// https://v4-alpha.getbootstrap.com/components/pagination/#sizing
$this->options['class'] = 'pagination justify-content-center';
// Change standard arrows "«" and "»"
$this->nextPageLabel = Yii::t('app', 'Next');
$this->prevPageLabel = Yii::t('app', 'Previous');
// Default div for links
$this->linkOptions['class'] = 'page-link';
}
/**
* @inheritdoc
*/
public function run()
{
if ($this->registerLinkTags) {
$this->registerLinkTags();
}
if ($this->pagination->getPageCount() > 1) {
echo Html::tag('nav', $this->renderPageButtons());
}
}
/**
* @inheritdoc
*/
protected function renderPageButton($label, $page, $class, $disabled, $active)
{
$options = ['class' => empty($class) ? 'page-item' : $class];
$linkOptions = $this->linkOptions;
if ($active) {
Html::addCssClass($options, $this->activePageCssClass);
}
if ($disabled) {
Html::addCssClass($options, $this->disabledPageCssClass);
$linkOptions['tabindex'] = '-1';
}
return Html::tag('li', Html::a($label, $this->pagination->createUrl($page), $linkOptions), $options);
}
}
Использовать просто: вместо LinkPager при вызове используйте BootstrapLinkPager.
Установить другой шаблон:
$this->layout()->setTemplate('layout/new-layout');
Добавить новый шаблон для сайдбара:
$view = new ViewModel();
$sideView = new ViewModel();
$sideView->setTemplate('content/sidebar');
$this->$layout->addChild($sideView, 'side-view');
return $view;
Отключить шаблон:
$view = new ViewModel();
$view->setTerminal(true);
return $view;
Разные файлы шаблона для разных контролеров:
//module.php
public function init(ModuleManager $moduleManager){
$sharedEvents = $moduleManager->getEventManager()->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
$controller = $e->getTarget();
if ($controller instanceof Controller\FrontEndController) {
$controller->layout('layout/front');
}
}, 100);
}
Получить доступ к объекту View в модули:
public function onBootstrap($e){
$app = $e->getApplication();
$viewModel = $app->getMvcEvent()->getViewModel();
}
Получить значение представления в Layout:
$viewModel = $this->viewModel()->getCurrent();
$children = $viewModel->getChildren();
$viewModel = $children[0];
$viewModel->foo;