Laravel - Difference between Model::create and save() - laravel

I've come across two different ways of inserting records into the database, the first being:
Model::create([
'field1' => $request['field1'],
'field2' => $request['field2']
]);
and the second way:
$model = new Model;
$model->field1 = $request['field1'];
$model->field2 = $request['field2'];
$model->save();
What is the difference between these two? Are they the same? When should I use one over the other?

Both do the same thing. See the create method code and you will understand. It's just a shorthand.
Sometimes I don't use the create method, for example when I need to set different values upon some condition.

I know this has already been answered. What I've noticed to be the main difference in both are these.
Both does the same thing. It "Saves" data. But create required you to have $fillable in your model. Without defining fillable fields, create will not work. The data will not be passed.
However, Save on the other hand, does not 'require' fillable and can store the data in to the table.
Hope someone else finds this helpful. Happy Coding :)

Related

Two models, two fields, return preferred if present

Been struggling with how to do this the most optimized way possible...
I have two models: Catalog and Application.
Catalog has a field called name.
Application has a field called name.
Both have a relationship with each other.
I am struggling to find a way to create a function i could use across my Laravel application which i would pass application.id to it and it would return a $app->name value based on the following logic:
if $application->name exists, use this value as the $app->name for the $application object
otherwise, get the $catalog->name value and use it as the $app->name
Note that I would like to create a component #application() where i can simply pass the $application->id and build the display logic (theming/styling) into it.
Since i display this $app->name in many places, i would like to make it as lightweight as possible to avoid unnecessary queries.
I hope this makes sense! There are probably so many ways to go with it, i am lost at figuring out the way way to do this :(
I'm not completely sure to understand your model/DB design, but you could use a custom Helper to use that function through the whole app.
For that, you can create a simple PHP class Helper.php file in app/Http/Helpers folder or whatever location you want. Something like:
<?php
use App\Catalog;
use App\Application;
if (! function_exists('getAppName')) {
function getAppName($id){
// Do your logic here to return the name
$catalog = Catalog::find($id);
return $catalog->name;
}
}
?>
Then in any controller or view, you just do
getAppName($application->id)
Do no forget to add your helpers file to the composer autoload. So in composer.json in Laravel's root folder, add the helper path to the autoload array:
"files": [
"app/Http/Helpers/helpers.php"
],
Last but not least, run the following command:
composer dump-autoload
Please note that function logic is just for sample purposes since I don't know your model structure.
In my opinion, I care about the database cost.
Use ternary expression will be elegant. But it took two times IO costs from database if application name is empty.
$app_name = Application::find($id)->name;
$app_name = empty($app_name) ? Catalog::where('application_id', $id)->first()->name;
And this will more complicated, but the catalog_query only execute when application.name is empty, it execute in database and the result is taken out only once;
And Database will only find the name from one table or two table.
Something like this:
$catalog_query = Catalog::where('catalogs.application_id', $id)->select('catalogs.name')->groupBy('catalogs.name');
// if catalogs and applications relationship is 1:1, use ->limit(1) or remove groupBy('name') is better.
Application::where("applications.id", $id)
->selectRaw("IF(application.name IS NULL OR application.name = '', (" . $catalog_query->toSql() ."), applications.name ) AS app_name")
->mergeBindings($catalog_query->getQuery())
->first()
->app_name;
Hope this will help you.

I want to check duplication value during insert time without using unique keyword

i make one table for with some column with nullable.
i already tried with two different query. one using
Register_member::where('passport',$passport)->orWhere('adharcardnumber',$adharcardnumber)->get();
and second DB::table type query.
$row = Register_member::where('passport',$passport)->orWhere('adharcardnumber',$adharcardnumber)->get();
if (!empty($row))
{
return response()->json(["status"=>0, "message"=>"Adharcard or Paasport number already exit."]);
}
if (empty($row))
{
Register_member::insert(['first_name'=>request('first_name'), 'middle_name'=>request('middle_name'), 'last_name'=>request('last_name'), 'adharcardnumber'=>request('adharcardnumber'), 'ocipcinumber'=>request('ocipcinumber'), 'passport'=>request('passport'), 'birthday'=>request('birthday'),
'mobilecode'=>request('mobilecode'), 'mobilenumber'=>request('mobilenumber'), 'email'=>request('email'), 'address'=>request('address'), 'landmark'=>request('landmark'), 'area'=>request('area'),
'gender'=>request('gender'), 'pincode'=>request('pincode'), 'city_name'=>request('city_name'), 'state_id'=>request('state_id'), 'country_id'=>request('country_id'), 'sampraday'=>request('sampraday'), 'other'=>request('other'), 'sms'=>request('sms')]);
return response()->json(["status"=>1, "message"=>"Member register successful."]);
}
if adharcardnumber or passport number are exists in table, then nagetive response. if in both any one in unique then, insert data in table
Let me suggest you something which I think serve you as a good solution. You can use the unique with required and regex. In this way it will use the already recommended ways of Laravel which are the best.
As an example for your adhaar card,
the validation should look like this
$request->validate([
'adhaar ' =>['required','unique:users','regex:/\d{12}/'],
]);
where adhar is the filed name where adhaar number is entered. Be sure to use validator like this use Illuminate\Support\Facades\Validator;. Also $request is the instance of the Request.
Using the required prevent empty field submission and the regex will throw an error if the pattern is not matched completely. so I think it would be a better a way to handle the scenario.
the above solution will work in both adhaar and passport. But for the passport the regex will be different though.
Please note these are all demo examples, you might need to modify it according to your needs. I use https://www.phpliveregex.com/ for regex making and checking and it is good enough.
I hope you get an idea of how to begin but if you need more information then let me know in the comments.

How to retrieve a customised list of records according to Repository pattern?

I wanna move the business logic out of controller actions. I read a lot about repository pattern in laravel with tons of examples.
However they're usually pretty straightforward - we have a class that uses some repository to fetch a list of all possible records, the data is returned to the controller and passed to the view.
Now what if our list isn't all the possible records? What if it depends on many things. For example:
we display the list as "pages" so we might need X records for Y-th page
we might need to filter the list or even apply multiple filters (status, author, date from - to etc)
the user can change the sorting of the data (for example by clicking the table column titles)
we might need some data from other data sources (joined tables) or it might even be used for sorting (so lazy loading won't work)
Should I write a special method with all these cases in mind? Something like that:
public function getForDisplay(
$with = array(),
$filters = array(),
$count = 20,
$page = 0,
$orderBy = 'date',
$orderDir = 'DESC'
)
{
//all the code goes here
return $result;
}
And then call it like this from my controller:
$orders = $this->orders->getForDisplay(
array('customer', 'address', 'seller'),
Input::get('filters', array()),
20,
Input::get('page', 0),
Input::get('sort', 'date'),
Input::get('direction', 'DESC')
);
This looks wrong already and we didn't even get to the repositories yet.
What are the best/correct practices for solving situations like this? I'm pretty sure there has to be a way to achieve the desired results without adding all the possible combinations as a method arguments.
Use the repository pattern just for business model updates and you'll end up with very specific query methods (the Domain usually doesn't need many queries and they are pretty straightforward). For UI/reporting querying purposes, you can use a simple DAO/Service/ORM/QUery Handler , that will take some input and returns the desired data (at least part of the view model).
Since you're already using an ORM, you can use it directly. Note that you can use the ORM for domain updates also, but inside a repository's implementation i.e the app only sees the repository interface. We care about separation at the business layer, for UI querying you can skip the unneeded abstraction.
Btw, because we're talking about design, everything is subjective and thus, there's no single best/optimum way of doing things.

yii use a model related function in a view

I have no reputation to comment on a question, so I am making a new one. But my question is related to another question: How to convert model data objects array to dataProvider
So.... if you read the question, my doubt is:
I need to ask for help to a new thing that this subject rises. I would like to get a function result as the data of a column, but this function is inside the Friend object. Its not possible to do:
array(
'name'=>$model->friends->getAttributeLabel('column_of_friend_model'),
'value'=> $model->friends->takeDataFromFriendModelThatIsActuallyInOtherModel(),
),
Can someone please help!? Thanks a lot!

CakePHP soft deleted data still showing up in model associations

I am using the SoftDeletableBehavior for my addresses model.
This sets it so when you delete an address it doesnt really delete it, instead sets a deleted column in the database to 1.
This also changes your query in the beforeFind function of the Address model to only pull entries where deleted != 1
This works when I am viewing addresses via the addresses controller like /addresses/show/43.
However my Users controller hasMany addresses. So when I am in the users controller and I call $this->find('first'); To get the user, I also get the associated addresses. I am expecting this to NOT give me the (softly) deleted addresses but it DOES. The beforeFilter on the Address Model is never called either.
What is the right way to handle this?
Update.
Apparently when I do this:
$data = $this->User->find('first',array('conditions' => array('User.id' => $id),'recursive' => 2));
I have a $data['User] array and a $data['Address] array (along with others).
But this does not use the beforeFind filter in the Address Model. So I get the wrong data.
But if I do this:
$data = $this->User->find('first',array('conditions' => array('User.id' => $id),'recursive' => 2));
$data['Address'] = $this->User->Address->find('all',array('conditions'=>array('user_id'=>$id)));
Then it does use the beforeFind filter on the Address model and returns the right data.
(Of course in a different format [Address][0][id] vs [Address][0][Address][id])
What I do not understand is if the associated data thats pulled does not use its own model to find its data, then whats the point? Isn't this one of the main purposes of MVC?
Maybe I just don't understand? Or I am missing something?
Can someone please enlighten me?
Can't you put this condition in your association?
<?php
class User extends AppModel {
var $hasMany = array(
'Address' => array(
'conditions' => array('NOT' => array('Address.deleted' => '1')),
)
);
}
?>
Personally, I would add a condition to the find query for users
$this->Users->find->('all',array('conditions'=>array('Address.deleted !='=>'1')));
(haven't tested the code for exact syntax, but this is the general idea)
When you use $this->User->find(...) and include Addresses, you will only see the User model's callbacks fire, because that is the model you are using to drive the find.
This is why you have to use extra conditions in your User model's associations to filter out the soft-deleted Addresses.
If the Address model's callbacks were fired during every find on the User model when recursion scope included Addresses, you'd have no control as to when to include the soft-deleted Addresses and would risk clashes in functionality and param manipulation by those callbacks. Not to mention the serious performance impact this could have.

Resources