8 заметок с тегом

PHP

Правильный LAMP на archlinux

Актуально на апрель 2016. Версия apache, php, mysql:

$ httpd -v
Server version: Apache/2.4.20 (Unix)
Server built:   Apr 11 2016 10:04:04

$ php -v
PHP 7.0.5 (cli) (built: Apr  2 2016 23:10:23) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies

$ mysql -V
mysql  Ver 15.1 Distrib 10.1.13-MariaDB, for Linux (x86_64) using readline 5.1


Я не буду подробно акцентироват внимание на конфигурировании, лишь общие настройки.
Для начала следует обновить все пакеты

sudo pacman -Syu

Ставим всё необходимое, а именно apache, php, mysql, openssl (если необходим доступ по https) и т. д.

sudo pacman -S apache php php-apache mysql openssl

Если mysql не стоял ранее:

sudo systemctl start mysqld
sudo mysql_secure_installation

Можно попробовать проверить работоспособность сервера базы

mysql -u root -p



Мне нравится способ конфигурирования apache в ubuntu, поэтому переделаем настройки на убунтуподобность)
Открываем httpd.conf

sudo nano /etc/httpd/conf/httpd.conf

и в конец файла добавляем:

IncludeOptional conf/sites-enabled/*.conf
IncludeOptional conf/mods-enabled/*.conf

Это позволит подхватывать все конфиги из {sites, mods}-enabled директорий.


Теперь создадим указанные каталоги:

sudo mkdir /etc/httpd/conf/{sites-available,sites-enabled,mods-available,mods-enabled}

Для включения/выключения сайтов создадим скрипт.
Я не стал брать скрипты из ubuntu из-за их монстроузости, вместо этого в интернете нашёл вполне подходящие для наших целей.

Первый скрипт. «Включает» выбранный конфиг сайта.

sudo nano /usr/sbin/a2ensite
#!/bin/bash
if test -d /etc/httpd/conf/sites-available && test -d /etc/httpd/conf/sites-enabled  ; then
echo "-------------------------------"
else
echo "Error!! Folders /etc/httpd/conf/sites-available & etc/httpd/conf/sites-enabled not found."
exit 0
fi

avail=/etc/httpd/conf/sites-available/$1.conf
enabled=/etc/httpd/conf/sites-enabled
site=`ls /etc/httpd/conf/sites-available/`

if [ "$#" != "1" ]; then
        echo "Use script: a2ensite site_config"
        echo -e "\nAvailable virtual hosts:\n$site"
        exit 0
else
if test -e $avail; then
sudo ln -s $avail $enabled
else
echo -e "$avail virtual host does not exist! Please create one!\n$site"
exit 0
fi
if test -e $enabled/$1.conf; then
echo "Success!! Now restart Apache server: sudo systemctl restart httpd"
else
echo  -e "Virtual host $avail does not exist!\nPlease see avail virtual hosts:\n$site"
exit 0
fi
fi

Делаем скрипт выполняемым.

sudo chmod +x /usr/sbin/a2ensite



Второй скрипт. «Выключает» выбранный конфиг сайта.

sudo nano /usr/sbin/a2dissite
#!/bin/bash
if test -d /etc/httpd/conf/sites-available && test -d /etc/httpd/conf/sites-enabled  ; then
echo "-------------------------------"
else
echo "Error!! Folders /etc/httpd/conf/sites-available & etc/httpd/conf/sites-enabled not found."
exit 0
fi

avail=/etc/httpd/conf/sites-enabled/$1.conf
enabled=/etc/httpd/conf/sites-enabled
site=`ls /etc/httpd/conf/sites-enabled`

if [ "$#" != "1" ]; then
        echo "Use script: a2dissite site_config"
        echo -e "\nEnabled virtual hosts: \n$site"
        exit 0
else
if test -e $avail; then
sudo rm  $avail
else
echo -e "$avail virtual host does not exist! Exiting"
exit 0
fi
if test -e $enabled/$1.conf; then
echo "Error!! Could not remove $avail virtual host!"
else
echo  -e "Success! $avail has been removed!\nsudo systemctl restart httpd"
exit 0
fi
fi

Делаем скрипт выполняемым.

sudo chmod +x /usr/sbin/a2dissite


Теперь создадим скрипты включения/отключения модулей

sudo nano /usr/sbin/a2enmod
#!/bin/bash
if test -d /etc/httpd/conf/mods-available && test -d /etc/httpd/conf/mods-enabled  ; then
echo "-------------------------------"
else
echo "Error!! Folders /etc/httpd/conf/mods-available & etc/httpd/conf/mods-enabled not found."
exit 0
fi

avail=/etc/httpd/conf/mods-available/$1.conf
enabled=/etc/httpd/conf/mods-enabled
mods=`ls /etc/httpd/conf/mods-available/`

if [ "$#" != "1" ]; then
        echo "Use script: a2enmod mod_name"
        echo -e "\nAvailable mods config:\n$mods"
        exit 0
else
if test -e $avail; then
sudo ln -s $avail $enabled
else
echo -e "$avail mod not exist! Please create one!\n$mods"
exit 0
fi
if test -e $enabled/$1.conf; then
echo "Success!! Now restart Apache server: sudo systemctl restart httpd"
else
echo  -e "Mod $avail does not exist!\nPlease see avail mods:\n$mods"
exit 0
fi
fi

Делаем скрипт выполняемым.

sudo chmod +x /usr/sbin/a2enmod



И второй скрипт (ну или 4 =) )

sudo nano /usr/sbin/a2dismod
#!/bin/bash
if test -d /etc/httpd/conf/mods-available && test -d /etc/httpd/conf/mods-enabled  ; then
echo "-------------------------------"
else
echo "Error!! Folders /etc/httpd/conf/mods-available & etc/httpd/conf/mods-enabled not found."
exit 0
fi

avail=/etc/httpd/conf/mods-enabled/$1.conf
enabled=/etc/httpd/conf/mods-enabled
mods=`ls /etc/httpd/conf/mods-enabled`

if [ "$#" != "1" ]; then
        echo "Use script: a2dismod mod_config"
        echo -e "\nEnabled mods: \n$mods"
        exit 0
else
if test -e $avail; then
sudo rm  $avail
else
echo -e "$avail mod does not exist! Exiting"
exit 0
fi
if test -e $enabled/$1.conf; then
echo "Error!! Could not remove $avail mod!"
else
echo  -e "Success! $avail has been removed!\nsudo systemctl restart httpd"
exit 0
fi
fi

Делаем скрипт выполняемым.

sudo chmod +x /usr/sbin/a2dismod


Создаём виртуальный хост

sudo nano /etc/httpd/conf/sites-available/localhost.conf

Пример конфигурации:

<VirtualHost *:80>
    DocumentRoot "/mnt/srv/www/localhost/public"
    <Directory "/mnt/srv/www/localhost/public">
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    ServerName localhost
    ErrorLog "/mnt/srv/www/logs/localhost.error.log"
    CustomLog "/mnt/srv/www/logs/localhost.access.log" combined
</VirtualHost>

Теперь его можно включить

sudo a2ensite localhost
$ sudo a2ensite localhost
-------------------------------
Success!! Now restart Apache server: sudo systemctl restart httpd

и добавить в /ets/hosts адрес если это требуется, попробовать запустить/перезапустить apache (как подсказывает скрипт)


Я попробовал перезапустить apache, и на данном этапе у меня всё работает.
Нужно уже браться за мод ssl. Но сначала напишем скрипт создания сертификатов, и создадим их.

sudo nano /usr/sbin/agenssl
#!/bin/bash
if test -d /etc/httpd/conf/ssl ; then
echo "..."
else
echo "make dir..."
mkdir /etc/httpd/conf/ssl
fi

cd /etc/httpd/conf/ssl

echo -e "Enter your virtual host FQDN"
read cert

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out $cert.key
chmod 600 $cert.key
openssl req -new -key $cert.key -out $cert.csr
openssl x509 -req -days 365 -in $cert.csr -signkey $cert.key -out $cert.crt

echo -e " The certificate "$cert" has been generated!\nPlease link it to Apache SSL available website!"

ls -all /etc/httpd/conf/ssl
exit 0

Сделаем скрипт выполняемым

sudo chmod +x /usr/sbin/agenssl



Можно смело запускать. Из обязательного нужно заполнить «Common Name (e. g. server FQDN or YOUR name) []», указав в качестве имени адрес сайта.

sudo agenssl
$ sudo agenssl
...
Enter your virtual host FQDN
localhost
.....................+++
..............................................................................+++
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:RU
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Signature ok
subject=/C=RU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=localhost
Getting Private key
The certificate localhost has been generated!

Please link it to Apache SSL available website!
drwxr-xr-x 2 root root 4096 апр 19 23:43 .
drwxr-xr-x 8 root root 4096 апр 19 21:27 ..
-rw-r--r-- 1 root root 1164 апр 19 23:43 localhost.crt
-rw-r--r-- 1 root root  985 апр 19 23:43 localhost.csr
-rw------- 1 root root 1704 апр 19 23:42 localhost.key


Мод ssl

sudo nano /etc/httpd/conf/mods-enabled/ssl.conf
LoadModule ssl_module modules/mod_ssl.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
Listen 443
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
SSLPassPhraseDialog  builtin
SSLSessionCache        "shmcb:/run/httpd/ssl_scache(512000)"
SSLSessionCacheTimeout  300

Включаем его

sudo a2enmod ssl
$ sudo a2enmod ssl
-------------------------------
Success!! Now restart Apache server: sudo systemctl restart httpd



Попробуем добавить конфигурацию виртуального хоста с ssl

sudo nano /etc/httpd/conf/sites-available/localhost-ssl.conf
<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    ServerName localhost
    DocumentRoot /mnt/srv/www/localhost/public

    LogLevel info ssl:warn

    <Directory "/mnt/srv/www/localhost/public">
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog "/mnt/srv/logs//localhost.error.log"
    CustomLog "/mnt/srv/logs/localhost.access.log" combined

    SSLEngine on
    SSLCertificateFile      /etc/httpd/conf/ssl/localhost.crt
    SSLCertificateKeyFile   /etc/httpd/conf/ssl/localhost.key

    <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
    </FilesMatch>

    BrowserMatch "MSIE [2-6]" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0

    BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>

Перезапускаем apach и пробуем наш https

sudo systemctl restart httpd

Справочник по методам коллекции Laravel



Изначально данный материал планировался как мини статья о методах коллекций, но потом всё скатилось в банальный перевод оригинальной документации.

Статья в разработке. Осталось дописать несколько методов и навигацию ;)



Как создать коллекцию из массива?
Очень просто:

// Допустим у нас есть такой массив
$myArray = [
    'one' => 'first',
    'two' => 'second',
    'three' => 'the third'
];

// Создаём коллекцию
$collection = collect($myArray);



Методы для работы с коллекциями



all() Возвращает базовый массив коллекции
avg() Среднее значение всех элементов коллекции
chank() Разбить коллекцию на множество мелкий коллекций





Метод all
Метод all() вернёт базовый массив коллекции

$myArray = [
    'one' => 'first',
    'two' => 'second',
    'three' => 'the third'
];

$collection = collect($myArray);
$collection->all();

// Результат
array:3 [▼
    "one" => "first"
    "two" => "second"
    "three" => "the third"
]



Метод avg
Посчитать среднее значение всех элементов коллекции

$collection = collect([0, 10]);
dd($collection->avg());

//Результат
5

Если коллекция содержит вложенные массивы или объекты, то вам необходимо передать ключ по которому будет считаться среднее значение

$myArray = [
    ['name' => 'one', 'amount' => '10'],
    ['name' => 'two', 'amount'=> '2']
];
$collection = collect($myArray);

dd($collection->avg('amount'));

//Результат
6



Метод chank
Разобьёт коллекцию на множество мелкий коллекций

$myArray = [
    'one' => 'first',
    'two' => 'second',
    'three' => 'the third'
];

$collection = collect($myArray);
dd($collection->chunk(2) );

// Результат
Collection {#17 ▼
  #items: array:2 [▼
    0 => Collection {#15 ▼
      #items: array:2 [▼
        "one" => "first"
        "two" => "second"
      ]
    }
    1 => Collection {#16 ▼
      #items: array:1 [▼
        "three" => "the third"
      ]
    }
  ]
}



Метод collapse
Позволяет собрать одну коллекцию из множества коллекций

$myArray = [
    [
        'one' => 'first',
        'two' => 'second',
    ],
    [
        'three' => 'the third'
    ]
];
$collection = collect($myArray);

dd( $collection->collapse() );

// Результат
Collection {#15 ▼
  #items: array:3 [▼
    "one" => "first"
    "two" => "second"
    "three" => "the third"
  ]
}



Метод contains
Проверяет, содержит ли коллекция нужное значение. Проверка осуществляется по значениям ключей.

$myArray = [
    'one' => 'first',
    'two' => 'second',
    'three' => 'the third'
];

$collection = collect($myArray);

dump( $collection->contains('first') ); // true
dump( $collection->contains('one') ); // false

// Результат
true
false



Метод count
count позволяет сосчитать количество элементов коллекции

$collection = collect([1, 2, 3]);
dd( $collection->count() );

// Результат
3



Метод diff
Метод diff сравнивает коллекцию с другой коллекцией или массивом

$collection = collect([1, 2, 3, 4, 5]);
$diff = $collection->diff([2, 4, 6, 8]);
dd( $diff->all());

//Результат
array:3 [▼
  0 => 1
  2 => 3
  4 => 5
]



Метод each
Что бы перебрать каждый элемент коллекции воспользуетесь методом each

$myArray = [
    'one' => 'first',
    'two' => 'second',
    'three' => 'the third'
];

$collection = collect($myArray);
$collection->each(function ($item, $key) {
    dump($item . ' -> ' . $key);
});

// Результат
"first -> one"
"second -> two"
"the third -> three"



Метод every
А что бы создать новую коллекцию содержащую только каждый N элемент начиная с первого — every

$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);

dd( $collection->every(4));

// Результат
Collection {#15 ▼
  #items: array:2 [▼
    0 => "a"
    1 => "e"
  ]
}

Вторым аргументом можно указать смещение

$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);

dd($collection->every(4, 1));

// Результат
Collection {#15 ▼
  #items: array:2 [▼
    0 => "b"
    1 => "f"
  ]
}



Метод except
Исключить из коллекции элементы можно с помощью метода except

$myArray = [
    'one' => 'first',
    'two' => 'second',
    'three' => 'the third'
];
$collection = collect($myArray);

dd($collection->except('two'));

// Результат
Collection {#15 ▼
  #items: array:2 [▼
    "one" => "first"
    "three" => "the third"
  ]
}



Метод filter
Метод фильтрует коллекцию с помощью функции колбэка сохраняя лишь те элементы при обработке которых колбэк вернул true

$collection = collect([1, 2, 3, 4]);

$filtered = $collection->filter(function ($value, $key) {
    return $value > 2;
});

dd($filtered);

// Результат
Collection {#16 ▼
  #items: array:2 [▼
    2 => 3
    3 => 4
  ]
}



Метод first
Работает так же как и filter, только возвращает первый элемент при обработке которого колбэк вернул true

$collection = collect([1, 2, 3, 4]);

$filtered = $collection->first(function ($key, $value) {
    return $value > 2;
});

dd($filtered);

// Результат
3
Обратите внимание, что первый аргумент функции колбэка (в отличии от колбэка filter) является ’ключ’, второй ’значение’. У фильтра наоборот.



Метод flatten
Данный метод сделает плоским многомерную коллекцию

$myArray = [
    [
        'one' => 'first',
        'two' => [
            'second', 'the third'
        ]
    ]
];
$collection = collect($myArray);

$flattened = $collection->flatten();
dd( $flattened );

// Результат
Collection {#15 ▼
  #items: array:3 [▼
    0 => "first"
    1 => "second"
    2 => "the third"
  ]
}



Метод flip
Поменяет местами ключи и значения в коллеции

$myArray = [
    'one' => 'first',
    'two' => 'second'
];
$collection = collect($myArray);

dd( $collection->flip());

// Результат
Collection {#15 ▼
  #items: array:2 [▼
    "first" => "one"
    "second" => "two"
  ]
}



Метод forget
Удалить элемент из коллекции по ключу можно с помощью данного метода

$myArray = [
    'one' => 'first',
    'two' => 'second'
];
$collection = collect($myArray);

$collection->forget('one');

dd($collection);

// Результат
Collection {#14 ▼
  #items: array:1 [▼
    "two" => "second"
  ]
}
Обратите внимание, что данный метод, в отличии от большинства, не создаёт новую коллекцию, а изменяет базовую.



Метод forPage
Создаёт новую коллекцию в которой будут присутствовать элементы заданной страницы. Метод первым аргументом принимает номер страницы, вторым количество элементов на ней.

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);

dump($collection->forPage(2, 3));
dump($collection->forPage(3, 3));

// Результат
Collection {#15 ▼
  #items: array:3 [▼
    3 => 4
    4 => 5
    5 => 6
  ]
}
Collection {#15 ▼
  #items: array:3 [▼
    6 => 7
    7 => 8
    8 => 9
  ]
}



Метод get
Данный метод возвращает значение по ключу. Если ключа не существует, то будет возвращён null либо значение по умолчанию

$myArray = [
    'one' => 'first',
    'two' => 'second'
];
$collection = collect($myArray);

dd($collection->get('one'));

// Результат
"first"

Для установки значения по умолчанию передайте необходимое значение вторым аргументом.

$myArray = [
    'one' => 'first',
    'two' => 'second'
];
$collection = collect($myArray);

dd($collection->get('three', 'nothing'));

// Результат
"nothing"

Вы так же можете указать в качестве второго аргумента колбэк функцию, результат работы которой будет возвращён, в случае если значение не найдено.

$myArray = [
    'one' => 'first',
    'two' => 'second'
];
$collection = collect($myArray);

$get = $collection->get('three', function () {
    return 'result';
});

dd($get);

// Результат
"result"



Метод groupBy
Группирует элементы коллекции по ключу

$collection = collect([
    ['user' => 'one',   'action' => 'buy'],
    ['user' => 'one',   'action' => 'pay'],
    ['user' => 'two',   'action' => 'pay'],
    ['user' => 'three', 'action' => 'buy'],
    ['user' => 'three', 'action' => 'buy'],
]);

$grouped = $collection->groupBy('action');

dd($grouped);

// Результат
Collection {#18 ▼
  #items: array:2 [▼
    "buy" => Collection {#16 ▼
      #items: array:3 [▼
        0 => array:2 [▼
          "user" => "one"
          "action" => "buy"
        ]
        1 => array:2 [▼
          "user" => "three"
          "action" => "buy"
        ]
        2 => array:2 [▼
          "user" => "three"
          "action" => "buy"
        ]
      ]
    }
    "pay" => Collection {#17 ▼
      #items: array:2 [▼
        0 => array:2 [▼
          "user" => "one"
          "action" => "pay"
        ]
        1 => array:2 [▼
          "user" => "two"
          "action" => "pay"
        ]
      ]
    }
  ]
}



Метод has
Проверяет существование ключа

$collection = collect(['one' => 1, 'two' => 2]);

dump($collection->has('one')); // true
dump($collection->has('ololo')); // false

// Результат
true
false



Метод implode
Объединяет элементы коллекции. Передаваемые в метод аргументы зависят от типа коллекции.
Если коллекция объект или массив, то первый аргумент должен указывать на ключ, второй — строка с помощью которой будет произведена склейка.

$collection = collect([
    ['user' => 'one',   'action' => 'buy'],
    ['user' => 'one',   'action' => 'pay'],
    ['user' => 'two',   'action' => 'pay'],
    ['user' => 'three', 'action' => 'buy'],
    ['user' => 'three', 'action' => 'buy'],
]);

dd($collection->implode('action', ', '));

// Результат
"buy, pay, pay, buy, buy"

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

dd(collect([1, 2, 3, 4, 5])->implode('-'));

// Результат
"1-2-3-4-5"



Метод intersect
Метод удаляет любые пересекающиеся значения, которые не присутствуют в данном массиве или коллекции:

$collection = collect(['one', 'two', 'three']);

dd($collection->intersect(['one', 'three', 'hmm']));

// Результат
Collection {#15 ▼
  #items: array:2 [▼
    0 => "one"
    2 => "three"
  ]
}



Метод isEmpty
Пуста ли коллекция.

dump(collect([])->isEmpty()); // true
dump(collect([1, 2, 3, 4, 5])->isEmpty()); // false

// Результат
true
false



Метод keyBy
Устанавливает в качестве ключа элемента коллекции выбранное значение ключа
(не знаю как лучше описать, смотрите пример =) )

$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'desk'],
    ['product_id' => 'prod-200', 'name' => 'chair'],
]);

dd ($collection->keyBy('product_id'));

// Результат
Collection {#16 ▼
  #items: array:2 [▼
    "prod-100" => array:2 [▼
      "product_id" => "prod-100"
      "name" => "desk"
    ]
    "prod-200" => array:2 [▼
      "product_id" => "prod-200"
      "name" => "chair"
    ]
  ]
}



Метод keys
Метод возвращает все ключи коллекции

$collection = collect([
    'first' => ['product_id' => 'prod-100', 'name' => 'Desk'],
    'second' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

dd($collection->keys());

// Результат
Collection {#15 ▼
  #items: array:2 [▼
    0 => "first"
    1 => "second"
  ]
}



Метод last
Возвращает последний элемент коллекции при обработке которого колбек вернул истину (true)
(Данный метод обратный методу first)

$collection = collect([1, 2, 3, 4]);

$last = $collection->last(function ($key, $value) {
    return $value > 2;
});

dd($last);

// Результат
4



Метод map
Метод map передаёт в функцию колбека каждый элемент и создаёт новую коллекцию обработанную этим колбеком.

$collection = collect([1, 2, 3, 4, 5]);

$map = $collection->map(function ($item, $key) {
    return $item * 2;
});

dd($map);

// Результат
Collection {#16 ▼
  #items: array:5 [▼
    0 => 2
    1 => 4
    2 => 6
    3 => 8
    4 => 10
  ]
}



Метод max
Возвращает максимальное значение в коллекции

dump(collect([['foo' => 10], ['foo' => 20]])->max('foo')); // 20
dump(collect([1, 2, 3, 4, 5])->max()); // 5

// Результат
20
5



Метод merge
Производит слияние массива с коллекцией, перезаписывая при этом одноимённые ключи. Цифровые ключи добавляются в конец коллекции.

$collection = collect(['product_id' => 1, 'name' => 'Desk']);

dd($collection->merge(['price' => 100, 'discount' => false]));

// Результат
Collection {#15 ▼
  #items: array:4 [▼
    "product_id" => 1
    "name" => "Desk"
    "price" => 100
    "discount" => false
  ]
}



Метод min
Возвращает минимальное значение в коллекции

dump(collect([['foo' => 10], ['foo' => 20]])->min('foo')); // 10
dump(collect([1, 2, 3, 4, 5])->min()); // 1

// Результат
10
1



Метод only
Метод возвращает только указанные элементы.
(Работает только с «простыми» коллекциями)

$collection = collect(['name' => 'one', 'amount' => 10, 'price'  => 5]);

dd( $collection->only(['amount', 'price']) );

// Результат
Collection {#15 ▼
  #items: array:2 [▼
    "amount" => 10
    "price" => 5
  ]
}



Метод pluck
Возвращает все значения ключей коллекции по указанному ключу

$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
    ['product_id' => 'prod-300', 'name' => 'Chair'],
]);

dd($collection->pluck('name'));

// Результат
Collection {#15 ▼
  #items: array:3 [▼
    0 => "Desk"
    1 => "Chair"
    2 => "Chair"
  ]
}

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

$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
    ['product_id' => 'prod-300', 'name' => 'Chair'],
]);

dd($collection->pluck('name', 'product_id'));

// Результат
Collection {#15 ▼
  #items: array:3 [▼
    "prod-100" => "Desk"
    "prod-200" => "Chair"
    "prod-300" => "Chair"
  ]
}



Метод pop
Метод удаляет и возвращает (проще говоря вытаскивает) последний элемент коллекции. Данный метод изменяет оригинальную коллекцию.

$collection = collect([1, 2, 3, 4, 5]);

dump($collection->pop()); // возвращает 5 и удаляет этот элемент из коллекции

dump($collection->all());

// Результат
5

array:4 [▼
  0 => 1
  1 => 2
  2 => 3
  3 => 4
]



Метод prepend
Добавляет элемент в начало коллекции. Данный метод изменяет оригинальную коллекцию.

$collection = collect([1, 2, 3, 4, 5]);

$collection->prepend(5); 

dump($collection->all());

// Результат
array:6 [▼
  0 => 5
  1 => 1
  2 => 2
  3 => 3
  4 => 4
  5 => 5
]

Второй переданный аргумент задаст имя нового ключа

$collection = collect([1, 2, 3, 4, 5]);

$collection->prepend(5, 'five'); 

dump($collection->all());

// Результат
array:6 [▼
  "five" => 5
  0 => 1
  1 => 2
  2 => 3
  3 => 4
  4 => 5
]



Метод pull
Метод извлекает из коллекции произвольный элемент по ключу. Данный метод изменяет оригинальную коллекцию.

$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']);

dump($collection->pull('name')); // "Desk"

dump($collection->all());

// Результат
 "Desk"

array:1 [▼
  "product_id" => "prod-100"
]



Метод push
Добавляет элемент в конец коллекции. Данный метод изменяет оригинальную коллекцию.

$collection = collect([1, 2, 3, 4]);

dump($collection->push(5));

dd($collection->all());

Результат

Collection {#14 ▼
  #items: array:5 [▼
    0 => 1
    1 => 2
    2 => 3
    3 => 4
    4 => 5
  ]
}

array:5 [▼
  0 => 1
  1 => 2
  2 => 3
  3 => 4
  4 => 5
]



Метод put
Устанавливает заданный ключ и значение в коллекции. Данный метод изменяет оригинальную коллекцию.

$collection = collect(['product_id' => 1, 'name' => 'Desk']);

dd($collection->put('price', 100));

// Результат
Collection {#14 ▼
  #items: array:3 [▼
    "product_id" => 1
    "name" => "Desk"
    "price" => 100
  ]
}



Метод random
Возвращает случайный элемент из коллекции

$collection = collect([1, 2, 3, 4, 5]);

dd($collection->random());

// Результат (Конечно же будет разный)
5



Метод reduce



Метод reject



Метод reverse



Метод search



Метод shift



Метод shuffle



Метод slice



Метод sort



Метод sortBy сортирует коллекцию по указанному ключу

$collection = collect([
    ['name' => 'Desk', 'price' => 200],
    ['name' => 'Chair', 'price' => 100],
    ['name' => 'Bookcase', 'price' => 150],
]);

$sorted = $collection->sortBy('price');

$sorted->values()->all();

/*
    [
        ['name' => 'Chair', 'price' => 100],
        ['name' => 'Bookcase', 'price' => 150],
        ['name' => 'Desk', 'price' => 200],
    ]
*/

Сортируемая коллекция сохраняет оригинальные ключи массива.
Вы можете использовать Callback для указания как сортировать

$collection = collect([
    ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
    ['name' => 'Chair', 'colors' => ['Black']],
    ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);

$sorted = $collection->sortBy(function ($product, $key) {
    return count($product['colors']);
});

$sorted->values()->all();

/*
    [
        ['name' => 'Chair', 'colors' => ['Black']],
        ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
        ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
    ]
*/



Метод sortByDesc



Метод splice



Метод sum



Метод take



Метод toArray



Метод toJson



Метод transform



Метод unique



Метод values



Метод where



Метод whereLoose



Метод whereIn



Метод whereInLoose



Метод zip

Массовое обновление данных в бд на laravel/lumen (innoDB)

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

// Получаем данные, к примеру из базы
$data = DB::table('users')->get();
$counter = 0;
foreach($data as $value){
    // Если счётчик в 0, то стартуем транзакцию
    if($counter == 0)
        DB::beginTransaction();
    }
    $counter++;

    // Выполняем какие-то действия
    $type = $value->type === 2?5:1;

    // Обновляем данные
    DB::table('users')->where('id', $value->id)->update(array('type' => $type));

    // Счётчик достиг нужного порога - коммитим изменения в DB
    if($counter >= 999){
        DB::commit();
        $counter = 0;
    }
}

// Снова коммит для оставшихся
DB::commit();

Таким способом обновление данных займёт гораздо меньше времени.

2016   innoDB   laravel   lumen   mysql   PHP   Транзакции

Как подружить monolog с redis в lumen

В принципе ничего сложного нет. Данная мини статья рассчитана на начинающих в PHP. Суть статьи больше в том, что бы показать, как переопределять методы.

Итак, понадобилось нам писать логи в redis, с чего начать? А начнём мы с того, что заглянем в папочку /vendor/laravel/lumen-framework/src/ в файл Application.php.

/**
* Register container bindings for the application.
*
* @return void
*/
protected function registerLogBindings()
{
    $this->singleton('Psr\Log\LoggerInterface', function () {
        return new Logger('lumen', [$this->getMonologHandler()]);
    });
}

/**
* Get the Monolog handler for the application.
*
* @return \Monolog\Handler\AbstractHandler
*/
protected function getMonologHandler()
{
    return (new StreamHandler(storage_path('logs/lumen.log'), Logger::DEBUG))
                        ->setFormatter(new LineFormatter(null, null, true, true));
}

В файле видим метод registerLogBindings который в свою очередь вызывает getMonologHandler, он то нам и нужен.

Что ж, для начала наследуем класс Application. Я обычно размещаю такие классы в директории /app/Classes/

<?php

/**
 * Файл Application.php
 */

namespace app\Classes;

// Наследовать будем конечно же от \Laravel\Lumen\Application
class Application extends \Laravel\Lumen\Application {

    }

}

Теперь переопределим метод getMonologHandler

<?php

namespace app\Classes;

// Импортируем необходимые пространства имён
use Monolog\Logger;
use Monolog\Handler\RedisHandler;
use Monolog\Formatter\JsonFormatter;

// Наследовать будем конечно же от \Laravel\Lumen\Application
class Application extends \Laravel\Lumen\Application {

    /**
     * Get the Monolog handler for the application.
     *
     * @return \Monolog\Handler\AbstractHandler
     */
    protected function getMonologHandler() {

        // Создадим экземпляр класса Predis
        $redis = new \Predis\Client("tcp://localhost:6379");
        
        // Добавим дефолтное имя ключа, по которому будут писаться наши логи
        // Для удобства, дадим возможность изменять это значение в файле .env
        $key = env('MONOLOG_REDIS_KEY', 'logs');

        return (new RedisHandler($redis, $key, Logger::DEBUG));

    }

}

Осталось только подменить наш класс в файле /bootstrap/app.php

<?php
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| Here we will load the environment and create the application instance
| that serves as the central piece of this framework. We'll use this
| application as an "IoC" container and router for this 
|
*/

// Закомментируем либо удалим
//$app = new Laravel\Lumen\Application(
//	realpath(__DIR__.'/../')
//);

$app = new App\Classes\Application(
	realpath(__DIR__.'/../')
);

Если оставить сейчас всё как есть, то в redis будут писаться строковые значения. Но нам не составит труда писать это к примеру в формате json.

return (new RedisHandler($redis, $key, Logger::DEBUG))->setFormatter(new JsonFormatter());

Что почитать?

Классы и Объекты. Основы.
Пространства имён
Так же смотрите и разбирайте исходники lumen

2015   framework   laravel   lumen   PHP   Redis

Трюки с коллекциями в laravel.

Коллекции бывают очень полезными но о них часто забывают. В этой статье я дам несколько советов по их применению.

Вольный перевод. Оригинальная статья http://codebyjeff.com/blog/2015/05/stupid-collection-tricks-in-laravel

Внимание: Это не страница «лучшей практики», я всего лишь дам несколько советов которые могут быть полезны в нужном месте кода.

Начнём с того, что создадим таблицу `people` и пустой класс Eloquent модели с именем Person:

CREATE TABLE `people` (
        `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
        `first_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
        `last_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
        `type` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
        PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `people` (`id`, `first_name`, `last_name`, `type`) VALUES
        (1, 'Jeff', 'Madsen', 'programmer'),
        (2, 'Mickey', 'Mouse', 'engineer'),
        (3, 'Daffy', 'Duck', 'critic'),
        (4, 'Mighty', 'Mouse', 'programmer');

Трюк #1: find()

Что? find? Да я давно всё знаю о нём. Серьёзно? Проверим?

// Возвратит одну строку как Коллекцию
$collection = App\People::find([1]);
dd($collection);
// Возвратит несколько строк как Коллекции
$collection = App\Person::find([1, 2, 3]);
dd($collection);

С помощью коллекций иногда действительно приятней работать, мы всегда знаем, что возвращается коллекция.

Трюк #2: $collection->where()

Сколько запросов к базе данных вы бы произвели, что бы получить в отдельном массиве всех программистов, инженеров и критиков? Хотите сказать три? Да ни за что в жизни! Один!

// Получаем всех
$collection = App\Person::all();

// фильтруем
$programmers =  $collection->where('type', 'programmer');
$critic =  $collection->where('type', 'critic');
$engineer =  $collection->where('type', 'engineer');

dd($engineer);

Трюк #3: where() & lists()

Возвратит массив с именами всех инженеров

Внимание: lists в Laravel 5.2 был переименован в pluck

$collection = App\Person::all();

$engineer =  $collection->where('type', 'engineer')->lists('first_name'); // ->pluck('first_name') для laravel старше  5.1
dd($engineer);

В WP вы вероятно сделали бы что-то вроде этого:

Внимание: следующий код написан по памяти и не проверен

// Получаем все метаданные для пользователя с ID  = 1
$collection = App\WP_Meta::whereUserId(1)->get();

// Мне нужны значения имени и фамилии
$first_name =  $collection->where('meta_key', 'first_name')->lists('value')[0];	
$last_name  =  $collection->where('meta_key', 'last_name')->lists('value')[0];
...любые другие поля, которые вам нужны

Трюк #4: $collection->implode()

Полезный метод (аналогичен php implode), объединит в строку указанный атрибут коллекции с нужным разделителем

$collection = App\Person::all();
$names = $collection->implode('first_name', ',');
echo $names;

Трюк #5: $collection->groupBy()

Мне вас жаль, если вы делали отчёты и не знали этого...

$collection = App\Person::all();
$grouped = $collection->groupBy('type');
dd($grouped);	

// Результат
Collection {#152 ▼
  #items: array:3 [▼
    "programmer" => array:2 [▼
      0 => Person {#166 ▶}
      1 => Person {#169 ▶}
    ]
    "engineer" => array:1 [▼
      0 => Person {#167 ▶}
    ]
    "critic" => array:1 [▼
      0 => Person {#168 ▶}
    ]
  ]
}

Трюк #6: Объединение

Несколько слов о коде. В примере мы будем использовать одну модель, но на самом деле предполагается это использовать для разных моделей .

use Illuminate\Support\Collection;

...

// Задача в том, что бы объединить результат из различных моделей	
$programmers =  \App\Person::where('type', 'programmer')->get();
$critic      =  \App\Person::where('type', 'critic')->get();
$engineer    =  \App\Person::where('type', 'engineer')->get();

$collection  = new Collection;
$all = $collection->merge($programmers)->merge($critic)->merge($engineer);
dd($all);

Теперь предостережения: Будьте осторожны с выбором что делать с результатом. Если вы будете делать циклы при сочетании экземпляров различных классов, то вас могут ожидать сюрпризы, так как некоторые поля данных не всегда могут присутствовать, или могут быть мутаторы в одной из моделей, либо и то и другое вместе. Причём сегодня это может работать нормально, а завтра кто-то придёт и добавит мутатор в модель. По этому прежде всего хорошенько рассчитайте всё.

Надеюсь, что статья Вам помогла!

Laravel 5. Возвращение whoops

В laravel 4 был замечательный обработчик ошибок под названием «whoops», из пятой версии данный обработчик был удалён на менее информативный. Исправить это не составит труда. Но будьте осторожны, никогда не используйте его на продакшене, т. к. это покажет ваши пароли от базы данных, и много чего ещё «полезного».

Без обработчика whoops

whoops




Добавить его очень просто:
Сначала необходимо с помощью composer добавить в зависимости и загрузить whoops

composer require filp/whoops:~1.0.

Привести функцию render в файле

app/Exceptions/Handler.php

вот к такому виду

public function render($request, Exception $e)
    {
        if ($this->isHttpException($e))
        {
            return $this->renderHttpException($e);
        }


        if (config('app.debug'))
        {
            return $this->renderExceptionWithWhoops($e);
        }

        return parent::render($request, $e);
    }

И написать функцию которую мы вызываем в 11 строчке ф-ии render

/**
     * Render an exception using Whoops.
     * 
     * @param  \Exception $e
     * @return \Illuminate\Http\Response
     */
    protected function renderExceptionWithWhoops(Exception $e)
    {
        $whoops = new \Whoops\Run;
        $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler());

        return new \Illuminate\Http\Response(
            $whoops->handleException($e),
            $e->getStatusCode(),
            $e->getHeaders()
        );

Готово. Как видно из кода (config(’app.debug’)), whoops будет отображаться только когда в env включен debug

Количественный анализ слов в книгах Сергея Тармашева серии «Холод»

Сегодня дочитав последнюю строчку книги Сергея Тармашева «Студёное Дыхание» из серии холод, подумал, а почему бы не сделать анализ часто используемых слов из всей серии. Написал небольшой скрипт на PHP в 15 строчек кода и вот результат.

Количество слов (в т.ч. союзов, предлогов и т. д.) в книгах «Неотвратимая Гибель», «Ледяная Бесконечность» и «Студёное Дыхание» приблизительно составило 44501 единицу.

Самый употребляемое слово — союз «И», использовалось 10602 раза. =)

Далее я приведу таблицу топ 50 наиболее употребляемых и «интересных» слов.

Слово Количество
майк 2946
майка 737
нет 455
варвар 395
время 357
батлер 341
мистер 334
головорез 327
майку 322
коэн 321
сэр 292
новой 277
сразу 272
больше 271
вокруг 267
бюро 259
людей 243
вновь 239
снег 228
косматый 216
снега 207
мутантов 199
сани 194
пришлось 190
глаза 189
минус 187
дикарей 184
вертолет 182
америки 180
удалось 178
человек 177
мутанты 177
назад 177
руки 176
дикари 175
слишком 174
заявил 167
место 160
лив 159
люди 155
ноги 154
сторону 153
дальше 152
секунду 152
ведь 151
варвара 149
снаряжение 148
должны 146
взглядом 146
человече 144