I wrote the following 'insert code' in a way that I can use it many times. So without writing the table name in the model I could write the table name in the controller.
model function
function insertTable($table, $data) {
$this->db->insert($table, $data);
return $this->db->insert_id();
}
controller instruction
$insert = $this->Model_Action->insertTable('student',$student_data)
But I want to do the same in the following code as well. Is there a way to replace the p_id as $id?
Model
function delete_by_id($id)
{
$this->db->where('p_id', $id);
$this->db->delete('parent');
}
Controller
public function student_delete($id)
{
$this->load->model('Model_Action');
$this->Model_Action->delete_by_id($id);
echo json_encode(array("status" => TRUE));
}
Yes you can. your model
function delete_by_id($column_name, $id){
$this->db->where($column_name, $id);
$this->db->delete('parent');
}
then use it in controller's student_delete methos like
$this->Model_Action->delete_by_id('p_id', $id);
If you want delete 'student' table row by ID, you can use to below code.
function delete_by_id($id)
{
$this->db->delete('student', array('id' => $id));
}
If you want delete different table row by ID:
function delete_by_id($table, $id)
{
$this->db->delete($table, array('id' => $id));
}
Well, you should use codeigniter Core Classes.
In folder hierarchy, there is a folder named core in which you can make parent controller and model.
You can make all functions of model which we are using in almost all models like for create, update, delete, read records in this parent model and inherit our app models from this model.
In our Controller, we just need to get model name and use these functions.
Note: I am using same way since 2018.
You can define Table_name in model for reusable insert , delete, edit methods.
You can use where conditions usig condition wise.
Ex.
function get($id='',$name='')
{
if($id >0)
{
$this->db->where('id',$id);
}
}
Controller:
Write required database table name to variable $table in controller. And pass the variable $table to model.
Model:
function insertTable($table, $data) {
$this->db->insert($table, $data);
return $this->db->insert_id();
}
Related
I just have a table that has relation belongsToMany, BUT it was a mistake by developer so I can not change this structure SO I need to get only first(). However, when I take only first it return empty array but I need in object
$animals = Cat::query()->with(['types' => function($query) {
$query->first(); //wrong
}])
So how I can get only first? Because I need to order by this field and I can't because it is array
you can do this in two ways:
1- using hasOne relation:
class Cat {
public function firstType() {
return $this->hasOne(Type::class, 'type_id', 'id')->latest();
}
}
2- using staudenmeir/eloquent-eager-limit
after installing it you can write:
class Cat extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
public function firstType() {
return $this->hasMany(Type::class, 'type_id', 'id')->latest()->limit(1);
}
}
class Type extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
// ......
}
the advantage of HasEagerLimit trait is that you can limit the result not only to one but any number you want ...
now you can write:
$animals = Cat::query()->with('firstType');
You can add a attribute getter and set up into appends attribute. follow bellow example:
class Cat {
protected $appends = ['type'];
public function getTypeAttribute() {
// return the first element from your array of the belongsToMany relationship if it exists
return isset($this->types[0])? $this->types[0] : null;
}
}
That's important to remember this method will bring just one type. If you want to get the same type everytime, you create a diferente table where the cat table has the type_id column.
obs: Sorry for my english, it's still in working progress.
I am developing a project in Laravel 5.4. I want to write a select, insert and update query in my model that should work for any table in database. I used to do this is Codeigniter and work fine there, but I don't know how to use it in Laravel.
Following is the code from a model file in Codeigniter
class General_Model extends CI_Model {
public function fetch_CoustomQuery($sql){
$query = $this->db->query($sql);
return $query->result();
}
public function create_record($data, $tbl)
{
$this->db->set($data);
$this->db->insert($tbl);
return ($this->db->affected_rows() != 1) ? FALSE : TRUE;
}
public function update_record($data, $tbl, $wher)
{
$this->db->where($wher);
$this->db->set($data);
$this->db->update($tbl);
}
public function delete_record($tbl, $wher)
{
$this->db->where($wher);
$this->db->delete($tbl);
}
}
It was very easy in Codeigniter. I only need to pass the parameters and worked fine. I want to write same queries in my model in Laravel. Please help
I would strongly recommend reading the documentation but the methods are as simple as:
GeneralModel::create(["num" => 1, "name" => 2]);
GeneralModel::where("num", ">", 2)->update(["num" => 1]);
GeneralModel::where("num", ">", 2)->delete();
There is no need to put these methods on the models.
if you really want something like that then you can have function there that accepts models as parameter:
public function create_record($model,$data)
{
$model::create($data);
}
where in the controller you can do something like
$model = App\Fruit; // lets say fruit is a model you have
GeneralModel::create_record($model,$data);
but why not just go straight with it like:
$var = App\Fruit::create($data);
this is redundant .. for each model have a way to fetch , insert , update or delete records from their perspective table .. i suggest you read more documentation about Laravel Eloquent
Now this, from what I can see, should have been simple.
I want to be able to delete multiple records from the database. I have the id's of all the records I wish to delete. I call the resource.destroy route using comma separated list of ids (id is of postgres type uuid), like so:
Request URL:http://foo.app/products/62100dd6-7ecf-4870-aa79-4b132e60c904,c4b369f1-d1ef-4aa2-b4df-b9bc300a4ff5
Request Method:DELETE
On the other end, my controller action looks like so:
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->find($ids)->delete();
}
catch(...) {
}
}
This gives me the following error:
BadMethodCallException in Macroable.php line 81:
Method delete does not exist.
in Macroable.php line 81
at Collection->__call('delete', array()) in ProductsController.php line 251
at Collection->delete() in ProductsController.php line 251
at ProductsController->destroy('62100dd6-7ecf-4870-aa79-4b132e60c904,c4b369f1-d1ef-4aa2-b4df-b9bc300a4ff5')
I have verified that find() is returning a collection of products matching the specified ids.
What am I missing?
PS:
1. The model Product has several belongsTo relationships with other models.
2. The product.destroy code works fine if I pass it a single id
EDIT
I guess, I'm also trying to understand what the difference between:
$org->products()->find($ids)->delete()
and
$org->products()->whereIn('id', $ids)->get()->delete()
is? From what I see, both find and get are returning Collections
The issue is that you're calling delete() on a Collection, which does not have that method.
You have a couple options here.
Model Events
If you have event listeners for the deleting/deleted model events, you will need to make sure the deletion happens in a way that each model is loaded and then deleted.
In this case, you can use the destroy method on the model that takes a list of ids. It will load a new model for each id, and then call delete() on it. As you mention in a comment, it won't restrict the deletion to only those products in the organization, so you would need to filter out those ids before passing the list into the destroy() method.
public function destroy($id)
{
try {
$ids = explode(",", $id);
// intersect the product ids for the org with those passed in
$orgIds = array_intersect($org->products()->lists('id'), $ids);
// now this will only destroy ids associated with the org
\App\Product::destroy($orgIds);
}
catch(...) {
}
}
If you don't particularly like that approach, you will need to iterate your collection of organization products and call delete() on them individually. You can use a standard foreach, or you can use the each method on the collection:
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->find($ids)->each(function ($product, $key) {
$product->delete();
});
}
catch(...) {
}
}
No Model Events
Now, if you don't have any model events that you need to listen for, things are a little easier. In this case, you can just call delete() on the query builder, and it will go straight to deleting the records without loading any model objects. So, you get cleaner code with better performance:
public function destroy($id)
{
try {
$ids = explode(",", $id);
// call delete on the query builder (no get())
$org->products()->whereIn('id', $ids)->delete();
}
catch(...) {
}
}
If you create a model of your products, it will help you with these types of operations.
For example:
the model Products.php
<?php
namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;
class Products extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'products';
protected $primaryKey = 'id';
protected $fillable = ['name', 'price', 'description'];
}
The controller Products.php
You can use the destroy method and pass one or more primary keys to it as arguments.
<?php
namespace App\Http\Controllers;
use App\Http\Models\Products;
class Products
{
public function destroy($id)
{
try {
$ids = explode(",", $id);
//$ids is a Array with the primary keys
Products::destroy($ids);
}
catch(...) {
}
}
}
You can also use this option to remove query results with a custom parameter
$deletedRows = Products::where('name', 'phones')->delete();
You can check the Laravel documentation https://laravel.com/docs/8.x/eloquent#soft-deleting
When you use the find method, it will find only a single ID. You should use a whereIn to match multiple ids
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->whereIn('id', $ids)->get()->delete();
}
catch(...) {
}
}
This way you will find all the products with the given IDs and delete them all.
I also faced this problem. Let $orgs contains some records as a collection. Now you can easily delete these records using a loop like this-
foreach($orgs as $org)
{
$org->delete();
}
In my database I have 2 tables:
country(id,name)
users(id,countryid)
country ->id= users->countryid;
I'm trying to perform this task with yii relations to get name from country table :
users modals
public function relations()
{
return array(
'linkedIndex' => array(self::BELONGS_TO, 'Country','countryid'),
);
}
public function afterFind()
{
$name = Users::model()->findByPk(1);
}
if you look at this code closely, you will see that variable name is being populated,BUT after functions ends, the variable also gets destroyed,
public function afterFind()
{
$name = Users::model()->findByPk(1);
}
if you want to keep this $name, you have to make it a property of the model class (or store it in an existing property)
I use models that extend a generic_model, which in turn extends Eloquent (so that I have several crud methods I use already set to be inherited).
A lot of the tables I use invoke soft delete, which needs a WHERE clause of...
WHERE deleted = 0
Is there a way to make Laravel behave in such a way that this WHERE clause is automatically included in all queries and all queries to objects that are related to one another?
e.g.
pages where id = 5 and deleted = 0
and then...
images where page_id = 5 and deleted = 0
if you're using laravel 3 this is what you needs
on your model
public function query()
{
$query = parent::query();
$query->where('deleted','=','0');
return $query;
}
if you're using laravel 4 just change the method query for newQuery
public function newQuery()
{
$query = parent::newQuery();
$query->where('deleted','=','0');
return $query;
}
reference
In relationships you can add the where_clause in your return:
public function pages()
{
return $this->has_many('Page')->where_deleted(0);
}
In your Model, you could add something like:
public static function active()
{
return self::where_delete(0)->get();
}
to use Page::active() instead of Page::all()
(Or you can remove the ->get() from the function in the model, so you can still further modify your query (Page::active()->order_by('name'))