Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) { ... }
Нет никакого способа установить $report_errors = false без повторения двух других значений по умолчанию. Для решения этой проблемы предлагается использовать пропуск параметров:
create_query("deleted=0", "name", default, default, false);
create_query("deleted=0", "name", $report_errors=false);, было бы круто. create_query("deleted=0", "name", "report_errors"=>false)
Всё, что внутри метода относится к внутренней реализации и внешний код не должно волновать как называется параметр функции — $cnt или $totalPages.
create_query("deleted=0", "name", $report_errors=>false)create_query("deleted=0", "name", array($report_errors=>false))create_query("deleted=0", "name", [$report_errors=>false])create_query("deleted=0", "name", , , false);
create_query("deleted=0", "name", NULL, NULL, false);
function some($arg1, $arg2 = 'some', $arg3 = 5)
{
echo $arg1 . ' ' . gettype($arg1) . PHP_EOL; // 1.1 double
echo $arg2 . ' ' . gettype($arg2) . PHP_EOL; // NULL
echo $arg3 . ' ' . gettype($arg3) . PHP_EOL; // 100 integer
}
some(1.1, null, 100);
create_query("deleted=0", "name", , , false)
if(!function_exists('array_column')){ function array_column(…){…}} не?Note:
Namespace names PHP and php, and compound names starting with these names (like PHP\Classes) are reserved for internal language use and should not be used in the userspace code.
public $hours {
get { return $this->seconds / 3600; }
set { $this->seconds = $value * 3600; }
}
<?php
$imagine = new Imagine\Gd\Imagine();
// or
$imagine = new Imagine\Imagick\Imagine();
// or
$imagine = new Imagine\Gmagick\Imagine();
$size = new Imagine\Image\Box(40, 40);
$mode = Imagine\Image\ImageInterface::THUMBNAIL_INSET;
// or
$mode = Imagine\Image\ImageInterface::THUMBNAIL_OUTBOUND;
$imagine->open('/path/to/large_image.jpg')
->thumbnail($size, $mode)
->save('/path/to/thumbnail.png')
;
public $hours {
get { return parent::$hours; }
set { parent::$hours = $value; }
}
public $hours = {
get { inherit; }
set { /* Set value here ... */ }
}
Отказ от поддержки Windows XP и 2003
Получение полного имени класса
array('Foo', 'bar'), которые IDE не могут валидировать. Хочу array(Foo::class, Foo::bar) или что-нибудь вроде того.Пропуск параметров
Контроль типа для скалярных значений
Getters и setters
Генераторы
Выделение списков и выражения-генераторы
Этим ужасом никто пользоваться не будет… если уж так хочется поддерживать говнокодерство с методами на 20 аргументов
$crop = new Crop($cropX1, $cropY1, $cropX2, $cropY2);
$thumb = new Thumbnail($source, $crop, $backgroundColor);
$create = $thumb->create($destination, $forceRegenerate);
if (!$create) {
// bla bla bla
}
new Crop($cropX1, $cropY1, $cropX2, $cropY2); в конструктор Thumbnail непосредственно.Thumbnail.from(source)
.crop(100, 100)
.quality(3)
.forceRegenerate(true)
.blabla(somearg)
.create(destination);
html_entity_decode( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' ]] )
html_entity_decode( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' ]] )
html_entity_decode( string $string [, string $encoding = 'UTF-8' ] )
html_entity_decode( string $string [, int $flags = ENT_COMPAT | ENT_HTML401])
зачем мне писать их, если я хочу указать кодировку?
html_entity_decode($string, , 'UTF-8'); // Отличный, удобный вариант.
// Это универсальнее, проще и понятнее чем function overloading.
html_entity_decode($string, empty($param) ? default : $param, 'UTF-8');
html_entity_decode($string, empty($param) ? (ENT_COMPAT | ENT_HTML401) : $param, 'UTF-8');
$flags = empty($param) ? (ENT_COMPAT | ENT_HTML401) : $param;
html_entity_decode($string, $flags, 'UTF-8');
$flags = empty($param) ? default : $param; // что здесь обозначает default ???
html_entity_decode($string, $flags, 'UTF-8');
$flags = empty($param) ? default : $param;
var_dump($flags); // что здесь будет?
html_entity_decode($string, , 'UTF-8');
html_entity_decode($string, default, 'UTF-8');
зачем ещё одно зарезервированное, если можно без него?
есть питоновский дзен — «Явное лучше, чем неявное».
html_entity_decode($string, , 'UTF-8');
Что бы пропустить не обязательный параметр, пропустите этот параметр
// vs
Что бы пропустить не обязательный параметр, укажите специальную конструкцию языка "default"А почему не empty?Особые случаи не настолько особые, чтобы нарушать правила.имею полное право считать, что пропуск параметра приведётся к NULL
$x = ; // это не работает.
Хотя, если «правильно» посчитать, то можно со спокойной совестью пропускать параметры используя null уже сейчас:html_entity_decode($string, null, 'UTF-8');
null — это же ведь «ничто», т.е. я как бы «передал ничто» или «ничего не передал». В оффициальной документации вообще написано, что переменная считается null-ом если она была удалена с помощью unset(). :) Т.е. отстутвующая переменная приравнивается к null.define('default', 'custom');
var_dump('test');
Отлично отрабатывает.define('default', 'custom');
var_dump(default); // Parse error: syntax error, unexpected ...
define("'", 123);
var_dump(constant("'")); // 123
define('true', false); // Notice: Constant true already defined
var_dump(FALSE);
// bool(false)
var_dump(TRUE);
// bool(true)
define('TRUE', false);
define('FALSE', true);
var_dump(TRUE);
// bool(false)
var_dump(FALSE);
// bool(true)shock@shock-notebook:~$ php -v
PHP 5.3.10-1ubuntu3.2 with Suhosin-Patch (cli) (built: Jun 13 2012 17:20:55)
Copyright © 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright © 1998-2012 Zend Technologies
shock@shock-notebook:~$ php define.php
bool(false)
bool(true)
bool(true)
bool(false)
createThumbnail($mySource, $myDestination, new CreateThumbnailParams(array('quality' => 10)))
foo.do(bar: "this is the bar", really: true);
foo.do({ 'bar' => "this is the bar", 'really' => true });
foo.do($bar => "this is the bar", $really => true );
$im->floodfillpaintimage($iPixel,10,$tPixel,$startX,$startY,false,Imagick::CHANNEL_DEFAULT);
// versus
$im->floodfillpaintimage({
$fill=>$iPixel,
$fuzz=>10,
$bordercolor=>$tPixel,
$x=>$startX,
$y=>$startY,
$invert=>false,
$CHANNEL=>Imagick::CHANNEL_DEFAULT
});
$im->floodfillpaintimage($iPixel,10,$tPixel,$startX,$startY,false,Imagick::CHANNEL_DEFAULT);
// versus
$im->floodfillpaintimage({
$fill=>$iPixel,
$fuzz=>10,
$bordercolor=>$tPixel,
$x=>$startX,
$y=>$startY,
$invert=>false,
$CHANNEL=>Imagick::CHANNEL_DEFAULT });
use Vendor\Image\Convert as imgconv;
imgconv\from("source.jpg")
->crop([10, 10, 40, 40])
->background(0xaabbcc)
->quality(80)
->regenerate(true)
->to("thumb.jpg");
// vs
createThumbnail("source.jpg", "thumb.jpg", 10, 10, 40, 40, 0xaabbcc, 80, true);
createThumbnail(
$from => "source.jpg",
$crop => [10, 10, 40, 40],
$background => 0xaabbcc,
$quality => 80,
$regenerate => true,
$to => "thumb.jpg"
);
class Crop
{
public static $x1=0;
public static $x2=0;
public static $y1=0;
public static $y2=0;
public static function set($x1, $y1, $x2, $y2);
}
class ThumbPipe
{
public static $source;
public static $destination;
public static function set($source, $destination);
}
class ThumbProperty
{
public static $backround;
public static $quality;
public static $forceRegenerate;
public static set($bg, $quality=80, $forceRegenerate=false);
}
$crop = Crop::set(1, 10, 52, 30);
$thumb = ThumbPipe::set('/srv/ht...', '/srv..');
$params = ThubmParams::set('#FFEE33');
createThumbnail(ThumbPipe $thumb, Crop $crop, ThumbParams $params);
$crop = array(1, 50, 20, 30);
$params = array('#FFFAAA', 85, true);
createThumbnail($source, $destination, array $crop, array $params);
$crop = array(1, 50, 20, 30);
$params = array('#FFFAAA', 85, true);
createThumbnail($source, $destination, array $crop, array $params);
Наконец-то они одумались! Нужна не строгая проверка на тип, а приведение.У меня несколько иное мнение на этот счет. Можете почитать эту ветку комментов, например. А если коротко — то в современных фреймворках объект, инкапсулирующий запрос, имеет методы для получения ключей с приведеднием к заданному типу. Поэтому строгая типизация, без приведения, лучше, чем приведение «без потерь», так как разработчик всегда знает, какой тип нужно ожидать в том или ином ключе, а строгая типизация делает валидацию неизбежной.
Итого: если вы пользовались тем, что вы описали — то для вас с появлением хинтов ничего не меняется. А если вы не пользовались этим всем — то введение хинтов на скаляры добавит головной боли.
Foo::bar сойдет, указание на класс же есть.#include<stdint.h>// 4
#include<stdio.h>/* 76. 1
..2321 1 57 3
21.... . .. .11 1 2
1 88..1321 2 33 5512 1 277 14 1
099..12.... . .. .... 1 4 11111...111 122 5.1 .
11...221.821112411123455676489 51.176543232666 902 .27 1
10111...1.....................11.417...........1...21..11.
..2239921176566156225563322299887...6533233233182469196894
22...............................111......................
*/// 3269548556987776665556662131223412347543332334543322223456
/*
13.3.37 */char C[120] [60 ];int R[120][60],W,H,J,K,B[61][61],/*
12.2.39 */r,i,j,c,*q =& H,t=7200,x,y,k;int64_t*U,T[28800],*S=/*
11.2.40 */T,O[120], Z[ 120],v,z;void D(){for(k=-1;7200>++k;S[/*
10.39 */k]=v)r=! ~(v=U[k])&&*R[k/60]?2:S[k]-v?1:r;;;;}/*
9.36 */void L( ){for(r=1;r==1;){r=3;;for(i=0;120>/*
9.31 */i;i++){ for(k=z=1,j=0;v=R[i][j];j++)O/*
8.3.32 */[i]|=( 1LL <<v)-1<<k,k+=v,0,Z[i]=z|=1LL<</*
7.3.30 */k++;; v=~ (3LL<<k-2);for(j=-61;++j<60;/*
5.3.29 */v=( v|~ z)&(j<0?v>>1:v<<1|1))v=S[60/*
3.1.3.1.28 */* i +(j < 0?~j:j)]|=j?v:~3;}for(z=0;/*
1.2.4.31 ; */ 7200 >z;z++)i=z/60,j=z%60,(B[i<60?/*
7.5.31 */i:j][ i<60? j:i-60]=~S[z]&O[i]?~S[z]&Z[i]/*
1.6.5.30 ; */?r=0 :(U=O ,1):(U=Z,2))?k=i<60?j+60:j,S/*
5.10.12.16 */[i% 60+60*k]|= ~U[k]:0;U=S; S-=t*=-1;D();z/*
5.11.5.4.12.4 */*9; }}int main( ){for (;K= scanf("%d",R [*/*
15.2.4.4.11.5 */q+c*60]+j)<1? q= &W,j --,2 >++c:'\n';j =-K/*
16.3.4.2.2.5.5 */+getchar()?j+1 :++ *q*0 ); L( );;if (!r/*
14.8.7.3 */)for(K=0;K<W *60;K++) if(K%60 </*
12.1.4.1.6.2 */W&!B[K/60] [ K%60 ] ){for( /*
11.3.4.6.1 */c=64;c--; )if (!(1 &S[K/* ;
10.1.8.8.5.1 */]>>c))U= S ,000,S+= J=14400, D()/* ;
9.8.11.5 */,S[K]=~ (1LL<<c) ,L(),S-=J,S [K]/*
9.5.6.1.2.4.1 */|=r==2? 1LL<< c:0;L( ) ;} q=/* ;
9.3.5.1.5 */&K;;for (J= K=i=0 ; 120/*
3.2.6.5.1 */> i; Z[i]=k --,/* ;
2.6.3.5.1 */ i>59?q =&J :0,/* ;
2.1.2.6.3.6.1 */ * q< k?*q=k :0, 0,C[/* ;
2.1.2.2.1.5.2.5.1 */ i ++ ][ k ]=' ' ){ j=k/* ;
2.1.2.5.5.6.3 */ = 0; for(; x=R[i ][j++] ;/*
4.1.9.7.5.1 */0) k +=sprintf ((00,C[ i]+/* ;
5.19.6.1.2 */k), "%d.",x);}i=~J;;r&1 ||puts ( /*
24.6.3.3 */r?"invalid":"failed"); for(;i <H; i/*
24.1.2.9.7.4 */++,puts(""))for(j=~K;j < W; )putchar( i<0?j<0 ||/*
25.1.2.25 */(k=i+Z[j+60])<0?' ':C[j + 60 ][k]:j<00?(k=j+Z[i])<0?/*
28.1.26 */' ':C[i][k]:"?X "[B[i][j]] ) ,j++;return 0;} /* 2012 */
from($categories)
->orderBy(function ($cat) { return $cat['name']; })
->groupJoin(
from($products)
->where(function ($prod) { return $prod["quantity"] > 0; })
->orderByDescending(function ($prod) { return $prod["quantity"]; })
->thenBy(function ($prod) { return $prod["name"]; }),
function ($cat) { return $cat["id"]; },
function ($prod) { return $prod["catId"]; },
function ($cat, $prods) { return array("name" => $cat["name"], "products" => $prods); }
);
from($categories)
->orderBy($cat ==> $cat['name'])
->groupJoin(
from($products)
->where($prod ==> $prod["quantity"] > 0)
->orderByDescending($prod ==> $prod["quantity"])
->thenBy($prod ==> $prod["name"]),
$cat ==> $cat["id"],
$prod ==> $prod["catId"],
($cat, $prods) ==> array("name" => $cat["name"], "products" => $prods)
);
function some($param1, $param2, $param3)
{
echo $param1.' '.$param2.' '.$param3;
}
$params = array(1,2,3);
some(*$params); // 1 2 3
// Сейчас вместо этого приходится писать call_user_func_array, а в случае с конструктором вообще использовать Reflection
PHP 5.5 больше не поддерживает Windows XP и 2003. Этим системам около десяти лет, поэтому PHP отказалось от них.Я очень глубоко скорблю.
$total = $price1 + 2*$price2
$total->getValue();
$total->getValueWithTaxes();
min($price1, $price2)
round($price)
FooBar::class). Ведь есть же уже константа __CLASS__, которая делает ровно то же самое, только доступная изнутри класса. Почему бы не сделать её доступной и снаружи: FooBar::__CLASS__. array_columnS() для этой цели могла бы быть полезна. Исключаемые столбцы можно было бы передавать в неё же третьим параметром:array_columns($array, ['cols', 'to', 'keep'], ['cols', 'to', 'remove']);
null. Впрочем, для удаления столбцов, пожалуй, действительно целесообразнее отдельная функция типа array_columns_remove() или array_columns_exclude(). Либо в функции array_columns() третий параметр сделать булевым переключателем: если true, то функциональность инвертируется, и указанные во втором параметре столбцы не сохраняются, а удаляются.array_column() была бы полезна функция для преобразования списка массивов в массив, где в качестве ключа использовалось бы значение указанного столбца. Примерно так:function array_column_to_key($input, $keyCol, $valueCol = null) {
$output = array();
if (null === $valueCol) {
foreach ($input as $row) {
$output[$row[$keyCol]] = $row;
}
}
else {
foreach ($input as $row) {
$output[$row[$keyCol]] = $row[$valueCol];
}
}
return $output;
}
[
[
'id' => 3,
'name' => 'lorem'
],
[
'id' => 5,
'name' => 'ipsum'
]
]
[
3 => ['name' => 'lorem'],
5 => ['name' => 'ipsum']
]
[
3 => 'lorem',
5 => 'ipsum'
]
$b = array_combine(array_column($a, 'id'), array_column($a, 'name'));array_column() (имя столбца-ключа указывается в третьем необязательном параметре).
Как может выглядеть PHP 5.5