Skip to content

Commit 96f3541

Browse files
author
github-ci
committed
update
1 parent 7d2b5c0 commit 96f3541

File tree

85 files changed

+3533
-1336
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+3533
-1336
lines changed

.github/workflows/composer-require-checker.yml

Lines changed: 0 additions & 41 deletions
This file was deleted.

.github/workflows/phpunit.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ jobs:
99
fail-fast: false
1010
matrix:
1111
php_version:
12-
- 8.1
1312
- 8.2
1413
- 8.3
1514
- 8.4

README.md

Lines changed: 167 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,106 @@
11
# AopBundle
22

33
[![Latest Version](https://img.shields.io/packagist/v/tourze/symfony-aop-bundle.svg?style=flat-square)](https://packagist.org/packages/tourze/symfony-aop-bundle)
4+
[![PHP Version](https://img.shields.io/packagist/php-v/tourze/symfony-aop-bundle.svg?style=flat-square)](https://packagist.org/packages/tourze/symfony-aop-bundle)
5+
[![License](https://img.shields.io/packagist/l/tourze/symfony-aop-bundle.svg?style=flat-square)](https://packagist.org/packages/tourze/symfony-aop-bundle)
6+
[![Build Status](https://img.shields.io/github/actions/workflow/status/tourze/php-monorepo/ci.yml?style=flat-square)](https://github.com/tourze/php-monorepo/actions)
7+
[![Coverage](https://img.shields.io/codecov/c/github/tourze/php-monorepo?style=flat-square)](https://codecov.io/gh/tourze/php-monorepo)
48

59
[English](README.md) | [中文](README.zh-CN.md)
610

11+
## Table of Contents
12+
13+
- [Overview](#overview)
14+
- [Requirements](#requirements)
15+
- [Installation](#installation)
16+
- [Quick Start](#quick-start)
17+
- [Features](#features)
18+
- [Basic Usage](#basic-usage)
19+
- [Advanced Usage](#advanced-usage)
20+
- [Performance Monitoring](#performance-monitoring)
21+
- [Best Practices](#best-practices)
22+
- [Configuration](#configuration)
23+
- [Contributing](#contributing)
24+
- [License](#license)
25+
726
## Overview
827

9-
AopBundle is a Symfony bundle that implements Aspect-Oriented Programming (AOP) using PHP 8's Attribute features. It enables adding cross-cutting concerns (like logging, caching, transactions) to your code without modifying the core logic.
28+
AopBundle is a Symfony bundle that implements Aspect-Oriented Programming (AOP) using PHP 8's
29+
Attribute features. It enables adding cross-cutting concerns (like logging, caching, transactions)
30+
to your code without modifying the core logic.
1031

1132
## Requirements
1233

1334
- PHP 8.1+
14-
- Symfony 6.4+
35+
- Symfony 7.3+
1536

1637
## Installation
1738

1839
```bash
1940
composer require tourze/symfony-aop-bundle
2041
```
2142

43+
## Quick Start
44+
45+
### Step 1: Install the Bundle
46+
47+
```bash
48+
composer require tourze/symfony-aop-bundle
49+
```
50+
51+
### Step 2: Create a Simple Aspect
52+
53+
Create a logging aspect in `src/Aspect/LoggingAspect.php`:
54+
55+
```php
56+
<?php
57+
58+
namespace App\Aspect;
59+
60+
use Psr\Log\LoggerInterface;
61+
use Tourze\Symfony\Aop\Attribute\Aspect;
62+
use Tourze\Symfony\Aop\Attribute\Before;
63+
use Tourze\Symfony\Aop\Model\JoinPoint;
64+
65+
#[Aspect]
66+
class LoggingAspect
67+
{
68+
public function __construct(
69+
private LoggerInterface $logger
70+
) {}
71+
72+
#[Before(serviceTags: ['app.loggable'])]
73+
public function logMethodExecution(JoinPoint $joinPoint): void
74+
{
75+
$this->logger->info('Method executed', [
76+
'class' => $joinPoint->getInstance()::class,
77+
'method' => $joinPoint->getMethod(),
78+
'params' => $joinPoint->getParams(),
79+
]);
80+
}
81+
}
82+
```
83+
84+
### Step 3: Tag Your Services
85+
86+
Tag services you want to log in `config/services.yaml`:
87+
88+
```yaml
89+
services:
90+
App\Service\UserService:
91+
tags:
92+
- { name: 'app.loggable' }
93+
```
94+
95+
### Step 4: Use Your Service
96+
97+
Now when you call methods on `UserService`, they will be automatically logged!
98+
99+
```php
100+
// This will trigger the logging aspect
101+
$userService->createUser($userData);
102+
```
103+
22104
## Features
23105

24106
- Define aspects using PHP 8 attributes
@@ -30,7 +112,7 @@ composer require tourze/symfony-aop-bundle
30112

31113
## Basic Usage
32114

33-
### 1. Define an Aspect
115+
### Define an Aspect
34116

35117
Create a class with the `#[Aspect]` attribute and define advice methods:
36118

@@ -54,15 +136,15 @@ class LoggingAspect
54136
}
55137
```
56138

57-
### 2. Available Advice Types
139+
### Available Advice Types
58140

59141
- `#[Before]` - Executed before the target method
60142
- `#[After]` - Executed after the target method (regardless of exceptions)
61143
- `#[AfterReturning]` - Executed after successful method return
62144
- `#[AfterThrowing]` - Executed when the target method throws an exception
63145
- `#[CatchException]` - Used for exception handling
64146

65-
### 3. JoinPoint
147+
### JoinPoint Context
66148

67149
The `JoinPoint` object provides context for the intercepted method:
68150

@@ -75,7 +157,7 @@ $joinPoint->getException(); // Exception (for exception advice)
75157
$joinPoint->proceed(); // Manually execute the original method
76158
```
77159

78-
### 4. Pointcut Expressions
160+
### Pointcut Expressions
79161

80162
Define where advice should be applied:
81163

@@ -99,7 +181,60 @@ Define where advice should be applied:
99181
#[Before('class.getName() === "App\\Service\\UserService"')]
100182
```
101183

102-
### 5. Performance Monitoring
184+
## Advanced Usage
185+
186+
### Exception Handling
187+
188+
Handle exceptions in your aspects:
189+
190+
```php
191+
#[Aspect]
192+
class ExceptionHandlingAspect
193+
{
194+
#[AfterThrowing(serviceTags: ['app.monitored'])]
195+
public function handleException(JoinPoint $joinPoint): void
196+
{
197+
$exception = $joinPoint->getException();
198+
199+
// Log the exception
200+
$this->logger->error('Method failed', [
201+
'exception' => $exception->getMessage(),
202+
'trace' => $exception->getTraceAsString(),
203+
]);
204+
205+
// Optionally transform or suppress the exception
206+
if ($exception instanceof RecoverableException) {
207+
$joinPoint->setReturnEarly(true);
208+
$joinPoint->setReturnValue(null);
209+
}
210+
}
211+
}
212+
```
213+
214+
### Method Interception
215+
216+
Completely control method execution:
217+
218+
```php
219+
#[Aspect]
220+
class CacheAspect
221+
{
222+
#[Before(methodAttribute: Cacheable::class)]
223+
public function cacheMethod(JoinPoint $joinPoint): void
224+
{
225+
$cacheKey = $this->generateCacheKey($joinPoint);
226+
227+
if ($this->cache->has($cacheKey)) {
228+
$joinPoint->setReturnEarly(true);
229+
$joinPoint->setReturnValue($this->cache->get($cacheKey));
230+
}
231+
}
232+
}
233+
```
234+
235+
## Performance Monitoring
236+
237+
Use the built-in Stopwatch attribute for performance monitoring:
103238

104239
```php
105240
use Tourze\Symfony\Aop\Attribute\Stopwatch;
@@ -116,32 +251,41 @@ class UserService
116251

117252
## Best Practices
118253

119-
1. **Keep aspects focused**
120-
- Each aspect should have a single responsibility
121-
- Avoid heavy operations in advice methods
254+
### Keep Aspects Focused
255+
256+
- Each aspect should have a single responsibility
257+
- Avoid heavy operations in advice methods
258+
- Use meaningful names for aspects and advice methods
259+
260+
### Advice Execution Order
261+
262+
- Before advice is executed in declaration order
263+
- After/AfterReturning/AfterThrowing advice is executed in reverse order
264+
- Consider the execution order when defining multiple aspects
265+
266+
### Performance Considerations
122267

123-
2. **Advice execution order**
124-
- Before advice is executed in declaration order
125-
- After/AfterReturning/AfterThrowing advice is executed in reverse order
268+
- Use AOP only when necessary
269+
- Consider the performance impact in production
270+
- Use Stopwatch to monitor method execution time
271+
- Avoid complex pointcut expressions in hot paths
126272

127-
3. **Performance considerations**
128-
- Use AOP only when necessary
129-
- Consider the performance impact in production
130-
- Use Stopwatch to monitor method execution time
273+
### Exception Handling
131274

132-
4. **Exception handling**
133-
- Be careful with exception handling in advice
134-
- Consider using AfterThrowing for exception logging
135-
- Use CatchException for controlled exception handling
275+
- Be careful with exception handling in advice
276+
- Consider using AfterThrowing for exception logging
277+
- Use CatchException for controlled exception handling
278+
- Test exception scenarios thoroughly
136279

137280
## Configuration
138281

139-
No additional configuration is required. The bundle automatically detects services with the `#[Aspect]` attribute and applies advice to matching services.
282+
No additional configuration is required. The bundle automatically detects services with the
283+
`#[Aspect]` attribute and applies advice to matching services.
140284

141285
## Contributing
142286

143287
Contributions are welcome. Please feel free to submit a Pull Request.
144288

145289
## License
146290

147-
This bundle is available under the MIT license. See the [LICENSE](LICENSE) file for more information.
291+
This bundle is available under the MIT license. See the [LICENSE](LICENSE) file for more information.

0 commit comments

Comments
 (0)