Laravel updating a hasMany relationship - php

In my system users can have many timesheets, timesheets can have many data.
I'm trying to update the data rows in the data_timesheet table. I'm using this:
$data = ['column_1' => 'value'];
$this->findTimesheetById($id)->data()->saveMany($data);
However, it's giving me the following error:
Argument 1 passed to Illuminate\Database\Eloquent\Relations\HasOneOrMany::save() must be an instance of Illuminate\Database\Eloquent\Model, array given
I know why it's giving me the error, because I need to send it a model as opposed to an array. How can I send in a model, when the values being passed are from a user form?
EDIT:
I can do this which works, but there must be a better way?
$data = $this->findTimesheetById($id)->data();
$data->delete();
$data->insert($data);

The way to do that is:
1) You create a file model and put it in the Models folder. That model can even almost empty, like this:
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Session;
use DB;
class Booking extends Model{
2) Then in the Controller you create an instance of that Model, like this
$theinstance = new Booking;
3) Then you use that object to have the values given, like this:
$theinstance->name = $name;
$theinstance->telephone = $telephone;
$theinstance->save();
That would be the way to save data.
Now, with regards to the update, at the Controller you can have something like this:
$photosslide = Property::returnPhotosSlide($id);
$propertydetails = Property::returnPropertyDetails($id);
$alsointown = Property::returnAlsoInTown($id);
return view('detailsproperty', compact('photosslide','propertydetails','alsointown'));
This sends the values from a Form into the Model
and once you are in the Model, just do an Update query.

Related

Laravel: passing dynamic table name to model e.g protected $table = "$tablename"

So my code successfully creates dynamic tables of the exact same structure (I need it this way for my own reasons).
However, the problem comes when I want to add data to any of the dynamically created table because I don't have a model for it, the way I have when I normally create tables/models.
So, I was wondering how can I work around this problem?
Can I use this kind of logic somehow?
namespace App;
use Illuminate\Database\Eloquent\Model;
class sys_cats extends Model
{
// I know we can't use variable in class like this
// but this is just to explain what kind of logic I have
// in mind.
$category = Session::get('catName');
protected $table = "$category";
protected $primarykey = 'id';
protected $fillable = [
.
.
.
So I assume, this way, we can use this model to dynamically change table name to the name stored in a session variable.
So we won't have to create a separate model for each of these tables.
Is this achievable? Or I must create a separate model file as well each time when I dynamically create a table in database?
I am sorry, if what I am suggesting is fundamentally wrong or anything related. I am pretty new to PHP and Laravel.
Waiting for your kind suggestions.
Thanks
better to use fluent query builder db
u can add dynamically table name with insert,update,read,delete
operation
for example
get record from db
DB::table($tableName)->all()
for insert
DB::table($tableName)->insert(['name' => $name]);
for automatically added created_at and updated_at add in migration
$table->timestamp('created_at')->default(\DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(\DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));

Eloquent (WITHOUT Laravel) get data from table with dynamic name

I'm sure this is a totally simple question but for the life of me I'm stuck here- we're using Eloquent outside of Laravel due to PHP restrictions. I have a support ticket tracking app that I'm trying to update.
The data structure of this app is such that each ticket is assigned a UUID on submission and a table with that UUID as its name is generated and all changes to the ticket are tracked as new entries in that table.
Following some tutorials on Eloquent I got our models and controllers set up and working but for each one I see that I'm defining the table name in the model itself. IE our ticket model is
namespace Models;
use \Illuminate\Database\Eloquent\Model;
class Ticket extends Model {
protected $table = 'tickets';
protected $fillable = [table columns here];
}
and anything called in the tickets controller correctly and successfully reads and writes data to our tickets table.
So... my question is: how would I go about reading/writing/creating/deleting those previously mentioned UUID tables?
I've tried the built in table selector (ie- DB::table(uuid here) and DB::setTable(uuid here) but to no avail. I get Fatal error: Call to undefined method Models\Database::setTable()
What I'm after is a model/controller that I can reuse for ANY dynamically-named table.
You could create a generic model and dynamically set the table name, like this:
namespace Models;
use \Illuminate\Database\Eloquent\Model;
class FormerUUIDTicket extends Model {
protected $table = 'some_table';
protected $fillable = [table columns here];
}
class SomeController
{
public function someAction()
{
$uuid = $_POST['uuid_field']; //some uuid, the table name
$model = new FormerUUIDTicket;
$model->setTable($uuid);
return $model->get(); //do anything using eloquent with proper table
}
}
Make sure that you always set the table name before use, or it will fail. Don't use static function either, for the same reason.

Always modify returned values from laravel model

So I have a model, Post that has no methods defined within it.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use DB;
class Post extends Model
{
}
From a controller, I make calls to that model like:
return view('pages.post', ['post' => Post::where('url_route', '=', $url_route)->first()]
This works fine, but I now want to format the date column that is returned from that request, every time that model is called. Is there a way to modify the returned array without defining a new method?
I am new to Laravel to thanks for the help. Just trying to figure out the most efficient way of doing things within the framework...
If your model has $timestamps set to true, the created_at and updated_at fields are natively a Carbon instance.
This means you can format the date in the view like this as a basic example:
$post->updated_at->format('Y-m-d H:i:s')
Carbon instances allow you to leverage its extensive api as you can see at http://carbon.nesbot.com
If you would like to do the same for another field other than created_at and updated_at, you can add an extra property in your model:
protected $dates = ['added_on']
The fields you specify in the array will be treated as Carbon instances.

Why eloquent model relationships do not use parenthesis and how do they work?

I kept searching the web for an hour but couldn't figure this out. If we look at the eloquent relationships documentation:
https://laravel.com/docs/5.2/eloquent-relationships
The example User model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('App\Phone');
}
}
Just below it, how to access the phone number of a user with id=1:
$phone = User::find(1)->phone;
Why is it phone and not phone() and what is the difference?
Also how does it work? If I try to call an object->name without parenthesis in my code PHP thinks I am looking for a class variable named name?
Some extra information:
It looks like phone is returning object(App\Models\Phone) and phone() is returning object(Illuminate\Database\Eloquent\Relations\HasOne)
If I run the code below:
User::find(1)->phone->count()
Framework executes following SQL statements:
select * from `phone` where `phone`.`user_id` = '1' and `phone`.`user_id` is not null limit 1
select count(*) as aggregate from `phone`
If I run the code below:
User::find(1)->phone()->count()
Framework executes following SQL statement:
select count(*) as aggregate from `phone` where `phone`.`user_id` = '1' and `phone`.`user_id` is not null
One way of thinking about it is that the public function phone() function defines the relationship, so using $obj->phone() would get you the Eloquent relationship itself (not the results of that relationship) which you could then modify with various query builder elements if you wanted.
Leaving out the brackets is the Eloquent shorthand for adding ->get() or ->first() at the end of the expression (Eloquent knows which to use based on if it's a hasOne, hasMany, etc. relationship, as defined in the function), which returns an Eloquent collection.
So, $obj->phone is the same as $obj->phone()->first().
I don't know Laravel/Eloquent and you would need to show the find() method for more information, but User::find(1) returns an object so the ->phone accesses the phone property of that object. This has nothing to do with the find() method that you have shown. It is shorter than this that would do the same:
$obj = User::find(1);
$phone = $obj->phone;
Do a var_dump($obj); and you should see a phone property. If not, then another possibility is that the class implements a __get() magic method so that when you attempt to access the phone property it runs the phone() method and returns the value.
As for the first explanation, the same can be done with arrays:
function test() { return array('phone'=>'713-555-1212'); }
echo test()['phone'];

Calling Correct Database Table with Laravel all()

I am just getting started with Laravel 5. I am trying to set up a basic page that retrieves all data from a database table. I have a table call people and I have a controller called ContactController.php. The controller has the following code:
<?php namespace App\Http\Controllers;
use App\Contact;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ContactController extends Controller {
public function index()
{
$people = Contact::all();
return $people;
}
}
When I access my page, I get the following error:
QueryException in /home/vagrant/sites/laravel/vendor/laravel/framework/src/Illuminate/Database/Connection.php line 614:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'homestead.contacts' doesn't exist (SQL: select * from `contacts`)
Why is it trying to access homestead.contacts? My table is called people. I never created a table called contacts. Where is it drawing the table name from and how do I correct this?
Thanks.
Quote from the docs:
Note that we did not tell Eloquent which table to use for our User model. The lower-case, plural name of the class will be used as the table name unless another name is explicitly specified.
So if you define nothing else, Laravel will take the plural snake_case version of your class name:
Contact => contacts
FooBar => foo_bars
To fix your issue either change the model name accordingly. In this case Person will let Laravel search for the table people.
Or explicitly specify the table in your model:
class Contact extends Eloquent {
protected $table = 'people';
}
Do you have the right table name in your app/Contact.php model?
protected $table = 'people';
Or are you using the wrong model?
Add the following line to your Contact model (app/Contact.php).
protected $table = 'people';
This will work.

Categories