I'm picking up a bit to create a method for database as shown in the example below:
$db = new Query();
$db->select('field')
->from('table')
->where('condition')
->etc. etc.
Ie a method with another to return a complete sql (SELECT FROM table WHERE condition fields etc etc).
My question is: How to create a class?
Grateful.
Basically you just return $this at the end of each method you want to be chain-able.
Using your sample API, the implementation would look something like this:
<?php
class Query {
public function select($arg) {
// do stuff
return $this;
}
public function from($arg) {
// do stuff
return $this;
}
public function where($arg) {
// do stuff
return $this;
}
}
Related
I need to create a function of this type, I do not know how it is done and I would like to learn
the function adds to the database, and receives some parameters
event($user)->balande(2.00)->points(300);
example https://github.com/spatie/laravel-activitylog
activity('default')
->performedOn($anEloquentModel)
->causedBy($user)
->withProperties(['customProperty' => 'customValue'])
->log('Look, I logged something');
It's actually quite simple : the first function returns an object instance, and subsequent method calls are applied to this instance (they all return $this, allowing you to chain other method calls afterwards). Have a look at https://en.wikipedia.org/wiki/Fluent_interface
<?php
class Thing{
public function doThat(){
// [do something interesting in this object]
return $this;
}
public function doSomethingElse(){
// [do something interesting in this object]
return $this;
}
}
function Something(){
return new Thing();
}
Something()->doThat()->doSomethingElse();
I'm self-studying the PHP language. And I'm focused on the latest PHP OOP language.
I search for some "ready-to-install" PHP software and as I scan for some references to search and know, I saw lines of code with a structure like this (can't remember so I'll create my own):
$myapp->settings->getValue('openforum');
$myapp->settings->setValue('closeformaintenance', '1');
So my question is, how can I reproduce the code above? I don't know what term to use that line of code (objects, I guess?).
Something like this:
$newLogin->search($uid)->setLogin($dateToday);
Like that. I really need to do that way so I can organize my coding structure. Thanks by the way.
And also for the final question, IS THAT POSSIBLE?
Here's a fairly straight forward way of looking at it, using dependency injection.
Try it out: https://3v4l.org/iSJgL
Note, the below requires PHP 7 due to the string type hint. Remove that and I believe it should work in 5.6 just fine.
<?php
$myapp = new MyApp(new SettingsBag([
'works' => false,
'random' => rand(),
]));
var_dump($myapp->settings()->get('random'));
var_dump($myapp->settings()->get('works'));
// Let's change it up...
$myapp->settings()->set('works', true);
// Now it should be true.
var_dump($myapp->settings()->get('works'));
These would normally have namespaces like \App and/or \App\Configuration, but I ignore that here so it's easier to follow:
class MyApp {
private $settings_bag = null;
function __construct(SettingsBag $settings_bag)
{
$this->settings_bag = $settings_bag;
}
public function settings()
{
return $this->settings_bag;
}
}
class SettingsBag {
private $settings = null;
function __construct(array $settings = [])
{
$this->settings = $settings;
}
public function set(string $key, $value)
{
return $this->settings[$key] = $value;
}
public function get(string $key)
{
return $this->settings[$key];
}
}
What you try to achieve is called method chaining. You can get this by the following:
<?php
class TestClass {
private $val = '';
public function test1($val) {
$this->val = $val;
return $this;
}
public function test2() {
echo 'Hello '.$this->val;
}
}
$test->test1('World')->test2(); // Hello World
You have simply to return the instance of the object on the method to allow the method chaining.
You can read more here.
It's method chaining.
See code below:
class T {
public function test() {
// do something
return $this;
}
}
$x = new T;
$x->test()->test();
I'm wanting to chain a method with the parent function of itself.
Example:
class Query
{
protected $limit;
/**
* Returns some third object that isn't in this family.
* This object represents the results, and also has
* a first function that gets called in a chain.
*/
public function get()
{
// Do Stuff
return new /* ... */;
}
public function take($amount)
{
$this->limit = $amount;
return $this;
}
}
class ChildQuery extends Query
{
protected $singular = false;
public function get()
{
if($this->singular)
return $this->take(1)->parent::get()->first();
return parent::get()
}
public function singular()
{
$this->singular = true;
return $this;
}
}
This obviously isn't the full set of functions, nor does it work, but you get the idea. I'd like ChildQuery::get to be able to call Query::get in a chain.
Right now, I have to do this:
public function get()
{
$this->take(1);
parent::get()->first();
}
Which is not appealing to me. Any ideas?
I'm running PHP 7, if it matters.
My end result would look something like this:
$query->singular()->get(); // ($query is a ChildQuery)
It is just not possible to call a parent method by the public interface of an object (even if it is the same class/object like the current context). Please have also a look at https://stackoverflow.com/a/11828729/2833639.
In my opinion your solution is the right way to go.
Off Topic: I recommend to read https://ocramius.github.io/blog/fluent-interfaces-are-evil/ to evaluate whether a fluid interface is good for your use case.
I'm new in PHP OOP. I need some help for how to write the php OOP class then can call the class like below.
Query->table('user')->column('id','name')->where('name LIKE ?',
["name"=> 'John'])->orderby('name', 'desc');
But, I had try so many time, what I can get it something like below then stop.
Query->table('user')->column('id','name');
I'm running out of ideas and I had google a lot, but fail to find any solution.
Any suitable help is very much appreciated.
You just need to return on each function of class object itself using $this. All functions that you want to run "in chain" should be public. Check this code:
<?php
class ClassName
{
public function a()
{
// ...
return $this;
}
public function b($param)
{
// ...
return $this;
}
public function c()
{
// ...
return $this;
}
}
// testing
$obj = new ClassName;
$result = $obj->a()->b('someParam')->c();
You should read about method chaining.
I'm trying to learn OOP with PHP. I have a website for a magazine and I've created a class called Magazine with some properties. When loading the page a cover image or a specific article should be loaded, the second variant when a user has selected a year and an issue from two select elements. The second select element is dependent on the first - not all years have the same number of issues. So the correct number of options for the second select element should be generated by the PHP code as well (I don't want to use only JavaScript for this).
Here's the basic code:
class Magazine {
public $contents;
public $cover;
public $currentArticle;
public function __construct($year,$issue) {
$this->contents = ...;
...
}
}
$magazine = new Magazine(...);
And now the question: Where should I create the select elements?
1) In a class of its own?
2) In the Magazine class, maybe through a helper method?
3) In the main code where I create instances of the classes?
Method number one (1a) could perhaps look something like this:
class Magazine {
public $contents;
public $cover;
public $currentArticle;
public function __construct($year,$issue) {
$this->contents = ...;
...
}
}
class SelectMagazine {
public $year;
public $issue;
public function __construct($year,$issue) {
$this->year = ...;
...
}
}
$magazine = new Magazine();
$selectMagazine = new SelectMagazine();
Overkill?
Or I could pass the select element through the Magazine class, but that seems rather pointless since they don't really belong there (1b):
class Magazine {
public $contents;
public $cover;
public $currentArticle;
public function __construct($year,$issue) {
$this->contents = ...;
...
$selectMagazine = new SelectMagazine();
$this->year = $selectMagazine->year;
...
}
}
class SelectMagazine {
public $year;
public $issue;
public function __construct($year,$issue) {
$this->year = ...;
...
}
}
$magazine = new Magazine();
Method number two has the same problem as 1b – the select elements aren't really properties of (an instance of) the Magazine (object), if the objects are supposed to mirror the real world.
Method number 3 - underkill?
You might want to do something like that (not sure about the syntax, I don't really know PHP :))
<?
interface SelectHelper {
function getSelect()
{
}
}
class YearsSelectHelper extends SelectHelper {
public function __construct() {
self->magazines = Database::getMagazineList(); // or something
}
public function getSelect()
{
$select = '';
// Construct the select with the years
// You probably want to use private functions to construct
// the select element.
...
return $select;
}
}
class IssuesSelectHelper extends SelectHelper {
public function __construct($year) {
self->year = $year;
// Get the magazine corresponding to that year
}
public function getSelect()
{
// Same thing as in the other class
}
}
In your view, you instanciate the YearsSelectHelper, and then call getSelect to generate the select element. When the user selects a year, you make an AJAX call to an exposed PHP web service that returns your second select, with the year parameter as AJAX data.