customers corresponds with one instance of the Customer class$todos = Todo::all();
print_r($todos);
echo $todos[0]->what;
$todo = new Todo();
$todo->what = 'Go lunching !!';
$todo->priority = 'high';
$todo->save();
print_r(Todo::all());
$todo->delete();
print_r(Todo::all());
public/slides/assets/02/examples/simple-mvc/01.php with a Todo classpublic/slides/assets/02/examples/simple-mvc/02.php with a generic Model classWHERE, GROUP BY, ...DB::table()get() returning a Collection of results
$users = DB::table('users')->get();
dump($users);
foreachforeach ($users as $user) {
echo $user->name;
}
select(), where() and groupBy()
$users = DB::table('users')
->select('name', 'email as user_email')
->where('status', '<>', 1)
->groupBy('status')
->get();
select(), where(), groupBy() return a Builder object
$where = DB::table('users')
->select('name', 'email as user_email')
->where('status', '<>', 1);
dump($where);
get() is the only method actually performing a query here !get() returns a collection of all matching rows (as you already know)first() returns a single row
$user = DB::table('users')->where('name', 'John')->first();
echo $user->name;
find() retrieves a single row by the specified value for the id column
$user = DB::table('users')->find(3);
value() returns a single value
$email = DB::table('users')->where('name', 'John')->value('email');
pluck() returns a Collection of custom keys and values
$events = DB::table('event')->pluck('name', 'id');
foreach ($events as $id => $name) {
…
count(), max()whereIn(), orWhere(); joins e.g. leftJoin(), on(); offset and limit with skip() and take(); chunking results with chunk() insert(), update() and delete()
$id = DB::table('users')->insertGetId(
['email' => 'john@example.com', 'votes' => 0]
);
DB::table('users')
->where('id', 1)
->update(['votes' => 1]);
DB::table('users')->increment('votes', 5);
DB::table('users')->where('votes', '<', 100)->delete();
DB::table('flights')->upsert([
['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
], ['departure', 'destination'], ['price']);
$ php artisan make:model Event
Event extending Illuminate\Database\Eloquent\Model in the app/Models/ directoryevents (! lowercase & eng. plural) in the database
app/Models/Event.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
//
}
app/Models/Event.php
events (plural!) in the database, unless you add
protected $table = 'my_other_table_name';
id, unless you add
protected $primaryKey = 'event_id';
public $incrementing = false;
protected $keyType = 'string';
created_at and updated_at columns, unless you add
public $timestamps = false;
protected $attributes = [
'delayed' => false,
];
all() returns all records in the table
use App\Models\Event;
foreach (Event::all() as $event) {
echo $event->name;
}
$events = Event::where('active', 1)
->orderBy('name', 'desc')
->take(10)
->get();
find() and first()
use App\Models\Event;
$event15 = Event::find(15); // retrieval by primary key
$activeEvent = Event::where('active', 1)->first(); // retrieve the first record
$activeEvent = Event::firstWhere('active', 1); // same
ModelNotFoundException when no result is found:
$event15 = Event::findOrFail(15);
$activeEvent = Event::where('active', 1)->firstOrFail();
404 HTTP response when not caught (!)all() and get() return an Eloquent Collection
use App\Models\Product;
$products = Product::all();
dump($products);
$products->count(), $products->pluck('name'), $products->where('name', 'Oneplus')
$products->find(1)
class Product extends Model) you generated with Artisan
$product = Product::find(1);
dump($product);
Event::all() // returns an Eloquent collection of Event objects
Event::find(15) // returns an Event object
Event::findOrFail(15) // returns an Event object
Event::count() // returns an integer
Event::where('active', 1)
Event::select('id', 'name')
$events = Event::where('capacity', '>', 315)->where('active', 1)->select('id', 'name')->orderBy('capacity', 'desc');
$events->get() // returns an Eloquent collection of Event objects
$events->count() // returns an integer
$events->first() // returns an Event object
$events->find(15) // returns an Event object
$events->value('name') // returns a value
$events->pluck('name') // returns an Eloquent collection of strings
use App\Models\Event;
$event = new Event;
$event->name = $request->name;
$event->save();
$event = Event::find(1);
$event->name = 'Pukkelpop 2024';
$event->save();
$event->delete();
Event::destroy(7);
$event = Event::where('name', 'Pukkelpop 2024')->first();
$freshEvent = $event->fresh(); // reload from DB and create new Event object
$event->price = 280;
$event->refresh(); // reload from DB and "re-hydrate" existing Event object
$event->price; // 200
$event = Event::where('name', 'Pukkelpop 2024')->first();
$event->price = 280;
$event->isDirty(); // true
$event->isDirty('price'); // true
$event->isDirty('name'); // false
$event->isDirty(['price', 'name']); // true
$event->isClean('price'); // false
$event->save();
$event->isDirty(); // false
$event->isClean(); // true
$user = User::create(['name' => 'Franky Pallemans', 'company' => 'Cynalco']); // does a DB INSERT
$user = User::create($request->all());
role=administrator which is passed to the create method
protected $guarded = ['role'];
protected $fillable = ['name', 'company']; → our choice
$user->role = 'administrator';
$user->save();
use App\Models\Event;
$event = new Event(['name' => 'Pukkelpop 2025']);
fill() on a model instance
$event = new Event;
$event->fill(['name' => 'Pukkelpop 2025']);
Event::where('price', '>', 300)->update(['active' => 0]);
// Retrieve the event by the attributes, or create it if it doesn't exist...
$event = Event::firstOrCreate(['name' => 'Dranouter 2024']);
// Retrieve the event by the attributes, or instantiate a new instance...
$event = Event::firstOrNew(['name' => 'Dranouter 2024']);
$event->save();
// If there's a matching event, set the price to $99.
// If no matching event exists, create one.
$event = Event::updateOrCreate(['name' => 'Dranouter 2024'], ['price' => 99]);
// Same for multiple rows? use Event::upsert()
user_id
$user = User::find(1);
foreach ($user->tasks as $task) {
echo $task->name;
}
User class: (! plural)
public function tasks(): HasMany
{
return $this->hasMany(Task::class);
}
Task class: (! singular)
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
$user->tasks
returns an Eloquent Collection of Task objects (data)
$user->tasks()
returns a (Query) Builder object Model class for the intermediate (= pivot) table
use Carbon\Carbon;
$events = Event::where('event_date', '<', new Carbon('yesterday 23:10'))->get();
class Event extends Model
{
protected function casts(): array
{
return [
'event_date' => 'datetime',
// you don't need to mention created_at and updated_at here!
];
}
}
$event->event_date = Carbon::now();$casts you can define many cast types in order to have your attributes auto-convertedphp artisan model:show Event
resources/views *Controller in the folder app/Http/Controllers
php artisan make:controller TaskController
/routes/web.php (or in /routes/api.php)
use App\Http\Controllers\TaskController;
Route::get('/tasks', [TaskController::class, 'index']);
Route::post('/tasks/create', [TaskController::class, 'store']);
Route::post('/tasks/{task}/delete', [TaskController::class, 'destroy'])->whereNumber('task');
*Controller
class TaskController extends Controller
{
public function index(Request $request): View
{
$tasks = Task::where('user_id', $request->input('user_id'))
->orderBy('created_at', 'asc')
->get();
return view('tasks.index', ['tasks' => $tasks]);
}
public function destroy(Request $request, string $id): RedirectResponse
class TaskController extends Controller
{
public function index(): View
{
return view('tasks.index');
}
id column
Route::post('/tasks/{task}/delete', [TaskController::class, 'destroy']);
class TaskController extends Controller
{
…
// Task $task: implicit model binding (on ID) + 404 on fail
public function destroy(Task $task): RedirectResponse
{
$task->delete();
return redirect('/tasks');
}
# start from an empty DB
# creates model + create_products_table migration + ProductSeeder + ProductController
$ php artisan make:model Product -msc
# migration contains: $table->id();
# migration contains: $table->timestamps();
# add to your migration: other columns
$ php artisan migrate
# add data to your seeder
$ php artisan db:seed --class=ProductSeeder
# add to your model: mass-assignable blacklist/whitelist and dates/times
# use App\Models\Product wherever you want for your DB operations from your ProductController
$fillable and all relationships ⟶ // retrieve product (data record) with ID 1
$product = Product::find(1);
dump($product->name);
dump($product->price);
// retrieve the product's brand (data record) through many-to-one
$brand = $product->brand;
dump('brand: ' . $brand->name);
// retrieve the product's categories (collection of data records) through many-to-many
$categories = $product->categories;
foreach ($categories as $category) {
dump('category: ' . $category->name);
}
// retrieve all products (collection of data records)
$products = Product::all();
dump('# products: ' . $products->count()); // count of collection
dump('# products: ' . Product::count()); // count in DB query (faster!)
// retrieve all products of brand 1
$productsOfBrandOne = Product::where('brand_id', 1)->orderBy('price', 'desc')->get();
dump('all products of brand 1 ---');
dump($productsOfBrandOne->pluck('name', 'id')); // pluck of collection
dump($productsOfBrandOne->pluck('name', 'id')->all()); // ... as a plain array
dump(Product::where('brand_id', 1)->orderBy('price', 'desc')->pluck('name', 'id')); // pluck integrated in DB query
// retrieve all products of category 2
dump('all products of category 2 ---');
$id = 2;
dump(Category::find($id)->products->pluck('name')); // v1: involves 2 DB queries (key in collection is 0 !)
dump(Category::find($id)->products()->pluck('name')); // v2: still 2 DB queries ...
// v3: involves only 1 DB query
$productsOfCategoryTwo = Product::whereHas('categories', function (Builder $query) use ($id) {
$query->where('id', $id);
})->get();
dump($productsOfCategoryTwo);
// v4: shorter, with whereRelation
dump(Product::whereRelation('categories', 'id', $id)->get());
// add a new product of brand 1
$brand1 = Brand::find(1);
$apple = new Product;
$apple->name = 'Jonagold';
$apple->description = 'Just a piece of fruit';
$apple->price = 0.85;
$apple->brand()->associate($brand1);
$apple->save();
// add another new product of brand 1 in one line
$brand1->products()->create(['name' => 'Pink Lady', 'description' => 'Just a piece of fruit', 'price' => 0.85]);
// yes ... you just saw a mass-assignment
// product checkup: find products without category or price 0.00
dump('faulty products ---');
$faultyProductsBuilder = Product::where('price', 0.00)->orDoesntHave('categories');
$faultyProductStrings = $faultyProductsBuilder->get()->map(function ($product) {
return $product->id . '. ' . $product->name . ' (' . $product->price . '€)';
});
dump($faultyProductStrings->all());
// Let's add both categories to the first faulty product
$faultyProductsBuilder->first()?->categories()->sync([1, 2]); // ?-> null-safe operator
// ... and delete all apples anyway
Product::where('price', 0.85)->delete();