我正在努力学习OOP。我正在阅读的书中所谓的“现实世界”例子并没有帮助。
Pet
,Car
,Human
等所有示例都不再帮助我了。我需要真实的生活示例,如注册,用户个人资料页面等。
一个例子:
$user->userName = $_POST['userName'];//save username
$user->password = $_POST['password'];//save password
$user->saveUser();//insert in database
我也看到了:
$user->user = (array) $_POST;
其中:
private $user = array();
保存数组中的所有信息。
在同一个班级里面
$user->getUser($uid);
// which sets the $this->user array equal to mysqli_fetch_assoc() using
//the user id.
在许多不同的php应用程序(注册,登录,用户帐户等)中是否存在实现OOP的真实示例?
答案 0 :(得分:80)
OOP不仅仅是关于单个课程的外观和操作方式。它还涉及一个或多个类的实例如何协同工作。
这就是为什么你看到很多基于“汽车”和“人物”的例子,因为他们确实很好地说明了这个原则。
在我看来,OOP中最重要的经验是封装和多态。
封装:以简洁,合理的方式将数据和作用于该数据的逻辑耦合在一起 多态性:一个对象看起来像和/或表现得像另一个对象的能力。
一个很好的现实世界的例子就像目录迭代器。这个目录在哪里?也许它是一个本地文件夹,也许它像FTP服务器一样远程。谁知道!
这是一个演示封装的基本类树:
<?php
interface DirectoryIteratorInterface
{
/**
* @return \Traversable|array
*/
public function listDirs();
}
abstract class AbstractDirectoryIterator implements DirectoryIteratorInterface
{
protected $root;
public function __construct($root)
{
$this->root = $root;
}
}
class LocalDirectoryIterator extends AbstractDirectoryIterator
{
public function listDirs()
{
// logic to get the current directory nodes and return them
}
}
class FtpDirectoryIterator extends AbstractDirectoryIterator
{
public function listDirs()
{
// logic to get the current directory nodes and return them
}
}
每个类/对象负责检索目录列表的方法。数据(变量)耦合到使用数据的逻辑(类函数,即方法)。
但故事还没有结束 - 还记得我是怎么说OOP是关于类的实例如何协同工作,而不是任何单个类或对象?
好的,让我们对这些数据做些什么 - 将它打印到屏幕上?当然。但是怎么样? HTML?纯文本? RSS?让我们解决这个问题。
<?php
interface DirectoryRendererInterface
{
public function render();
}
abstract class AbstractDirectoryRenderer implements DirectoryRendererInterface
{
protected $iterator;
public function __construct(DirectoryIteratorInterface $iterator)
{
$this->iterator = $iterator;
}
public function render()
{
$dirs = $this->iterator->listDirs();
foreach ($dirs as $dir) {
$this->renderDirectory($dir);
}
}
abstract protected function renderDirectory($directory);
}
class PlainTextDirectoryRenderer extends AbstractDirectoryRenderer
{
protected function renderDirectory($directory)
{
echo $directory, "\n";
}
}
class HtmlDirectoryRenderer extends AbstractDirectoryRenderer
{
protected function renderDirectory($directory)
{
echo $directory, "<br>";
}
}
好的,现在我们有一些用于遍历和呈现目录列表的类树。我们如何使用它们?
// Print a remote directory as HTML
$data = new HtmlDirectoryRenderer(
new FtpDirectoryIterator('ftp://example.com/path')
);
$data->render();
// Print a local directory a plain text
$data = new PlainTextDirectoryRenderer(
new LocalDirectoryIterator('/home/pbailey')
);
$data->render();
现在,我知道你在想什么,“但彼得,我不需要这些大树来做这件事!”但如果你认为那么你就错过了这一点,就像我怀疑你曾经使用过“汽车”和“人物”的例子。不要只关注这个例子的细节 - 而是试着去理解这里发生的事情。
我们创建了两个类树,其中一个(*DirectoryRenderer
)以预期的方式使用另一个(*DirectoryIterator
) - 这通常被称为合同。 *DirectoryRenderer
的实例不关心它接收的*DirectoryIterator
实例类型,*DirectoryIterator
的实例也不关心它们是如何呈现的。
为什么呢?因为我们就是这样设计的。他们只是互相插入并工作。 这是行动中的OOP 。
答案 1 :(得分:9)
购买“PHP和Mysql日常应用程序傻瓜”这样的书。
它的陈旧我知道[2005],但它在过程和面向对象的Mysqli中显示了用户登录,论坛,购物车等的概念。
它帮助我学习面向对象的PHP,我研究了很多。非常物有所值。
OOP非常类似于将程序的各个部分分组为可重复使用的部分。与你说实话并不难,只是将你的功能打包成课程的想法。
以下OOP内容的真实世界迷你示例:
CLASS DATABASE
课堂会议
CLASS WEBFORMS
CLASS EMAIL
CLASS ACCOUNTS(以下示例功能)
功能选择帐户
功能检查密码
功能CHECKUSERNAME
功能创建账号
我希望你坚持下去,PHP 6将重新设计,以支持OOP。
祝你好运!
答案 2 :(得分:2)
虽然我知道这个问题已经得到了解答,但我觉得我可以在这里增加价值。
我不相信你应该使用PHP作为编程语言来学习OOP。如果您希望学习Web应用程序的OOP,您应该真正关注C#或Java。一旦学会了OOP,就可以将这些知识应用到PHP中。我以前学习OOP的一本书的例子是Big Java by Cay S. Horstmann
为什么我这样说?因为在PHP上有数以百万计的关于如何做事的例子,然而没有多少例子是如何正确编程的。除此之外,PHP还允许您使用许多快捷方式,而这些快捷方式对于Java类来说是不可接受的。因此,如果您使用Java头编程PHP,那么我相信您将成为一名更强大的程序员。 OOP不是语言特定的,它是一种编程范式。
如果你必须使用PHP学习OOP,那么我建议你看一下github的公共存储库中的一些真正的源代码。您可以在packagist.org中搜索它们。如果它们是一个不错的公共存储库,它们将包含一个readme.md文件,该文件将向您展示如何使用composer包。例如https://github.com/moltin/laravel-cart是您可以在应用程序中使用的购物车包的示例。请注意您不需要查看包源代码以了解包的功能。这个软件包已经编写好了,你不关心它们是如何工作的,但你使用它们只需要知道如何使用它们。这正是OOP的意思。
我不关心购物车类如何将商品添加到购物车,我只是想创建一个新购物车并添加一些东西。
您正在做的是深入了解源代码,作为了解OOP如何工作的工具。
除此之外,也许更重要的是,对于Web应用程序开发,我会研究MVC设计模式。
MVC设计模式代表模型,视图,控制器。在Web应用程序的情况下,模型负责对数据库建模,视图负责向用户显示内容。控制器负责与模型交互并处理用户输入。
我认为您应该尝试在本地计算机上安装Laravel Framework或其他“体面的现代框架”。为什么我说现代,因为现代框架需要一个5.3+的最小PHP版本,这意味着你的机器上的PHP将支持类似于你从Java那样的实际OOP。
有许多教程将向您展示如何在laravel中构建Web应用程序。您将立即看到,在创建控制器时,您可以扩展BaseController。创建模型时,可以扩展Eloquent。这意味着您已经在代码中使用了Polymorphism。您将看到,通过使用类,它们被封装,您将看到每个类都有特定的角色。
如果要与数据库进行交互,最初将在控制器方法中创建一个new Model
对象。当您开始学习更多内容时,您将开始学习如何将依赖项注入控制器,然后学习如何转储模型并创建存储库并编程到接口。
一本关于为初学者学习Laravel的好书将由Dale Rees https://leanpub.com/codebright。两周前我在Laravel聚会上遇见了Dale。
此外,随着您越来越熟练地构建Web应用程序,您将开始学习如何将以下原则应用于您的编程:
答案 3 :(得分:1)
astropanic说,你可以看看一个好的PHP框架或库的源代码。我推荐Zend Framework,它非常模块化,并且拥有出色的专业设计。我想说这是一个非常好的面向对象的PHP代码。
尽管如此,我认为从大量的生产代码中学习并不容易,因为它并没有真正教会你什么。但是如果你想要真实的面向对象的PHP代码,那么Zend Framework(或Symfony,或者也许是CakePHP)可能就是这样。
答案 4 :(得分:1)
我建议你暂时远离任何框架,如果你不了解OOP,挖掘zend或任何其他框架会太多。
PHP OOP很有趣......就像哈哈搞笑一样,因为它受到支持,但PHP不是像Java或c#这样的OOP语言。
简短的例子只是为了强调我的陈述:
// define class
class User {
// define properties and methods
public $name = "";
}
// instantiate class
$user = new User; // or new User() or new user, it's all the same
echo $user->name;
但如果你想“动态”做OOP,你可以做到以下几点:
$user = (object) array('name' => 'Peter');
然后
$user->name;
但你可以像在java或c#中那样使用OOP,但不能使用相同的扩展 - 并且请记住,像wordpress和drupal这样的流行系统不是纯粹的OOP!但你也可以在PHP中继承和其他分类OOP。
答案 5 :(得分:1)
我在PHP OOP方面并没有走得太远,但是我越是容易进入它就越容易。对象示例可供您了解OOP的工作原理。我之前理解并经历过,OOP只是关于属性和方法(正常变量和函数)。我使用我的教程中的示例自己编写了真正的OOP,并不一定要在现实世界中。这就像勺子喂,你永远不会理解OOP,很容易忘记。我的建议学会了解。如果你明白,你可以做任何事情,并意识到OOP的力量。我下载了这本书,我认为你也应该这样做。但这就像有人为你构建你的应用程序......
Here指向PHP和Mysql日常应用程序傻瓜书的链接
答案 6 :(得分:0)
我建议也看看我的包装Arrayzy。它是OOP方式的本机PHP数组易操作库。
因此,如果您使用本机PHP数组函数 - 您可以在OOP中执行相同的操作,Arrayzy可以帮助您完成它,例如:
// Functional programming:
$array = ['a', 'b', 'c'];
$resultArray = array_merge($array, ['c', 'd']);
和
// Object-oriented programming:
$obj = Arrayzy\MutableArray::create(['a', 'b', 'c']);
$obj->mergeWith(['c', 'd']);
$resultArray = $obj->toArray();
在这两种情况下,结果数组都是:
Array(
0 => 'a'
1 => 'b'
2 => 'c'
3 => 'c'
4 => 'd'
)
检查此mergeWith方法(或其他)如何在幕后工作。
我认为这是一个很好的例子,它表明几乎所有功能代码都可以替换为 OOP 代码,就像在这个库中一样。但是通过OOP,您可以获得更多,还可以查看Functional programming vs OOP问题,了解更多详细信息,以及它的缺点和道具。
答案 7 :(得分:0)
您说得对,您可以在网上找到 99% 的教程都过于基础,而且没有任何意义。我对任何尝试学习面向对象编程的人的建议是:
找到一些您用过程编程编写的代码,并尝试将其转换为 OOP。
获取所有变量并使它们成为类的属性,找到合适的类名。然后把你所有的函数(如果你有函数)放在一个类中。如果您在编写代码时没有使用函数,请首先尝试将您的代码转换为一组函数。找到合适的函数名称,函数应该定义一段代码的作用。一旦你有了你的函数,就把它们移到一个类中。
我会给你一个简单的分页代码示例,我将其转换为可重用的分页类。在 youtube 上找到完整的教程:https://www.youtube.com/watch?v=X38IRlyY_ww&t=91s,源代码链接在说明框中
class Paginator{
/*the class need to know the current page to calculate the offset
the offset tell my sql how many rows to skip */
private $current_page;
//the limit is the number of results to display per page
private $limit;
/*pagination links to display below the results with next
and previous button*/
private $pagination_links;
//the last page of your pagination links
private $last_page;
.
. etc
public function __contruct($number_of_rows_found,$results_to_display_per_page){
//the paginator uses the number_of_rows_found to determine the last page
$this->last_page = $number_of_rows_found/$results_to_display_per_page;
//get the current page, set it to 1 by default
$this->current_page = isset($_GET['page']) ? ($_GET['page'] : 1;
}
public function generate_pagination_links(){
this method uses the last_page property to generate pagination links
if the last page is 3, this will give you 3 pagination links
for ($page = 1; $page <= $this->last_page; $page++) {
//use
}
}
public function get_offset_and_limit(){
//this method calculates the offset based on the current page
return "LIMIT $this->per_page OFFSET ".($this->page - 1) * $this->per_page;
}
.
.
.etc
}
}
然后要使用分页类,您创建它的一个新实例,并传递 每页要显示的结果数,以及返回的结果数 通过您的查询作为参数。分页类将生成分页链接 您并计算偏移量和限制。这是 php 可重用的一个很好的例子 类,您可以在多个项目中使用它,而无需重写或更改它。
$paginator = New Paginator($rows_found,8);
$pagination_links = $paginator->get_pagination_links();
$offset_and_limit = $paginator->get_offset_and_limit();
//apend the limit and offset to your sql query
$query = $query. ' '.$offset_and_limit;
$connection = getdbconnection();
$stmt = $connection->prepare($query);
$stmt->execute();
$movies = $stmt->fetchAll();
当然,OOP 中有更高级的概念没有在这个例子中介绍,但这应该能让你对类和对象的工作方式有一个基本的了解