Crear mis propias acciones en API REST


(Nicolasignacioleone) #1

Hola estimados, espero que alguien de habla hispana pueda darme una mano con esta orientación. Estoy siguiendo la siguiente guía https://www.yiiframework.com/doc/guide/2.0/es/rest-quick-start para crear mi API, el problema es que son demasiado simples las acciones de los controladores, y en la recopilación de datos que haré desde una app móvil, que será un json, vendrán datos que debo guardar en distintos modelos relacionados, por ejemplo, las formaciones de un empleado, los eventos a los que asiste, la posibilidad de crear un posteo, etc. Todo esto me sería muy útil que ademas sea transaccional por la cantidad de concurrencia que tendrá la aplicación.

Mi consulta precisa es cómo debo crear mis acciones en el controller que extienda de ActiveController? se que puedo anular las que vienen por defecto y redefinirlas, pero digo, cómo puedo recopilar los datos desde el json que viaja desde el móvil y cómo guardar los datos en modo transaccional y por último qué debo devolver como retorno?

En una aplicación web convencional todo esto lo puedo hacer sin problemas, pero nunca me he topado con tener que trabajar desde una API.

Bueno espero alguno pueda ayudarme, les dejo mis saludos!


(Rafaelt88) #2

No comprendo tu duda? me refiero estas explicando el proceso que deseas el ActiveController es para dar soporte RESTFull a un modelo, puedes fácilmente crear un controlador puntual que procese tu petición con la lógica que describes, por otro lado puedes crear tu Action de forma individual y añadirla a tu Controlador en actions() & verbs() recordando que debes traer los padres o perderás la definición de tú ActiveController… Abre la clase una sola vez y entenderás a que me refiero.


(Nicolasignacioleone) #3

Hola Rafael, antes que nada gracias por tu respuesta. Quizá no me expliqué bien.

Se que puedo anular la action create por defecto y volver a definirla dentro de mi controler por ejemplo EstudianteController extends ActiveController. Pero mi duda por nunca haber trabajado con api rest es, cómo recopilo los datos que me llegan desde la app móvil, que será un json, y lo guardo en distintos modelos, por ejemplo tengo el modelo Estudiante donde podría hacer un $model->load()…y otros datos que van dentro del modelo Notas , donde debería hacer un $modelNotas->load(), o algo por el estilo es solo para dar un ejemplo.

Además de eso quiero darle soporte de transacciones utilizando la forma que uso siempre que debo usar transacciones que es:

$transaction = $connection->beginTransaction();
try {
$connection->createCommand($sql1)->execute();
$connection->createCommand($sql2)->execute();
//.... other SQL executions
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollBack();
throw $e;
} catch (\Throwable $e) {
$transaction->rollBack();
throw $e;
}

Ya que temo que por la alta concurrencia que haya en la base de datos haya datos inconsistentes.

Bueno dime si me he explicado bien o reformulo mi consulta, saludos y gracias!


(Rafaelt88) #4

Vale!

Bueno insisto mira la documentación cuando tengas duda, sobre todo ya que sabes lo que quieres (eso es lo mas dificil).

Ejemplo: Este es el código de yii\rest\CreateAction

$model->load(Yii::$app->getRequest()->getBodyParams(), ‘’);
if ($model->save()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(201);
$id = implode(’,’, array_values($model->getPrimaryKey(true)));
$response->getHeaders()->set(‘Location’, Url::toRoute([$this->viewAction, ‘id’ => $id], true));
} elseif (!$model->hasErrors()) {
throw new ServerErrorHttpException(‘Failed to create the object for unknown reason.’);
}

Yii::$app->getRequest()->getBodyParams() te dará los datos que recibes y es donde debes comenzar a plantear la lógica, que ya mencionaste y el tratamiento a tus datos.


(Nicolasignacioleone) #5

Muchas gracias eso me faltaba, en realidad lo abrí pero al no haber trabajado nunca con api, no se bien cómo retornar tanto los datos o una excepción pero bueno ahí está. Así puedo hacer con update también no? lo que sería index o view no lo toco. Delete en mi requerimiento debo “no permitirlo”, así que lo anulo directamente.

Qué opinas ya que veo tienes experiencia, en meter transacciones en acciones donde intervienen varios modelos? yo hago así siempre que tengo modelos anidados o tablas intermedias para que me garantice ACID en las aplicaciones más grandes.

En cuanto a autenticación qué me recomiendas? token? OAuth?

Saludos y gracias!


(Rafaelt88) #6

Cuando usas múltiples tabmas el deber ser es utilizarla transacciones, si solo harás ajustes a una tabla no es necesario…

Ubica los ficheros del ActiveController y puedes estudiar mejor las acciones actuales o tener una idea de cómo las maneja Yii2…

La autenticación depende de tu app lo común es un token particular para consumir tus servicios.


(Nicolasignacioleone) #7

Muchas gracias Rafael has sido esclarecedor en tu respuesta. Te deseo un buen final de día! Saludos!


(Nicolasignacioleone) #8

Hola! Perdón por molestar nuevamente, he avanzado en el diseño de la API, te pregunto o pregunto al foro a quien pueda responder, así evito abrir otro hilo.

Es conveniente crear la api en una carpeta separada como sugiere la documentación? así como frontend, backend, crear una carpeta api con toda su estructura, o es mejor como he visto hacer a varios, crear la api como módulo?

Saludos y muchas gracias nuevamente!


(Rafaelt88) #9

La API por lo general consume petición de tus modelos o tablas, definirlas en un módulo no está mal aunque podría chocar con la arquitectura modular que tengas definida, podrías por otro lado hacer una app similar a console, Backend y Frontend, dentro de API darle modularidad a tus versiones creo esto es lo q quieres.


(Nicolasignacioleone) #10

Muchas gracias Rafael, si he visto las dos opciones, lo del módulo lo vi en un curso y me pareció práctico, pero me hacía un poco de ruido el hecho de que no esté en una carpeta de aplicación distinta. Ahora cuando me dices de darle modularidad a tus versiones a qué te refieres? yo en lo que sería un módulo, tendría una carpeta llamada modules > api > v1 …v2, etc. Si creo una carpeta de aplicación separada debería de hacer lo mismo no? por ejemplo tendría console, backend, frontend, api y dentro de api > v1…v2 , algo así me sugieres? o hacer api > modules > v1…v2 ?

Muy interesante este tema, saludos nuevamente!


(Rafaelt88) #11

Así es, ambas formas son funcionales y similares… Ahora yo optaría por crear una app te dará un poco más de alcance y bueno podrías omitir o controlar aspectos de autenticación o tus respuestas, en el módulo igual pero acá estás un nivel más abajo incluso puedes linkear tu app a un subdominio y sería más elegante api.sitio.con/v1 :slight_smile:


(Nicolasignacioleone) #12

Bueno Rafael una vez más muchas gracias por tu aporte. Me es de mucha ayuda poder orientarme un poco más.

Sinceramente es muy difícil encontrar comunidad en español sobre este poderoso framework y que tanta satisfacción me da trabajar con el. Pero al menos aquí he obtenido respuesta.

Saludos y que tengas un buen día!