Search in a container of objects with PHP - php

I have a container with some methods like add, get, and search, and within that class I have a variable that is an array holding instances of Car. How to make that object searchable by its name?
For example:
class Container {
private $cars = [];
public function __construct(array $cars = [])
{
$this->cars = $cars;
}
public function add($key, Car $car)
{
$this->cars[$key] = $car;
}
public function get($key)
{
return $this->cars[$key];
}
public function search($car)
{
// ...
}
};
class Car {
private $name;
public function __construct($name = null)
{
$this->name = $name;
}
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}

You'd need some sort of iterative search like a foreach() or array_filter().
For example:
public function search($car)
{
$matches = array();
foreach ($this->cars as $car) {
if ($car->getName() === $car) {
$matches[] = $car;
}
}
return $matches;
}
Or
public function search($car)
{
return array_filter($this->cars, function ($v) use ($car) {
return $v->getName() === $car;
});
}

Related

How to make Laravel Nova like Fields

I wanna create class for making fields, but in Laravel Nova this classes called like Text::make()->placeholder() and etc. This means that methods inside that class is static.
This is my field class:
class Field
{
private $field = [];
public function set($key, $value)
{
$this->field[$key] = $value;
}
public function get()
{
return $this->field;
}
}
class Text
{
private static $field;
public static function make($name)
{
self::$field = new Field;
self::$field->set('#saturn_type', 'string');
self::$field->set('#saturn_key', $name);
self::$field->set('#saturn_field', 'text');
return new Text;
}
public function placeholder($value)
{
self::$field->set('placeholder', $value);
return $this;
}
public function required()
{
self::$field->set('required', true);
return $this;
}
public function translate()
{
self::$field->set('translate', true);
return $this;
}
public function wysiwyg()
{
self::$field->set('wysiwyg', true);
return $this;
}
public function get()
{
return (array) self::$field->get();
}
}
and this is how i call it:
$fields = [
Text::make('name')->placeholder('Full Name'),
Text::make('email')->placeholder('Email'),
Text::make('password')->placeholder('Password'),
]
$lastArray = $fields->map(function ($field) {
return $field->get();
}
);
But when i call get() method for each item in this array to get array, each item returns the last item's name and placeholder because it is static. How can i solve this.
I found the solution. Actually my friend Nijat found ))
class Field
{
private $field = [];
public function set($key, $value)
{
$this->field[$key] = $value;
}
public function get()
{
return $this->field;
}
}
class Text
{
private $field;
public function __construct($name)
{
$this->field = new Field;
$this->field->set('#saturn_type', 'string');
$this->field->set('#saturn_key', $name);
$this->field->set('#saturn_field', 'text');
}
public static function make($name)
{
return new Text($name);
}
public function placeholder($value)
{
$this->field->set('placeholder', $value);
return $this;
}
public function required()
{
$this->field->set('required', true);
return $this;
}
public function translate()
{
$this->field->set('translate', true);
return $this;
}
public function wysiwyg()
{
$this->field->set('wysiwyg', true);
return $this;
}
public function get()
{
return (array) $this->field->get();
}
}
You just have to create constructor then call it in static method.
You can make Text inherit from Field and have a much simpler make method:
class Field
{
public static function make(...$arguments)
{
return new static(...$arguments);
}
// ...
}
This will instantiate the parent class (e.g. Text) and return it, allowing you to keep the chaining. In the methods you can then use $this-> as usual (instead of self::). And move the content of Text::make to the constructor:
class Text extends Field
{
public function __construct($name)
{
$this->set('#saturn_type', 'string');
$this->set('#saturn_key', $name);
$this->set('#saturn_field', 'text');
}
// ...
}

convert object of class into string

class Person
{
protected $name;
public function __construct($name)
{
$this->name = $name;
}
}
class Business
{
protected $staff;
public function __construct(Staff $staff)
{
$this->staff = $staff;
}
public function hire(Person $person)
{
$this->staff->add($person);
}
public function getStaffMembers()
{
return $this->staff->members();
}
}
class Staff //staff é uma coleção, logo os membros são um array
{
protected $members = [];
public function __construct($members = [])
{
$this->members = $members;
}
public function add(Person $person)
{
$this->members[] = $person;
}
public function members()
{
return $this->members;
}
}
$daniel = new Person('Daniel Santos'); //name==$daniel santos
$staff = new Staff([$daniel]);
$laracasts = new Business($staff);
$laracasts->hire(new Person("Jorge"));
var_dump($laracasts->getStaffMembers());
I would like to print(implode("",$laracasts->getStaffMembers()); instead of just var_dump() it. Thanks.
Add a __toString "magic method" to your Person class.
class Person
{
protected $name;
public function __construct($name)
{
$this->name = $name;
}
public function __toString()
{
return $this->name;
}
}
__toString provides a string representation of the class, so you can use it in string contexts, like echo $person, or echo implode(', ', $laracasts->getStaffMembers());
In this example I just returned the person's name, but you can do more complex stuff in that method as well (formatting, etc.), as long as it returns a string.

Managing collection of items through adding/removing

I want have an in-memory data structure to be able to add or remove an item (in this instance a student) into some sort of table (just like a shopping cart) from the collection class I have created. At the moment, it just displays students. For instance, if I click add student, it will pop up below, and I can delete this student from below also.
How I could implement this?
Here is my Member.php class
<?php
class Member {
private $name;
private $age;
private $gender;
private $course;
public function __construct($name,$age, $gender, $course){
$this->name = $name;
$this->age = $age;
$this->gender = $gender;
$this->course = $course;
}
public function setName($name) { //Sets the age value
$this->name = $name;
}
public function setAge($age) { //Sets the age value
$this->age = $age;
}
public function setGender($gender) { //Sets the gender value
$this->gender = $gender;
}
public function setCourse ($course) {
$this->course = $course;
}
public function getName() { //Gets the name value
return $this->name;
}
public function getAge() { //Gets the age value
return $this->age;
}
public function getGender() { //Gets the gender value
return $this->gender;
}
public function getCourse() {
return $this->course;
}
}
?>
Here is my ObjectCollection.php
<?php
class ObjectCollection
{
//This is an array to hold line items
private $items_array ;
private $itemCounter; //Count the number of items
public function __construct() {
//Create an array object to hold line items
$this->items_array = array();
$this->itemCounter=0;
}
public function getItemCount(){
return $this->itemCounter;
}
public function addItem($item) {
$this->itemCounter++;
$this->items_array[] = $item;
}
public function getItem($index) {
return $this->items_array[$index];
}
}
?>
And finally displaying this through testcollection.php
<?php
$ObjColl = new ObjectCollection();
$member1 = new Member("Jessica Davidson", 21, "Female", "Computing");
$ObjColl->addItem($member1);
$member2 = new Member("Lucy Barnes", 22, "Female", "History");
$ObjColl->addItem($member2);
$member3 = new Member("Mark Smith", 24, "Male", "Social Science");
$ObjColl->addItem($member3);
for($i = 0;$i < $ObjColl->getItemCount();$i++){
$item = $ObjColl->getItem($i);
if ($item instanceof Member) {
print "<br> University Member: ";
}
print "Name: " . $item->getName();
print ". Age: " . $item->getAge();
print ". Gender: " . $item->getGender();
print ". Enrolled on: " .$item->getCourse() . " course<br>";
}
?>
At first if your ObjectCollection must collect only objects of Member class, use parameter type declaration. It’s good practice in OOP.
public function addItem(Member $item)
At second if you want work with ObjectCollection like with array, implement ArrayAccess and Iterator interfaces.
Example
<?php
class Member{
private $__name;
public function __construct($name){
$this->__name = $name;
}
public function getName(){
return $this->__name;
}
}
class MemberCollection implements ArrayAccess, Iterator{
private $__Collection = [];
private $__position = 0;
public function __construct(){
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->__Collection[] = $value;
} else {
$this->__Collection[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->__Collection[$offset]);
}
public function offsetUnset($offset) {
unset($this->__Collection[$offset]);
}
public function offsetGet($offset) {
return isset($this->__Collection[$offset]) ? $this->__Collection[$offset] : null;
}
function rewind() {
$this->__position = 0;
}
function current() {
return $this->__Collection[$this->__position];
}
function key() {
return $this->__position;
}
function next() {
++$this->__position;
}
function valid() {
return isset($this->__Collection[$this->__position]);
}
public function addItem(Member $Member){
$this->offsetSet(null, $Member);
}
}
$MC = new MemberCollection();
$Member1 = new Member('Name 1');
$Member2 = new Member('Name 2');
$MC->addItem($Member1);
$MC->addItem($Member2);
foreach ($MC as $Member){
echo '<br>' . $MC->key() . ':<br>';
var_dump($Member->getName());
}
unset($MC[0]); //Delete member from collection
?>

PHP implements ArrayAccess

I have two Classes viz foo & Bar
class bar extends foo
{
public $element = null;
public function __construct()
{
}
}
and the Class foo goes as
class foo implements ArrayAccess
{
private $data = [];
private $elementId = null;
public function __call($functionName, $arguments)
{
if ($this->elementId !== null) {
echo "Function $functionName called with arguments " . print_r($arguments, true);
}
return true;
}
public function __construct($id = null)
{
$this->elementId = $id;
}
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->data[] = $value;
} else {
$this->data[$offset] = $value;
}
}
public function offsetExists($offset)
{
return isset($this->data[$offset]);
}
public function offsetUnset($offset)
{
if ($this->offsetExists($offset)) {
unset($this->data[$offset]);
}
}
public function offsetGet($offset)
{
if (!$this->offsetExists($offset)) {
$this->$offset = new foo($offset);
}
}
}
i want that when i run the below piece of code:
$a = new bar();
$a['saysomething']->sayHello('Hello Said!');
should return Function sayHello Called with arguments Hello Said! from foo's __call magic method.
Here, i want to say is saysomething should be passed in $this->elementId from foo's __construct function and sayHello should be taken as method and Hello Said should be taken as parameters for sayHello Function which would be rendered from __call magic method.
Also, need to chain methods like:
$a['saysomething']->sayHello('Hello Said!')->sayBye('Good Bye!');
If I'm not mistaken, you should change foo::offsetGet() to this:
public function offsetGet($offset)
{
if (!$this->offsetExists($offset)) {
return new self($this->elementId);
} else {
return $this->data[$offset];
}
}
It returns an instance of itself if there's no element at the given offset.
That said, foo::__construct() should be called from bar::__construct() as well and be passed a value other than null:
class bar extends foo
{
public $element = null;
public function __construct()
{
parent::__construct(42);
}
}
Update
To chain calls, you need to return the instance from __call():
public function __call($functionName, $arguments)
{
if ($this->elementId !== null) {
echo "Function $functionName called with arguments " . print_r($arguments, true);
}
return $this;
}

How perform USort() on an Array of Objects class definition as a method?

class Contact{
public $name;
public $bgcolor;
public $lgcolor;
public $email;
public $element;
public function __construct($name, $bgcolor, $lgcolor, $email, $element)
{
$this->name = $name;
$this->bgcolor = $bgcolor;
$this->lgcolor = $lgcolor;
$this->email = $email;
$this->element = $element;
}
public static function sortByName(Contact $p1, Contact $p2)
{
return strcmp($p1->name, $p2->name);
}
}
class ContactList implements Iterator, ArrayAccess
{
protected $_label;
protected $_contacts = array();
public function __construct($label)
{
$this->_label = $label;
}
public function getLabel()
{
return $this->_label;
}
public function addContact(Contact $contact)
{
$this->_contacts[] = $contact;
}
public function current()
{
return current($this->_contacts);
}
public function key()
{
return key($this->_contacts);
}
public function next()
{
return next($this->_contacts);
}
public function rewind()
{
return reset($this->_contacts);
}
public function valid()
{
return current($this->_contacts);
}
public function offsetGet($offset)
{
return $this->_contacts[$offset];
}
public function offsetSet($offset, $data)
{
if (!$data instanceof Contact)
throw new InvalidArgumentException('Only Contact objects allowed in a ContactList');
if ($offset == '')
{
$this->_contacts[] = $data;
} else
{
$this->_contacts[$offset] = $data;
}
}
public function offsetUnset($offset)
{
unset($this->_contacts[$offset]);
}
public function offsetExists($offset) {
return isset($this->_contacts[$offset]);
}
public function sort($attribute = 'name')
{
$sortFct = 'sortBy' . ucfirst(strtolower($attribute));
if (!in_array($sortFct, get_class_methods('Contact')))
{
throw new Exception('contact->sort(): Can\'t sort by ' . $attribute);
}
usort($this->contact, 'ContactList::' . $sortFct);
}
}
public function Sort($property, $asc=true)
{
// this is where sorting logic takes place
$_pd = $this->_contact->getProperty($property);
if ($_pd == null)
{
user_error('Property '.$property.' does not exist in class '.$this->_contact->getName(), E_WARNING);
return;
}
// set sortDescriptor
ContactList::$sortProperty = $_pd;
// and apply sorting
usort($this->_array, array('ContactList', ($asc?'USortAsc':'USortDesc')));
}
function getItems(){
return $this->_array;
}
class SortableItem extends ContactList
{
static public $sortProperty;
static function USortAsc($a, $b)
{
/*#var $_pd ReflectionProperty*/
/*
$_pd = self::$sortProperty;
if ($_pd !== null)
{
if ($_pd->getValue($a) === $_pd->getValue($b))
return 0;
else
return (($_pd->getValue($a) < $_pd->getValue($b))?-1:1);
}
return 0;
}
static function USortDesc($a, $b)
{
return -(self::USortAsc($a,$b));
}
}
This approach keeps giving me PHP Warnings: usort() [function.usort]: of all kinds which I can provide later as needed to comment out those methods and definitions in order to test and fix some minor bugs of our program.
**$billy parameters are already defined.
$all -> addContact($billy);
// --> ended up adding each contact manually above
$all->Sort('name',true);
$items = $all->getItems();
foreach($items as $contact)
{
echo $contact->__toString();
}
$all->sort();
The reason for using usort is to re-arrange the order alphabetically by name but somehow is either stating that the function comparison needs to be an array or another errors which obviously I have seemed to pass. Any help would be greatly appreciated, thanks in advance.
It's happening because the variable inside the usort call is not a valid array. You use $this->_contacts everywhere, but your usort line is:
usort($this->contact, 'ContactList::' . $sortFct);
Try changing that to:
usort($this->_contacts, 'ContactList::' . $sortFct);
<?php
class Contact{
public $name;
public $bgcolor;
public $lgcolor;
public $email;
public $element;
public function __construct($name, $bgcolor, $lgcolor, $email, $element)
{
$this->name = $name;
$this->bgcolor = $bgcolor;
$this->lgcolor = $lgcolor;
$this->email = $email;
$this->element = $element;
}
}
class ContactList implements Iterator, ArrayAccess
{
public $_label;
public $_contacts = array();
public function __construct($label)
{
$this->_label = $label;
}
public function getLabel()
{
return $this->_label;
}
public function addContact(Contact $contact)
{
$this->_contacts[] = $contact;
}
public function current()
{
return current($this->_contacts);
}
public function key()
{
return key($this->_contacts);
}
public function next()
{
return next($this->_contacts);
}
public function rewind()
{
return reset($this->_contacts);
}
public function valid()
{
return current($this->_contacts);
}
public function offsetGet($offset)
{
return $this->_contacts[$offset];
}
public function offsetSet($offset, $data)
{
if (!$data instanceof Contact)
throw new InvalidArgumentException('Only Contact objects allowed in a ContactList');
if ($offset == '')
{
$this->_contacts[] = $data;
} else
{
$this->_contacts[$offset] = $data;
}
}
public function offsetUnset($offset)
{
unset($this->_contacts[$offset]);
}
public function offsetExists($offset) {
return isset($this->_contacts[$offset]);
}
/* This is the comparing function to be used with usort to make it alphabetically ordered for All Contacts */
public function sort_by($field, &$arr, $sorting='SORT_DSC', $case_insensitive=true){
if(is_array($arr) && (count($arr)>0) && ( ( is_array($arr[0]) && isset($arr[0][$field]) ) || ( is_object($arr[0]) && isset($arr[0]->$field) ) ) ){
if($case_insensitive==true) $strcmp_fn = "strnatcasecmp";
else $strcmp_fn = "strnatcmp";
if($sorting=='SORT_DSC'){
$fn = create_function('$a,$b', '
if(is_object($a) && is_object($b)){
return '.$strcmp_fn.'($a->'.$field.', $b->'.$field.');
}else if(is_array($a) && is_array($b)){
return '.$strcmp_fn.'($a["'.$field.'"], $b["'.$field.'"]);
}else return 0;
');
}else if($sorting=='SORT_ASC'){
$fn = create_function('$a,$b', '
if(is_object($a) && is_object($b)){
return '.$strcmp_fn.'($b->'.$field.', $a->'.$field.');
}else if(is_array($a) && is_array($b)){
return '.$strcmp_fn.'($b["'.$field.'"], $a["'.$field.'"]);
}else return 0;
');
}
usort($arr, $fn);
return true;
}else{
return false;
}
}
}
?
The call:
$all->sort_by('name',$all->_contacts,'SORT_DSC','false');

Categories