Соглашения об URL-адресе в рамках PHP - PullRequest
2 голосов
/ 23 июня 2009

Многие фреймворки используют URL-соглашения, такие как /controller/action/{id}, что замечательно, но если вам нужна какая-либо конфигурация, кроме вас, вы сами можете написать свои собственные маршруты.

Как бы вы справились с URL-адресами вроде /users/{id}/friends на сервере? (для просмотра списка всех друзей пользователя)

Я думаю, что в контроллере что-то вроде этого будет уместно:

class User {
    function index() {
        echo 'user index';
    }
}

class Friend extends User {
    function index($user_id) {
        echo 'friend index';
    }    
}

Тогда у вас будет следующая карта:

/users              -> User::index()
/users/{id}         -> User::view($id)
/users/{id}/friends -> Friend::index($user_id)

Я хотел поместить класс Friend в класс User, но, очевидно, вы не можете сделать это в PHP, так что это лучшее, что я могу придумать. Мысли? * * 1013

Какой URL будет использоваться для редактирования вашего списка друзей? /users/{id}/friends/edit может сработать, но это не кажется подходящим, так как вы никогда не должны редактировать чужой список друзей. /account/friends/edit будет лучшим выбором? Где бы вы положили соответствующий код для этого? В контроллере друга, или в контроллере пользователя, или в специализированном контроллере учетных записей?

Бонусный вопрос: что вы предпочитаете? /photos/delete/{id} или /photos/{id}/delete


Ответы:

Итак, что я понял из ответов, так это то, что если «вещь» сложная (например, «друзья»), но не имеет своего собственного контроллера, вы можете дать ему один без модели, или если это не так Вы должны заполнить это тем, с чем это наиболее тесно связано. Ваши URL не должны влиять на то, где вы размещаете свой код. Большинство людей, кажется, думают, что вы должны придерживаться /controller/action/{id}, насколько это возможно, потому что это то, с чем люди знакомы.

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

Спасибо за все ответы:)

Ответы [ 5 ]

2 голосов
/ 23 июня 2009

Вы можете сделать либо или. Проблема в том, когда вы смешиваете два. / users / {id} / friends и / users / friends / {id} Если у кого-то есть идентификатор «friends», это не удастся. Это может показаться тривиальным случаем, но очень популярно использовать имена пользователей для идентификаторов. Вам придется ограничить имена пользователей для каждого действия.


Иногда вы не можете сделать /{controller}/{action}/{id}

Некоторое время назад я создал инди-музыкальный сайт, и мы сделали 1007 *

/artist/{username}
/artist/{username}/albums
/artist/{username}/albums/{album}

Мы не хотели проверять условия, поэтому мы не делали

/artist/{username}/{album}

Так как мы не хотели проверять кого-либо с альбомом под названием "album"

Мы могли бы сделать это

/artist/{username}
/artist/{username}/albums
/albums/{album}

но тогда мы потеряем преимущество SEO, поскольку в URL-адресе были указаны имя исполнителя и название альбома. Также в этом случае мы бы заставляли имена альбомов быть уникальными, что было бы плохо, так как для артиста характерно, чтобы названия альбомов были такими же, как у другого исполнителя.

Вы можете сделать чистый /{controller}/{action}/{id}, но тогда вы потеряете часть SEO и не сможете сократить URL.

/artist/view/{username}
/artist/albums/{username}
/album/view/{album}

Возвращаясь к вашему примеру.

/ users / {id} / friends / edit может работать, но это не кажется уместным, так как Вы никогда не должны редактировать кого-то список других друзей.

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

(Бонусный вопрос) Также я бы использовал REST . DELETE /photo?id={id}

2 голосов
/ 23 июня 2009

Я бы предпочел /photos/{id}/delete. Я рассуждаю так: если вы убираете один компонент с конца URL, это все равно имеет смысл.

Довольно легко предположить, что должен делать /photos/{id}: просмотреть набор фотографий для этого {id}.

Но что должен /photos/delete делать? Это действительно неясно.

Я знаю, что по умолчанию существует соглашение /controller/action/id, но эта организация предназначена для отображения в архитектуру контроллеров класса / метода. Я не думаю, что это хорошая идея, чтобы организовать интерфейс для размещения кода (URL является частью интерфейса).


Комментарии: Да, /photos/{id} возможно, имеет больше смысла просматривать данную фотографию по ее идентификатору. /users/{id}/photos возможно, для просмотра коллекции. Тебе решать.

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

2 голосов
/ 23 июня 2009

Маршруты, о которых вы говорите, и то, как вы используете подклассы для достижения этой структуры, мне немного неловко. Стандартное соглашение /controller/action/{id} отлично подходит для простых действий, но если вы создаете сложное приложение, вам всегда нужно будет создавать собственные маршруты. Вероятно, есть несколько хороших рекомендаций, которые следует использовать при создании этих маршрутов, но на самом деле все сводится к тому, чтобы оставаться единообразным во всем приложении и максимально упростить работу.

Я не вижу веских причин для привязки /user/{id}/friends к контроллеру "Friend". Почему бы просто не «friends» быть действием на User контроллере? После того, как вы перейдете к просмотру страницы конкретного друга, вы можете использовать контроллер Friend (/friends/view/123) или перенастроить свой контроллер User, чтобы он работал для друга или текущего пользователя (* 1011). *).

Re: бонусный вопрос, я бы придерживался /photos/delete/{id} (/controller/action/{id}), так как это наиболее распространенный механизм.

1 голос
/ 23 июня 2009

Сами URL не имеют большого значения. Что важнее, так это то, что входит в каждый из ваших контроллеров. В вашем примере ваш список друзей расширил класс User. Если ваш список друзей - это просто список пользователей, возможно, он должен расширить контроллер Users, чтобы вы могли работать со списками пользователей в одном месте.

class Users {

    public function index() {
        $users = $this->findUsers();
    }

    protected function findUsers($userId=null) { ... }
}

class Friends extends Users {

    public function index($userId) {
        $users = $this->findUsers($userId);
    }
}

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

1 голос
/ 23 июня 2009

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

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

/friends/edit/{friendListId}

Вам решать. Как заявил pix0r: для небольших приложений используется соглашение /{controller}/{action}/{id}, где {id} должен быть необязательным, чтобы соответствовать большинству действий ваших сайтов. В некоторых случаях приложения становятся большими, и вы хотите определить конкретные маршруты с более чем 3 элементами. В некоторых случаях некоторые сущности просто получают большее значение (пример выше), и вы можете решить определить собственный контроллер для него (что делает маршрут по умолчанию снова идеальным ...).

Я бы придерживался маршрута по умолчанию /controller/action/id, но просто не начинал создавать контроллеры для всего (как друзья) в начале. Шаблон Model-View-Controller позволяет очень просто изменять маршруты позже , если все ваши маршрутные ссылки и действия (формы и т.д.) генерируются на основе маршрутов и действий. Так что вам не нужно так сильно беспокоиться:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...