0

I currently have two tables namely storing users and clients. A client is related to a User in a one-to-one relationship.

I am currently storing and updating the models like so but it feels rather clunky...

 public function store(Request $request)
    {
        $requestData = $request->all();

        $user = new User();
        $user->fill($requestData);
        $user->save();

        $client = new Client;
        $client->fill($requestData);
        $client->user()->associate($user);
        $client->save();

        return response()->json($client->toArray(), 201, ['id' => $client->id]);
    }

    public function update(Request $request, $id)
    {
        try {
            $client = Client::findOrFail($id);
            $user = User::findOrFail($client->fk_user);
        } catch (ModelNotFoundException $e) {
            return response()->json([
                'error' => [
                    'message'   =>  'Client not found',
                ]
            ], 404);
        }

        $requestData = $request->all();

        $user->fill($requestData);
        $user->save();
        $client->fill($requestData);
        $client->user()->associate($user);
        $client->save();

        return response()->json($client->toArray(), 200);
    }

Is there a way to refactor this to avoid having to work with both users and clients as separate models. Is there a way to perhaps fill a client and in turn fill the parent user model?

Just wondering, thanks!

liamjnorman
  • 784
  • 1
  • 16
  • 30
  • 1
    Maybe start by extract some of the logic to their own methods, for example storing the user and client. Then you also get the ability reuse them. You might also set up some response methods so you dont need to have all that response type and status code junk in the store/update methods. – Isak Berglind May 26 '17 at 20:48
  • Ah okay thanks @IsakBerglind, but is there no way in Laravel to fill a client and then that fills the user in this case or? – liamjnorman May 26 '17 at 20:52
  • 1
    You can add that on the client model, send it the request data and save it. eg: $client->saveAndAssociateUser($requestData); – Isak Berglind May 26 '17 at 20:56
  • Also, check this out for handling exceptions when the user expects a json response, so you can maybe get rid of that trycatch https://stackoverflow.com/questions/28944097/laravel-5-handle-exceptions-when-request-wants-json – Isak Berglind May 26 '17 at 20:58
  • Thanks, feel free to add an answer and I'll accept! – liamjnorman May 26 '17 at 21:10

1 Answers1

1

I´ve made some refactoring inspiration for you. This is not necessarily the "right" way, but maybe you can pick up something you like.

Note! I haven't actually tested the code, its probably full of syntax errors. I just hacked it down to show some ideas. Some of the logic, like associating the user, I've imaginary placed in the client model. The error handling happens in app/Exceptions/Handler.php.

Hope you can have some use of it :)

 private function saveUser($args, $user = null) {        
    $user = $user ?: new User();
    $user->fill($args);
    $user->save();
    return $user;
}

private function saveClient($args, $client= null) {
    $client = $client ?: new Client;
    $client->fill($args);
    $client->save();
    return $client;
}

private function respondCreated($data = []) {
    return $this->respond($data, 201, "created");
}

private function respond($data = [], $statusCode = 200, $message = "ok") {
    $response = [
        "message" => $message, 
        "data" => $data
    ];
    return response()->json($response, $statusCode);
}

public function store(Request $request)
{
    $user = $this->saveUser($request->all());
    $client = $this->saveClient($request->all());
    $client->saveUser($user);

    return $this->respondCreated($client);
}

public function update(Request $request, $id)
{

    $client = $this->saveClient($request->all(), $client::findOrFail($id));
    $this->saveUser($request->all(), $client->fk_user);

    return $this->respond($client);
}