Непринятая ошибка: вызов функции-члена prepare () на null в & hellip; (PDO) [дубликат]

Не думаю, что высота большого пальца основана на размере содержимого, вы можете изменить ширину внутри ::-webkit-scrollbar, но высота всегда будет основана на содержании.

::-webkit-scrollbar              { /* 1 */ }
::-webkit-scrollbar-button       { /* 2 */ }
::-webkit-scrollbar-track        { /* 3 */ }
::-webkit-scrollbar-track-piece  { /* 4 */ }
::-webkit-scrollbar-thumb        { /* 5 */ }
::-webkit-scrollbar-corner       { /* 6 */ }
::-webkit-resizer                { /* 7 */ }

Источник

160
задан user73119 26 July 2009 в 22:30
поделиться

10 ответов

Это довольно интересный вопрос - и ответы могут быть интересными также ^^

. Самый простой способ рассмотреть вещи может быть:

  • использовать инстанцированный класс, где каждый объект имеет свои собственные данные (например, у пользователя есть имя).
  • использует статический класс, когда это просто инструмент, который работает на других вещах (например, синтаксический преобразователь для BB-кода для HTML , у него нет собственной жизни)

(Да, я признаю, действительно действительно слишком упрощен ...)

. Одна вещь о статических методах / классах заключается в том, что они не облегчают модульное тестирование (по крайней мере, в PHP, но, вероятно, и на других языках).

Другое дело о статических данных состоит в том, что только один экземпляр он существует в вашей программе: если вы установите где-то значение MyClass :: $ myData, оно будет иметь это значение и только оно, где угодно - говоря о пользователе, вы сможете иметь только одного пользователя - что это не так уж и больно?

Для системы блога, что я могу сказать? Не так много, я бы написал как статичный, на самом деле, я думаю; возможно, класс DB-access, но, вероятно, нет, в конце ^^

118
ответ дан Pascal MARTIN 27 August 2018 в 13:01
поделиться
  • 1
    Таким образом, в основном используйте объекты при работе с уникальными вещами, такими как фотография, пользователь, почта и т. Д., И статичны, когда они предназначены для общих вещей? – Robert Rocha 2 April 2016 в 21:29
  • 2
    говоря о пользователе, у вас есть только один активный пользователь по каждому запросу. так что прикосновение активного пользователя к статическому запросу имеет смысл – My1 27 September 2017 в 10:31

Основными двумя причинами против использования статических методов являются:

    код с использованием статических методов трудно проверить
  • код с использованием статических методов трудно расширить

Наличие вызова статического метода внутри какого-либо другого метода на самом деле хуже, чем импорт глобальной переменной. В PHP классы являются глобальными символами, поэтому каждый раз, когда вы вызываете статический метод, вы полагаетесь на глобальный символ (имя класса). Это случай, когда глобальное зло. У меня были проблемы с подобным подходом с некоторыми компонентами Zend Framework. Существуют классы, которые используют статические вызовы (фабрики) для создания объектов. Мне не удалось поставить другую фабрику в этот экземпляр, чтобы вернуть настроенный объект. Решение этой проблемы состоит в том, чтобы использовать только экземпляры и внедрять методы и применять синглтоны и т. Д. В начале программы.

Мишко Хевери , который работает в качестве Agile Coach at Google, имеет интересную теорию или, скорее, советует, что мы должны отделить время создания объекта от времени использования объекта. Таким образом, жизненный цикл программы разделен на две части. Первая часть (например, метод [6]), которая заботится обо всех объектных проводках в вашем приложении и о части, которая выполняет фактическую работу.

Итак, вместо наличия:

class HttpClient
{
    public function request()
    {
        return HttpResponse::build();
    }
}

Мы должны сделать следующее:

class HttpClient
{
    private $httpResponseFactory;

    public function __construct($httpResponseFactory)
    {
        $this->httpResponseFactory = $httpResponseFactory;
    }

    public function request()
    {
        return $this->httpResponseFactory->build();
    }
}

И затем, на странице индекса / главной страницы, мы сделали бы (это шаг проводки объекта или время для создания графика экземпляры, которые будут использоваться программой):

$httpResponseFactory = new HttpResponseFactory;
$httpClient          = new HttpClient($httpResponseFactory);
$httpResponse        = $httpClient->request();

Основная идея состоит в том, чтобы отделить зависимости от ваших классов. Таким образом, код гораздо более расширяемый и, что самое важное для меня, можно проверить. Почему важнее быть проверяемым? Потому что я не всегда пишу библиотечный код, поэтому расширяемость не так важна, но проверяемость важна, когда я делаю рефакторинг. В любом случае, проверяемый код обычно дает расширяемый код, поэтому он не является ни одной из ситуаций.

Miško Hevery также проводит четкое различие между синглтонами и синглтонами (с или без капитала S). Разница очень проста. Синглтоны с нижним регистром «s» выполняются проводкой в ​​индексе / главной. Вы создаете экземпляр объекта класса, который не реализует шаблон Singleton, и следите за тем, чтобы вы передавали этот экземпляр только любому другому экземпляру, который ему нужен. С другой стороны, Синглтон с капиталом «S» является реализацией классического (анти) шаблона. В основном глобальная маскировка, которая мало использует в мире PHP. Я до сих пор не видел этого. Если вы хотите, чтобы одно соединение с БД использовалось всеми вашими классами, лучше сделать это следующим образом:

$db = new DbConnection;

$users    = new UserCollection($db);
$posts    = new PostCollection($db);
$comments = new CommentsCollection($db);

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

/**
 * An example of a test using PHPUnit. The point is to see how easy it is to
 * pass the UserCollection constructor an alternative implementation of
 * DbCollection.
 */
class UserCollection extends PHPUnit_Framework_TestCase
{
    public function testGetAllComments()
    {
        $mockedMethods = array('query');
        $dbMock = $this->getMock('DbConnection', $mockedMethods);
        $dbMock->expects($this->any())
               ->method('query')
               ->will($this->returnValue(array('John', 'George')));

        $userCollection = new UserCollection($dbMock);
        $allUsers       = $userCollection->getAll();

        $this->assertEquals(array('John', 'George'), $allUsers);
    }
}

Единственная ситуация, в которой я буду использовать (и я использовал их для имитации объекта прототипа JavaScript в PHP 5.3). Статические члены - это когда я знаю, что соответствующее поле будет иметь одно и то же значение cross-instance. В этот момент вы можете использовать статическое свойство и, возможно, пару статических методов getter / setter. В любом случае, не забудьте добавить возможность переопределения статического члена членом экземпляра. Например, Zend Framework использует статическое свойство, чтобы указать имя класса адаптера DB, используемого в экземплярах Zend_Db_Table. Прошло некоторое время с тех пор, как я использовал их, поэтому он больше не может быть релевантным, но вот как я его помню.

Статические методы, не относящиеся к статическим свойствам, должны быть функциями. PHP имеет функции, и мы должны их использовать.

67
ответ дан Theodore R. Smith 27 August 2018 в 13:01
поделиться
  • 1
    @Ionut, я не сомневаюсь, что один бит. Я понимаю, что есть ценность в позиции / роли; однако, как и все связанные с XP / Agile, у него действительно популярное имя. – jason 27 July 2009 в 15:39
  • 2
    «Инъекция зависимостей» Я считаю, что это слишком сложное звучание. МНОГО и много чтения по всему миру и Google. Что касается «синглетов», go, вот что действительно заставило меня задуматься: slideshare.net/go_oh/… Разговор о том, почему синглтоны PHP действительно не имеют никакого смысла. Надеюсь, это немного повлияет на старый вопрос :) – dudewad 13 July 2013 в 21:10

Я хотел бы сказать, что определенно есть случай, когда мне нужны статические переменные - в приложениях с несколькими языками. У вас может быть класс, через который вы передаете язык (например, $ _SESSION ['language']), и он, в свою очередь, обращается к другим классам, которые сконструированы так:

Srings.php //The main class to access
StringsENUS.php  //English/US 
StringsESAR.php  //Spanish/Argentina
//...etc

Использование строк :: getString ( «somestring») - отличный способ отвлечь ваше использование языка от вашего приложения. Вы можете сделать это, как вам угодно, но в этом случае, если каждый файл строк имеет константы со строковыми значениями, к которым обращается класс Strings, работает очень хорошо.

3
ответ дан dudewad 27 August 2018 в 13:01
поделиться

«Наличие вызова статического метода внутри какого-либо другого метода на самом деле хуже, чем импорт глобальной переменной». (определить «хуже») ... и «Статические методы, которые не имеют статических свойств, должны быть функциями».

Это оба довольно радикальные утверждения. Если у меня есть набор функций, связанных с предметом, но данные экземпляра совершенно неуместны, я бы скорее их определил в классе, а не в каждом из них в глобальном пространстве имен. Я просто использую механику, доступную в PHP5, чтобы

  • дать им все пространство имен - избегая любых конфликтов имен
  • , чтобы они физически находились вместе, а не разбросаны по проект - другие разработчики могут более легко найти то, что уже доступно, и реже изобретать колесо
  • позволяют мне использовать класс consts вместо глобальных определений для любых магических значений

это всего лишь удобный способ обеспечить более высокую степень сцепления и более низкую связь.

И FWIW - нет такой вещи, по крайней мере в PHP5, как «статические классы»; методы и свойства могут быть статическими. Чтобы предотвратить создание экземпляра класса, можно также объявить его абстрактным.

10
ответ дан grantwparks 27 August 2018 в 13:01
поделиться
  • 1
    «Чтобы предотвратить создание экземпляра класса, можно объявить его абстрактным, также & quot; - Мне это очень нравится. Ранее я читал о том, что люди делают __construct () частной функцией, но я думаю, что если мне когда-нибудь понадобится, я, скорее всего, буду использовать абстрактную – Kavi Siegel 28 October 2014 в 01:34

У меня есть другой подход к большинству ответов здесь, особенно при использовании PHP. Я думаю, что все классы должны быть статическими, если у вас нет веских причин, почему бы и нет. Некоторые из причин «почему нет»:

  • Вам нужно несколько экземпляров класса
  • . Ваш класс должен быть расширен
  • . Части вашего код не может делиться переменными класса с любыми другими частями

Позвольте мне привести один пример. Поскольку каждый скрипт PHP создает HTML-код, в моей структуре есть класс html writer. Это гарантирует, что ни один другой класс не попытается написать HTML, поскольку это специализированная задача, которая должна быть сконцентрирована в одном классе.

Как правило, вы должны использовать класс html следующим образом:

html::set_attribute('class','myclass');
html::tag('div');
$str=html::get_buffer();

Каждый раз, когда вызывается get_buffer (), он сбрасывает все, чтобы запускался следующий класс для использования html-writer в известном состоянии.

Все мои статические классы имеют функцию init (), которую нужно вызвать до того, как класс будет использоваться в первый раз. Это скорее условность, чем необходимость.

Альтернатива статическому классу в этом случае беспорядочна. Вы бы не хотели, чтобы каждый класс должен был написать маленький бит html, чтобы управлять экземпляром html-записи.

Теперь я приведу вам пример того, когда не использовать статические классы. Мой класс формы управляет списком элементов формы, таких как текстовые входы, выпадающие списки и многое другое. Обычно он используется следующим образом:

$form = new form(stuff here);
$form->add(new text(stuff here));
$form->add(new submit(stuff here));
$form->render(); // Creates the entire form using the html class

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

Большинство классов полезности, таких как строки преобразования / форматирования, являются хорошими кандидатами для статического класса. Мое правило прост: все статично в PHP, если нет одной причины, почему это не должно.

9
ответ дан JG Estiot 27 August 2018 в 13:01
поделиться

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

3
ответ дан Michael Aaron Safyan 27 August 2018 в 13:01
поделиться

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

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

И да, это только одна из многих других причин, о которых уже упоминалось.

6
ответ дан Muhammad Hasan Khan 27 August 2018 в 13:01
поделиться

Таким образом, в PHP статические могут быть применены к функциям или переменным. Нестатические переменные привязаны к определенному экземпляру класса. Нестатические методы действуют на экземпляр класса. Итак, создадим класс под названием BlogPost.

title будет нестационарным членом. Он содержит название этого блога. У нас также может быть метод, называемый find_related(). Это не статично, потому что для этого требуется информация из определенного экземпляра класса post post.

Этот класс будет выглядеть примерно так:

class blog_post {
    public $title;
    public $my_dao;

    public function find_related() {
        $this->my_dao->find_all_with_title_words($this->title);
    }
}

С другой стороны, использование статических функций , вы можете написать такой класс:

class blog_post_helper {
    public static function find_related($blog_post) {
         // Do stuff.
    }
}

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

По сути, это вопрос об объектно-ориентированном дизайне. Ваши классы - существительные в вашей системе, а функции, действующие на них, - это глаголы. Статические функции являются процедурными. Вы передаете объект функций в качестве аргументов.


Обновление: я бы также добавил, что решение редко встречается между методами экземпляра и статическими методами, и многое другое между использованием классов и использованием ассоциативных массивов. Например, в приложении для ведения блога вы либо читаете сообщения в блоге из базы данных и преобразуете их в объекты, либо оставляете их в наборе результатов и рассматриваете их как ассоциативные массивы. Затем вы записываете функции, которые принимают ассоциативные массивы или списки ассоциативных массивов в качестве аргументов.

В сценарии OO вы пишете методы в своем классе BlogPost, которые действуют на отдельные сообщения, и вы пишете статические методы, которые действуют на коллекции сообщений.

21
ответ дан Rafe 27 August 2018 в 13:01
поделиться
  • 1
    Этот ответ довольно хорош, особенно с обновлением, которое вы сделали, потому что именно по этой причине я закончил этот вопрос. Я понимаю функциональность & quot; :: & quot; vs & quot; $ this & quot ;, но когда вы добавляете во внимание, пример, который вы указали из блогов, извлекаемых из БД в ассоциативном массиве .. Он добавляет совершенно новое измерение, которое также находится в базовом тональности этого вопроса , – Gerben Jacobs 28 March 2011 в 10:55
  • 2
    Это один из лучших практических (по сравнению с теоретическими) ответов на этот часто задаваемый вопрос PHP, добавление очень полезно. Я думаю, что это ответ, который многие программисты PHP ищут, поддержали! – ajmedway 5 March 2018 в 12:07

Сначала спросите себя, что будет представлять этот объект? Экземпляр объекта хорош для работы с отдельными наборами динамических данных.

Хорошим примером может быть уровень абстракции ORM или базы данных. У вас может быть несколько соединений с базой данных.

$db1 = new Db(array('host' => $host1, 'username' => $username1, 'password' => $password1));
$db2 = new Db(array('host' => $host2, 'username' => $username2, 'password' => $password2));

Эти два соединения теперь могут работать независимо:

$someRecordsFromDb1 = $db1->getRows($selectStatement);
$someRecordsFromDb2 = $db2->getRows($selectStatement);

Теперь в этом пакете / библиотеке могут быть другие классы, такие как Db_Row и т. д., чтобы представить определенную строку, возвращаемую из инструкции SELECT. Если этот класс Db_Row был статическим классом, тогда предполагается, что у вас есть только одна строка данных в одной базе данных, и было бы невозможно сделать то, что мог бы сделать экземпляр объекта. С экземпляром теперь вы можете иметь неограниченное количество строк в неограниченном количестве таблиц в неограниченном количестве баз данных. Единственным ограничением является аппаратное обеспечение сервера;).

Например, если метод getRows объекта Db возвращает массив объектов Db_Row, вы можете теперь работать с каждой строкой независимо друг от друга:

foreach ($someRecordsFromDb1 as $row) {
    // change some values
    $row->someFieldValue = 'I am the value for someFieldValue';
    $row->anotherDbField = 1;

    // now save that record/row
    $row->save();
}

foreach ($someRecordsFromDb2 as $row) {
    // delete a row
    $row->delete();
}

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

В одной части вашего application:

Session::set('someVar', 'toThisValue');

И в другой части:

Session::get('someVar'); // returns 'toThisValue'

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

Надеюсь, это поможет вместе с другими ответами помочь разобраться. В качестве примечания обратите внимание на «сцепление » и « соединение ». Они описывают некоторые очень и очень хорошие практики, которые следует использовать при написании кода, применимого ко всем языкам программирования.

7
ответ дан Tres 27 August 2018 в 13:01
поделиться

Все ли это стиль?

Долгий путь, да. Вы можете писать совершенно хорошие объектно-ориентированные программы, не используя статические элементы. На самом деле некоторые люди утверждают, что статические члены - это, прежде всего, примесь. Я бы предположил, что - как новичок в oop - вы пытаетесь избежать статических членов вместе. Это заставит вас в направлении записи в объектно-ориентированном , а не в процедуре .

14
ответ дан troelskn 27 August 2018 в 13:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: