I am passing a parameter from model to view like this
Model
class school_model extends CI_Model{
function employee_get($student_id){
$query = $this->db->get_where('students', array('student_id'=>$student_id));
return $query->row_array();
}
}
Controller
function bret($student_id){
$this->load->model('school_model');
$data = $this->school_model->employee_get($student_id);
echo $data['student_gender'];
}
This obviously translates to select * from students where id=id given for example and seen through the browser like http://example.com/env/at/index.php/frontpage/bret/306
I am wondering if the get_where() is suitable if i wanted to have this query
select student_gender,student_has_a_medical_condition from students where (student_gender = 'female' && student_has_a_medical_condition = 'no') LIMIT 40;
Will i need to extend get_where() for it to work?.
First,I suggest reading the excellent documentation for CodeIgniter on the ActiveRecord class.
You don't have to extend get_where() but just use the existing methods to define your query:
function employee_get($student_id){
$this->db->select('student_gender','student_has_a_medical_condition');
$query = $this->db->get_where('students', array('student_id'=>$student_id,'student_has_a_medical_condition'=>'no','student_gender'=>'female'),40);
return $query->row_array();
}
Of course you can pass in the additional parameters to the function so they are not hardcoded, and you can also pass in the desired columns as a paremeter, too. But start with the documentation.
Related
I'm building my own CMS and I used my own Database class for it.
In some frameworks there is a way to do a function on another function
$firstValues = $this-db->query('your query')->first();
What do I kind of class do I need for the ->first().
Is there a way in php to do this? Do I need to use an Abstract class? Does anybody has an example?
If you need any more information, please ask me!
Thanks for helping!
Tom
What do I kind of class do I need for the ->first().
Most frameworks provide a "Query Builder" class to generate and execute SQL statements without writing SQL manually.
Is there a way in php to do this?
Yes, just pick a query builder:
https://github.com/cakephp/database
https://github.com/illuminate/database
Do I need to use an Abstract class?
No
Does anybody has an example?
Illuminate Database (Laravel):
$userRow = Capsule::table('users')->where('votes', '>', 100)->get();
CakePHP:
$userRow = $connection->newQuery()
->from('users')
->select('*')
->where(['votes >' => 20])
->execute()
->fetch('assoc');
Under the hood the first() method just fetches the first row.
PDO example:
$statement = $pdo->prepare("SELECT * FROM users WHERE votes > :votes LIMIT 1");
$statement->execute(['votes' => 20]);
$userRow = $statement->fetch();
You have to pass $this between methods.
Here's some example:
Class Db {
private $_query_result;
public function query($query_string = '')
{
// make your query or smth
// save for example array of results
$this->_query_result = $your_query_result;
return $this;
}
public function first()
{
return array_shift($this->_query_result);
}
}
I am using default scope in my project and it works fine.
public static function find()
{
return parent::find()->where(['is_deleted' => 0]);
}
But now, I want to show all the deleted records in the report section.
How can I skip default scope for particular query only?
Use this to clear or redefine your condition:
$model = Model::find()->where('');
If you want to make sure that you're using fresh query (without any params or conditions), you need to create new ActiveQuery object for given model.
$query = Yii::createObject(ActiveQuery::className(), [Post::class]);
Or add a helper method in model itself:
public static function freshFind()
{
return parent::find();
}
and use it instead of Post::find().
You could avoid the use of find() ..using a findBySql
$sql = 'SELECT * FROM product';
$product= Product::findBySql($sql,)->all();
in this way you all the models of product ..
and you could also use
$sql = 'SELECT * FROM ' . Product::tableName() ;
for avoid explici table name for Products
I want to display the content of page dynamically this following code is working fine but it only shows the content of specific id...how can i make that dynamic??
Model
public function getAllDepartment() {
$join = $this->db->query( "Select * from labreport_db inner join patient_db on labreport_db.P_ID=patient_db.id where labreport_db.P_ID=15");
return $join->result_array();
}
Controller
public function reportDisplay(){
$data['clubs'] = $this->labdoc_model->getAllDepartment();
$this->load->view('SystemAdminUser/labreport', $data);
}
There is simple work around for this using Query Builder class of CI.
So this is how your code will look like,
$id=15;
$this->db->select('*');
$this->db->from('labreport_db');
$this->db->join('patient_db', 'labreport_db.P_ID = patient_db.id');
$this->db->where('labreport_db.P_ID', $id);
$query = $this->db->get();
This is standard approach in CI to make database operation using query builder class in which you can perform dynamic WHERE condition.
For which just change the value of $id and the query will do the needful.
Reference: https://www.codeigniter.com/userguide3/database/query_builder.html#selecting-data
Hold the id in some variable like:
$pid = $_REQUEST['p_id'];
// $_REQUEST['p_id'] will contain the dynamic value in it
and put this variable in your query like:
where labreport_db.P_ID = $pid;
It will show the data for the value contained in $pid, and make sure it contains the dynamic value in it.
You can used this code for you solution.
Model.php
public function getAllDepartment($pId) {
$join = $this->db->query( "Select * from labreport_db inner join patient_db on labreport_db.P_ID=patient_db.id where labreport_db.P_ID=".$pId);
return $join->result_array();
}
Controller.php
public function reportDisplay(){
$pid = $_REQUEST['pid']; //OR $_GET['pid']; OR $_POST['pid']; You can pass your id for get content
$data['clubs'] = $this->labdoc_model->getAllDepartment($pid);
$this->load->view('SystemAdminUser/labreport', $data);
}
There are a couple of ways doing it. One of them is through CI routing ability.
Model
public function getAllDepartment($p_id = 0) {
$join = $this->db->query( "Select * from labreport_db inner join patient_db on labreport_db.P_ID=patient_db.id where labreport_db.P_ID={$p_id}");
return $join->result_array();
}
Comment: I added $p_id as a variable to fetch the ID dynamically.
Controller
public function reportDisplay($p_id = 0){
$data['clubs'] = $this->labdoc_model->getAllDepartment($p_id);
$this->load->view('SystemAdminUser/labreport', $data);
}
Comment: We also add a variable called $p_id in the reportDisplay function and pass it to your model's getAllDepartment()function.
How to fetch the report dynamically
I don't know your URL structure, but for example purposes let's say it's http://localhost/yourcontrollername/reportDisplay/
To access it dynamically, simply add an ID after the reportDisplay
For example:
http://localhost/yourcontrollername/reportDisplay/15
http://localhost/yourcontrollername/reportDisplay/10
Whenever I add additional logic to Eloquent models, I end up having to make it a static method (i.e. less than ideal) in order to call it from the model's facade. I've tried searching a lot on how to do this the proper way and pretty much all results talk about creating methods that return portions of a Query Builder interface. I'm trying to figure out how to add methods that can return anything and be called using the model's facade.
For example, lets say I have a model called Car and want to get them all:
$cars = Car::all();
Great, except for now, let's say I want to sort the result into a multidimensional array by make so my result may look like this:
$cars = array(
'Ford' => array(
'F-150' => '...',
'Escape' => '...',
),
'Honda' => array(
'Accord' => '...',
'Civic' => '...',
),
);
Taking that theoretical example, I am tempted to create a method that can be called like:
$cars = Car::getAllSortedByMake();
For a moment, lets forget the terrible method name and the fact that it is tightly coupled to the data structure. If I make a method like this in the model:
public function getAllSortedByMake()
{
// Process and return resulting array
return array('...');
}
And finally call it in my controller, I will get this Exception thrown:
Non-static method Car::getAllSortedByMake() should not be called statically, assuming $this from incompatible context
TL;DR: How can I add custom functionality that makes sense to be in the model without making it a static method and call it using the model's facade?
Edit:
This is a theoretical example. Perhaps a rephrase of the question would make more sense. Why are certain non-static methods such as all() or which() available on the facade of an Eloquent model, but not additional methods added into the model? This means that the __call magic method is being used, but how can I make it recognize my own functions in the model?
Probably a better example over the "sorting" is if I needed to run an calculation or algorithm on a piece of data:
$validSPG = Chemical::isValidSpecificGravity(-1.43);
To me, it makes sense for something like that to be in the model as it is domain specific.
My question is at more of a fundamental level such as why is all()
accessible via the facade?
If you look at the Laravel Core - all() is actually a static function
public static function all($columns = array('*'))
You have two options:
public static function getAllSortedByMake()
{
return Car::where('....')->get();
}
or
public function scopeGetAllSortedByMake($query)
{
return $query->where('...')->get();
}
Both will allow you to do
Car::getAllSortedByMake();
Actually you can extend Eloquent Builder and put custom methods there.
Steps to extend builder :
1.Create custom builder
<?php
namespace App;
class CustomBuilder extends \Illuminate\Database\Eloquent\Builder
{
public function test()
{
$this->where(['id' => 1]);
return $this;
}
}
2.Add this method to your base model :
public function newEloquentBuilder($query)
{
return new CustomBuilder($query);
}
3.Run query with methods inside your custom builder :
User::where('first_name', 'like', 'a')
->test()
->get();
for above code generated mysql query will be :
select * from `users` where `first_name` like ? and (`id` = ?) and `users`.`deleted_at` is null
PS:
First Laurence example is code more suitable for you repository not for model, but also you can't pipe more methods with this approach :
public static function getAllSortedByMake()
{
return Car::where('....')->get();
}
Second Laurence example is event worst.
public function scopeGetAllSortedByMake($query)
{
return $query->where('...')->get();
}
Many people suggest using scopes for extend laravel builder but that is actually bad solution because scopes are isolated by eloquent builder and you won't get the same query with same commands inside vs outside scope. I proposed PR for change whether scopes should be isolated but Taylor ignored me.
More explanation :
For example if you have scopes like this one :
public function scopeWhereTest($builder, $column, $operator = null, $value = null, $boolean = 'and')
{
$builder->where($column, $operator, $value, $boolean);
}
and two eloquent queries :
User::where(function($query){
$query->where('first_name', 'like', 'a');
$query->where('first_name', 'like', 'b');
})->get();
vs
User::where(function($query){
$query->where('first_name', 'like', 'a');
$query->whereTest('first_name', 'like', 'b');
})->get();
Generated queries would be :
select * from `users` where (`first_name` like ? and `first_name` like ?) and `users`.`deleted_at` is null
vs
select * from `users` where (`first_name` like ? and (`id` = ?)) and `users`.`deleted_at` is null
on first sight queries look the same but there are not. For this simple query maybe it does not matter but for complicated queries it does, so please don't use scopes for extending builder :)
for better dynamic code, rather than using Model class name "Car",
just use "static" or "self"
public static function getAllSortedByMake()
{
//to return "Illuminate\Database\Query\Builder" class object you can add another where as you want
return static::where('...');
//or return already as collection object
return static::where('...')->get();
}
Laravel model custom methods -> best way is using traits
Step #1: Create a trait
Step #2: Add the trait to model
Step #3: Use the method
User::first()->confirmEmailNow()
app/Model/User.php
use App\Traits\EmailConfirmation;
class User extends Authenticatable
{
use EmailConfirmation;
//...
}
app/Traits/EmailConfirmation.php
<?php
namespace App\Traits;
trait EmailConfirmation
{
/**
* Set email_verified_at to now and save.
*
*/
public function confirmEmailNow()
{
$this->email_verified_at = now();
$this->save();
return $this;
}
}
How I can execute a SQL query in CakePHP.
I want to make some like this code
$employees = $this->Employee->find('all');
but introducing my own SQL statment.
Insert into your Model a function that executes your SQL statment,
public function get_employees() {
$sql = 'select * from employees';
$data = $this->query($sql);
return $data;
}
And call this function like this way:
$employee = new Employee();
$data = $employee->get_employees();
In model you can't write model name. Its already detected. Use only
$this->find('all');
Assuming your statement is inside EmployeesController.php
$employeeRows = $this->employee->find('all', array('conditions'=>array('id' => 100)));
if you are in another controller, you have to load the model before the find
$this->loadModel('employee');
if you are in a view, you can write a helper and use raw sql
The cakephp website also offers the following controller logic
$this->Picture->query("SELECT * FROM pictures LIMIT 2;");